feat(agent-interface): agentCandidateLineageSchema accepts an agent-authored candidate - #290
feat(agent-interface): agentCandidateLineageSchema accepts an agent-authored candidate#290drewstone wants to merge 2 commits into
Conversation
…uthored candidate An agent that writes another agent's profile from inside a run had no source member. `spawn_worker` takes a full AgentProfile and `metadata.role: "driver"` promotes a child to a sub-supervisor, so the case is shipped, not hypothetical. `optimizer` was the closest member and its own refinement closed it: it mandates a `developmentSplitDigest`, and a run-time author has no held-out split. The only ways through were a fabricated digest or a `human` declaration, and both put a false statement into the evidence record. `agent-author` keeps the two requirements that make a generated lineage checkable — at least one parent, and the run that produced it — and drops the development split, which now applies to `optimizer` and `compound` only. The change is additive: every lineage that parsed before parses unchanged. The new test file also pins the existing optimizer, compound and duplicate rules, which had no direct coverage. Closes #289
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 84913516
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
This approval is provisional. It rests on the audit running. If the audit cannot run — for example the CLI bridge rejects it — this approval is dismissed rather than left standing, so an unrun check never reads as a passing one.
tangletools · auto-approval · reason: drewstone_author · 2026-09-02T03:50:58Z
tangletools
left a comment
There was a problem hiding this comment.
🟡 Value Audit — sound-with-nits
| Verdict | sound-with-nits |
| Coverage | 2 of 2 lenses (value, usefulness) |
| Concerns | 4 (1 medium-concern, 3 weak-concern) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 311.6s (2 bridge agents) |
| Total | 311.6s |
💰 Value — sound-with-nits
Adds an agent-author source to AgentCandidateLineage so a profile one agent writes for another inside a run (spawn_worker/driver promotion) is representable without fabricating a development-split digest; correct and additive, with one naming-consistency nit.
- What it does: Widens the
AgentCandidateLineage.sourceenum fromoptimizer|human|import|compoundto addagent-author(agent-candidate.ts:394, agent-candidate-lineage-schema.ts:50-56). It groupsagent-authorwithoptimizer/compoundfor the parent + producing-run requirements (agent-candidate-lineage-schema.ts:81-100) but drops thedevelopmentSplitDigestrequirement, which now applies only to `optimi - Goals it achieves: Gives a shipped capability (a supervising agent authoring a child's full
AgentProfilefrom inside a run) a truthful lineage source, instead of forcing producers to either fabricate adevelopmentSplitDigestor falsely declarehuman/optimizerin the immutable evidence record. Keeps agent-authored lineages checkable via the two requirements that survive without a held-out set: at least one pa - Assessment: Sound on its merits. It is genuinely additive (every lineage that parsed before parses unchanged; existing generated sources keep every rule), the refinement split is exactly the right cut — parent/run are inherent to any generated lineage while the development split is specific to offline search — and the code comment cleanly documents why the field is optional for this member. The experiment-bas
- Better / existing approach: The mechanism (add an enum member + narrow one refinement) is right; no existing capability is duplicated. But the codebase already has a parallel source-kind enum for the same actors —
AgentProfileDiff.source.kind(profile-diff.ts:94-100, profile-schema.ts:547-555) includesfrontier-author, a documented case of an agent authoring a profile change from a session trace (profile-diff.test.ts:474 - Model: opencode/deepseek/deepseek-v4-pro
- Bridge attempts: 3
- Bridge warning: opencode/kimi-for-coding/k2p7: opencode: opencode error event without a message: {"type":"error","timestamp":1788321206226,"sessionID":"ses_f9fbff364ffeZKPzXQMjKlV2U6","error":{"name":"UnknownError","data":{"message":"Unexpected server error. Check server logs for details.","ref":"err_9a75a6bb"}}}; opencode/zai-coding-plan/glm-5.2: opencode: opencode error event without a message: {"type":"error",
🎯 Usefulness — sound-with-nits
An additive, correctly-scoped widening of the lineage source enum so an agent-authored profile can be recorded truthfully instead of faking a human or optimizer declaration; the only gaps are that the two downstream experiment schemas were left gating on the old source set, leaving `agent-author
- Integration: Reachable.
agentCandidateLineageSchemais imported and used by bothagent-candidate-promotion-schema.ts:47andagent-profile-improvement-schema.ts:222, so the new member flows through every path that admits a lineage. There is no in-repo producer emittingsource: "agent-author"yet (the runtimespawn_workertool is out-of-repo), but the motivating capability is real in-repo: `metadata.ro - Fit with existing patterns: Fits the codebase grain: it extends the existing
z.enum+superRefinestructure inagent-candidate-lineage-schema.tsrather than introducing a parallel mechanism, and the two experiment schemas already branch onsource === "optimizer" || source === "compound", so the change is additive and every previously-parsing lineage parses unchanged. Minor vocabulary drift: `AgentProfileDiff.source.k - Real-world viability: Robust for the happy path and the edge cases it pins: empty parent/run lists are refused (
agent-candidate-lineage-schema.ts:81-99), duplicate ancestry entries are refused (viaaddDuplicateIssues, tested), self-reference is blocked by the source-agnostic check in both experiment schemas (agent-candidate-promotion-schema.ts:65,agent-profile-improvement-schema.ts:254), and the development-sp - Model: opencode/deepseek/deepseek-v4-pro
- Bridge attempts: 3
- Bridge warning: opencode/zai-coding-plan/glm-5.2: opencode: opencode error event without a message: {"type":"error","timestamp":1788321276371,"sessionID":"ses_f9fbff288ffeLPvqUKyt5of7W5","error":{"name":"APIError","data":{"message":"Usage limit reached for 5 hour. Your limit will reset at 2026-09-02 12:05:20","statusCode":429,"isRetryable":true,"responseHeaders":{"alt-svc":"h3=":443"; ma=3600","connection":"kee
💰 Value Audit
🟠 agent-author duplicates the existing frontier-author source concept under a new name [against-grain] ``
Two parallel source-kind enums already overlap on
human|optimizer|compoundand now diverge on the agent-authored member:AgentProfileDiff.source.kindnames itfrontier-author(profile-diff.ts:97, profile-schema.ts:551, exercised at profile-diff.test.ts:474-498), while this PR mintsagent-authorinAgentCandidateLineage.source(agent-candidate.ts:394). They describe the same actor (a non-optimizer agent authoring a profile from inside a run, with a trace/session and no held-out split).
🟡 developmentSplitDigest doc comment is now slightly stale [maintenance] ``
agent-candidate.ts:399 still reads 'Exact development split used to produce a generated candidate', but
agent-authoris a generated candidate (it requires parent + run) that carries no development split. Adjust to note the field applies only to optimizer/compound, matching the new code comment in the schema.
🎯 Usefulness Audit
🟡 agent-author skips the 'parent must include baseline' invariant in both experiment schemas [integration] ``
agent-candidate-promotion-schema.ts:56andagent-profile-improvement-schema.ts:245gate the generated-lineage baseline-parent check onsource === "optimizer" || source === "compound"and were not extended toagent-author. Result: anagent-authorexperiment passes even whenparentDigestsomitsbaseline.digest/baseline.stateDigest, disconnecting the candidate from the state it was measured against. This may be intended (agent-author's parent is its predecessor, not the baseline), b
🟡 agent-author overlaps the existing frontier-author authorship vocabulary [problem-fit] ``
AgentProfileDiff.source.kindalready has afrontier-authormember (profile-diff.ts:97-100,profile-schema.ts:549-555) for agent-authored diffs. The lineage enum now getsagent-authorfor a closely related concept. They are distinct enums for distinct documents, so there is no functional duplication, but two names for 'an agent wrote this' invites confusion. Recommend either naming the new member consistently with the existing term or documenting (as the added comment partially does) wh
What this audit checks
It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.
| Pass | What it asks |
|---|---|
| Heuristic | Vague title? Whitespace-only or cruft-bearing diff? (content signals only) |
| Duplication | Do added function/class names already exist elsewhere in the repo? |
| Value Audit | What does it do? What goal does it achieve? Is it good? Better architecture or already-exists? |
| Usefulness Audit | Does it integrate and fit? Will it hold up in real use and actually get used? |
Findings are concerns, not blocks — the human reviewer decides what to do with them.
✅ No Blockers —
|
| opencode DeepSeek v4 Pro | opencode DeepSeek v4 Flash | aggregate | |
|---|---|---|---|
| Readiness | 92 | 79 | 79 |
| Confidence | 70 | 70 | 70 |
| Correctness | 92 | 79 | 79 |
| Security | 92 | 79 | 79 |
| Testing | 92 | 79 | 79 |
| Architecture | 92 | 79 | 79 |
Reviewer score is advisory once the run is complete and the verdict has no blockers.
Full multi-shot audit completed 2/2 planned shots over 4 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 2/2 planned shots over 4 changed files. Global verifier still owns final merge decision.
🟠 MEDIUM agent-author bypasses the experiment baseline-binding invariant in both downstream experiment schemas — packages/agent-interface/src/agent-candidate-lineage-schema.ts
agentCandidateExperimentSchema (agent-candidate-promotion-schema.ts:54-64) and agentProfileImprovementExperimentSchema (agent-profile-improvement-schema.ts:243-253) consume agentCandidateLineageSchema directly and enforce 'generated candidate lineage must include the experiment baseline' only when source is 'optimizer' or 'compound'. Adding 'agent-author' to the shared enum makes it a valid source in both experiment documents, where the parentDigests baseline check is skipped: an experiment can parse with source 'agent-author' and a parentDigest unrelated to baseline.digest/stateDigest. The PR's own rationale keeps 'agent-author' under optimizer's parent-and-run requirements, so the parent-of-baseline invariant was plausibly meant to hold here too. Fix: bind agent-author in the two experim
🟡 LOW Cross-schema consumers of lineage.source not addressed in changeset — .changeset/agent-author-lineage.md
Sibling schemas agent-profile-improvement-schema.ts:222 and agent-candidate-promotion-schema.ts:47 embed agentCandidateLineageSchema and also branch on (source === 'optimizer' || source === 'compound') in their own refinements (verified via grep). Whether those branches must also cover 'agent-author' is outside this shot's changed files, but the changeset's assertion of full additivity should be cross-checked by the shot covering those files. Non-blocking for this document; noted for the global verifier.
🟡 LOW agent-author may still declare a developmentSplitDigest, permitting the fabricated-digest claim the change exists to prevent — packages/agent-interface/src/agent-candidate-lineage-schema.ts
developmentSplitDigest is an optional base-schema field and the refinement (lines 105-113) requires it for optimizer/compound but never forbids it for agent-author. The doc comment in agent-candidate.ts:390-392 states an agent-author 'has no held-out split'; allowing the field means an agent-author lineage can carry a made-up sha256 split, reintroducing the exact fabrication the PR removes from optimizer. It is only caught downstream when it happens to equal a benchmark split (agent-candidate-promotion-schema.ts:72-79). Fix: in the agent-author branch, reject a present developmentSplitDigest with a custom issue. Low severity b
🟡 LOW agent-author treated as generated here but not in experiment baseline-binding — packages/agent-interface/src/agent-candidate-lineage-schema.ts
agentCandidateLineageSchema now requires parentDigests and runIds for source
agent-author(lines 81-99), classifying it as a generated lineage. But the two consumers that validate a full measured experiment still gate the 'generated lineage must name the experiment baseline as a parent' rule to optimizer/compound only: agent-candidate-promotion-schema.ts:56 and agent-profile-improvement-schema.ts:245 both test(source === "optimizer" || source === "compound"). AgentCandidateLineage is embedded in both experiment types (agent-candidate.ts:656 and agent-profile-improvement.ts:90), so anagent-authorlineage is type-legal ins
tangletools · 2026-09-02T03:58:39Z · trace
tangletools
left a comment
There was a problem hiding this comment.
✅ Approved — 4 non-blocking findings — 84913516
Full multi-shot audit completed 2/2 planned shots over 4 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 2/2 planned shots over 4 changed files. Global verifier still owns final merge decision.
Full immutable report for this review: trace
Summary comment for this run: full summary
tangletools · 2026-09-02T03:58:39Z · immutable trace
…ate on it once Two findings from the review of #290, both real. NAMING. `AgentProfileDiff.source.kind` already ships `frontier-author` for an agent that wrote a profile change. Minting `agent-author` beside it gave one actor two words across two parallel enums. The lineage member is now `frontier-author`, and both declarations say they name the same thing. GATING. Three call sites branched on `source === "optimizer" || source === "compound"` independently: the lineage refinement, `agentCandidateExperimentSchema` and `agentProfileImprovementExperimentSchema`. Adding a fourth generated source therefore exempted it from the "generated lineage must include the experiment baseline" rule in the two experiment schemas, silently. `generatedCandidateSources` and `isGeneratedCandidateSource` are now the single owner of that set and all three read it. The development split stays required by `optimizer` and `compound` only — that branch is deliberately not the generated-source list. The new test derives the set from the schema rather than restating it: it asks every enum member whether the schema makes it name a parent, and requires the answer to equal `generatedCandidateSources`. 520 tests pass; `tsc --noEmit` clean on source and tests.
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — b0a4b289
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
This approval is provisional. It rests on the audit running. If the audit cannot run — for example the CLI bridge rejects it — this approval is dismissed rather than left standing, so an unrun check never reads as a passing one.
tangletools · auto-approval · reason: drewstone_author · 2026-09-02T04:26:37Z
tangletools
left a comment
There was a problem hiding this comment.
🟢 Value Audit — sound
| Verdict | sound |
| Coverage | 2 of 2 lenses (value, usefulness) |
| Concerns | 1 (1 weak-concern) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 223.3s (2 bridge agents) |
| Total | 223.3s |
💰 Value — sound
Adds a frontier-author provenance member for profiles an agent authors at runtime, and consolidates three duplicated optimizer || compound gates into one exported list — additive, in-grain, and it reuses the enum term the codebase already ships for this actor.
- What it does: Extends
AgentCandidateLineage.source(type at packages/agent-interface/src/agent-candidate.ts:397, schema at packages/agent-interface/src/agent-candidate-lineage-schema.ts:69-75) withfrontier-author: a candidate one agent wrote for another from inside a run. It inherits the two checkability requirements of generated sources — at least oneparentDigestsentry and a producingrunIdsentry ( - Goals it achieves: Truthful evidence records for a shipped capability. A supervising agent authoring a child's full AgentProfile at runtime (the
metadata.role: "driver"pattern already exercised at agent-execution-preparation.test.ts:139 and agent-profile-improvement-schema.test.ts:675;spawn_workerlives in the external discovery-lab consumer) previously had no honest enum member:optimizer's refinement deman - Assessment: Good on its merits. The design separates two concepts that were previously conflated in one branch: "produced from a parent" (the generated-source list) and "produced by offline search" (the dev-split branch), with a comment explaining why the second is deliberately not the first (agent-candidate-lineage-schema.ts:116-120). It reuses the exact vocabulary the codebase already ships for this actor —
- Better / existing approach: none — this is the right approach. Searched: (a) grep for
frontier-author— already exists only in the profile-diff actor enum, which this change aligns with rather than duplicates; lineage provenance and diff authorship are distinct schemas that now share one word, the right amount of reuse. (b) A discriminated union onsourcemakingdevelopmentSplitDigestrequired at the type level for opt - Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 2
- Bridge warning: opencode/kimi-for-coding/k2p7: opencode: opencode error event without a message: {"type":"error","timestamp":1788323246534,"sessionID":"ses_f9fa0d1aaffeUnoA8eikvXLitw","error":{"name":"UnknownError","data":{"message":"Unexpected server error. Check server logs for details.","ref":"err_b839bbf2"}}}
🎯 Usefulness — sound
A vocabulary-unifying, additive enum member that unblocks a real, already-shipped capability and removes a live fabricated-evidence workaround in an external consumer, with the branching logic consolidated into one shared owner.
- Integration: Fully wired and reachable. The new member enters at agent-candidate-lineage-schema.ts:69-75, flows into both experiment schemas that embed the lineage schema (agent-candidate-promotion-schema.ts:50, agent-profile-improvement-schema.ts:225), and reaches the public package surface via the re-export chain agent-candidate-schema.ts:135 -> index.ts:88. Grep for
source === "optimizer"and `candidateLi - Fit with existing patterns: Fits the codebase grain precisely.
frontier-authoris not a new word — it is the exact member the sibling enumAgentProfileDiff.source.kindalready carries (profile-schema.ts:549-555, pre-existing), so the PR unifies vocabulary instead of inventing a synonym (the PR title'sagent-authorwas rightly not what landed). Consolidating three independentoptimizer || compoundbranches into one ex - Real-world viability: Holds up beyond the happy path. The change is strictly additive: the enum widened, refinement rules for
optimizer/compoundare byte-identical in effect, and the new test pins both the old sources' requirements and the set-derivation (needsSplit === ["optimizer","compound"]) so a future source cannot silently dodge a rule. The self-declaration concern (a producer labeling offline search as `fro - Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
💰 Value Audit
🟡 Stale error message: dev-split issue still says "generated candidates must pin their development split" [maintenance] ``
After the split at packages/agent-interface/src/agent-candidate-lineage-schema.ts:121-129, the issue message at line 126 reads "generated candidates must pin their development split", but
frontier-authorlineages are also generated and correctly do not pin one. The message now over-claims; "optimizer and compound candidates must pin their development split" (or "offline-search candidates...") would match the actual rule. Cosmetic — the rule itself and the tests pinning it (agent-candidate-line
What this audit checks
It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.
| Pass | What it asks |
|---|---|
| Heuristic | Vague title? Whitespace-only or cruft-bearing diff? (content signals only) |
| Duplication | Do added function/class names already exist elsewhere in the repo? |
| Value Audit | What does it do? What goal does it achieve? Is it good? Better architecture or already-exists? |
| Usefulness Audit | Does it integrate and fit? Will it hold up in real use and actually get used? |
Findings are concerns, not blocks — the human reviewer decides what to do with them.
✅ No Blockers —
|
| opencode GLM 5.2 | opencode DeepSeek v4 Pro | opencode DeepSeek v4 Flash | aggregate | |
|---|---|---|---|---|
| Readiness | 83 | 89 | 89 | 83 |
| Confidence | 70 | 70 | 70 | 70 |
| Correctness | 83 | 89 | 89 | 83 |
| Security | 83 | 89 | 89 | 83 |
| Testing | 83 | 89 | 89 | 83 |
| Architecture | 83 | 89 | 89 | 83 |
Reviewer score is advisory once the run is complete and the verdict has no blockers.
Full multi-shot audit completed 2/2 planned shots over 7 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 2/2 planned shots over 7 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 2/2 planned shots over 7 changed files. Global verifier still owns final merge decision.
🟡 LOW Enum widening shipped as minor is source-breaking for exhaustive-switch consumers — .changeset/agent-author-lineage.md
The changeset declares minor, but the change widens the exported AgentCandidateLineage['source'] union (agent-candidate.ts:384). A downstream consumer that switches exhaustively over
sourcewith no default breaks at compile time after upgrade, which strict semver would call major. This matches the repo's established additive-as-minor convention (2.2.0, 2.3.0) and runtime parsing is genuinely additive, so minor is defensible; consider one sentence in the release notes flagging the widened union for exhaustive-switch callers. No change required to merge.
🟡 LOW 'generated-source list == schema' invariant test is tautological — packages/agent-interface/src/agent-candidate-lineage-schema.test.ts
The test derives needsParent from agentCandidateLineageSchema, whose parent requirement is implemented as isGeneratedCandidateSource(lineage.source) — the same list under test (agent-candidate-lineage-schema.ts:100). needsParent therefore equals generatedCandidateSources by construction, and a 6th enum member omitted from the list would leave the assertion green, reproducing the silent exemption this PR fixes. Every source value is also hardcoded in everySource. Strengthen with an independent expectation (literal expected generated set) so a future enum addition must consciously update the classification. Suggest a concrete fix; low risk today.
🟡 LOW Drift-guard meta-test hardcodes the enum it claims to guard — packages/agent-interface/src/agent-candidate-lineage-schema.test.ts
everySourceis a manually written third runtime copy of the five-member source list (after the z.enum literal and, separately, the TS union). A fifth source added to the zod enum but not toeverySourcesilently escapes the meta-test — the same drift class the PR eliminates. The type/schema pair is compiler-synced viasatisfies z.ZodType<AgentCandidateLineage>, but the test list is unenforced. Fix: export one runtimeagentCandidateLineageSourcesconst, type the TS union as(typeof agentCandidateLineageSources)[number], feed it toz.enum(...), and deriveeverySourcefrom it in the test.
🟡 LOW Experiment-level 'name your baseline' gate untested for frontier-author — packages/agent-interface/src/agent-candidate-lineage-schema.test.ts
The new tests cover the lineage schema itself but not the two call sites this PR rewires. agent-candidate-promotion-schema.test.ts (12 tests, lines 58-235) exercises only activation/activation-result schemas — the baseline-in-parentDigests rule at agent-candidate-promotion-schema.ts:59 has no test for optimizer, compound, or the new frontier-author. agent-profile-improvement-schema.test.ts:126 builds the optimizer happy path only. Add one test per experiment schema asserting a frontier-author lineage WITHOUT the baseline digest in parentDigests is rejected (and that including it passes); this is the exact behavior the chan
🟡 LOW frontier-author candidates carry no development-split evidence by design — packages/agent-interface/src/agent-candidate-lineage-schema.ts
Informational, documented tradeoff: a frontier-authored candidate can enter a measured comparison without any pinned train/test split, unlike optimizer/compound. The inline comment and changeset argue this is inherent (a run-time author has no held-out set) and the disjointness checks in both experiment schemas still fire when a split is supplied voluntarily, so no hole opens for existing sources. No action required; flagged so the evidence-weakening is a visible decision rather than an accident.
🟡 LOW frontier-author exempts development-split leak guard by self-reported source — packages/agent-interface/src/agent-candidate-lineage-schema.ts
The developmentSplitDigest requirement is deliberately kept as
optimizer || compound(line 121), so a frontier-author lineage may carry no development split. The disjoint-split leak checks in the two experiment schemas (promotion-schema.ts:76-88, profile-improvement-schema.ts:264-273) only fire when developmentSplitDigest is present, so a frontier-author candidate never proves its dev split is disjoint from the held-out eval split. This is the documented intent (an agent authoring a profile inside a run has no held-out split), and the source field is self-reported metadata throughout this schema (human/import also require no spli
🟡 LOW Experiment-schema baseline gate for frontier-author is untested — packages/agent-interface/src/agent-candidate-promotion-schema.ts
The gate changed from
source === "optimizer" || source === "compound"toisGeneratedCandidateSource(source)here and at agent-profile-improvement-schema.ts:248, but no test file imports either experiment schema (verified by grep). The refactor's own motivation — a new generated source silently skipping the 'name your baseline' rule — is exactly the behavior nothing pins at these two sites; the meta-test only guards the helper against the lineage schema, not against a future caller bypassing the helper. Fix: add one negative test per schema (frontier-author experiment whose parentDigests omit the baseline digest must fail with the 'generated candidate lineage must include the experiment baseline' issue).
🟡 LOW Comment overstates enum equivalence — packages/agent-interface/src/agent-candidate.ts
The doc says frontier-author is 'the same member AgentProfileDiff.source.kind already carries, so the two enums name one actor with one word.' That is accurate for the frontier-author member, but the two source enums are not identical sets: AgentProfileDiff.source.kind is {trace, frontier-author, human, optimizer, compound} (profile-diff.ts:100-105, profile-schema.ts:549-555) while AgentCandidateLineage.source is {optimizer, human, import, compound, frontier-author} (line 397). 'trace' vs 'import' diverge. Not a logic bug — only a documentation precision nit; a reader could infer the enums must stay in lockstep when they actually track different
tangletools · 2026-09-02T04:31:27Z · trace
tangletools
left a comment
There was a problem hiding this comment.
✅ Approved — 8 non-blocking findings — b0a4b289
Full multi-shot audit completed 2/2 planned shots over 7 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 2/2 planned shots over 7 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 2/2 planned shots over 7 changed files. Global verifier still owns final merge decision.
Full immutable report for this review: trace
Summary comment for this run: full summary
tangletools · 2026-09-02T04:31:27Z · immutable trace
Closes #289.
The gap
agentCandidateLineageSchema.sourceisoptimizer | human | import | compound. None of those describes a profile that one agent wrote for another from inside a run — a shipped capability:spawn_workertakes a fullAgentProfile, andmetadata.role: "driver"promotes that child to a sub-supervisor.optimizeris the closest member and its own refinement closes it:A run-time author has no development split. There is no held-out set and no offline search — a supervising agent read its own evidence and wrote a profile. The only ways through were a fabricated digest or a
humandeclaration, and both put a false statement into the evidence record.The change
agent-authorjoins the enum. It keeps the two requirements that make a generated lineage checkable — at least one parent, and the run that produced it — and drops the development split, which now applies tooptimizerandcompoundonly.Additive: every lineage that parsed before parses unchanged, and the two existing generated sources keep every rule they had.
Coverage
agent-candidate-lineage-schema.test.tsis new. The refinements in this file had no direct tests, so it pins all of them: the hand-written case with no ancestry,optimizer's three requirements,compound's two-distinct-parents rule, the duplicate-entry refusal, and the new member both ways — accepted without a development split, still refused without a parent and a run.pnpm --filter @tangle-network/agent-interface test: 40 files, 518 tests, all passing.tsc --noEmitandtsc --noEmit -p tsconfig.test.jsonclean.The consumer
discovery-lab keeps permanent, identifiable agents per problem area: an agent is
<role>/<area>, its record is append-only, and successive versions link to their predecessor throughdiffAgentProfiles/applyAgentProfileDiff. The record already uses this schema's field names verbatim —parentDigests,runIds,profileDiffIds— and today reports the refusal on every one of its 68 version rows rather than faking a member that would pass. It pins the current refusal as a kill test, so when this merges that test goes red and the record starts parsing through the schema with no migration.🤖 Generated with Claude Code