feat(candidate): compile full improvement bundles#514
Conversation
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — bbbddddb
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.
tangletools · auto-approval · reason: drewstone_author · 2026-07-11T17:39:55Z
tangletools
left a comment
There was a problem hiding this comment.
🟡 Value Audit — sound-with-nits
| Verdict | sound-with-nits |
| Concerns | 2 (2 weak-concern) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 150.9s (2 bridge agents) |
| Total | 150.9s |
💰 Value — sound
Adds the canonical buildAgentCandidateBundle so products no longer hand-roll profile-freezing + CodeSurface-byte-verification + diff-id derivation to produce a sealed candidate bundle; fills a real gap in the existing sealer/verifier pair, no existing equivalent found.
- What it does: Introduces
buildAgentCandidateBundle(input)insrc/candidate-execution/builder.ts— the one public constructor that takes high-level inputs (a typed profile source = full profile | profile-diffs | pre-closed candidate profile; a code source = CodeSurface | disabled | no-op; execution policy; optional knowledge; memory policy; lineage) and compiles them into a schema-validated, canonically-dige - Goals it achieves: Before this PR the runtime exposed only
sealAgentCandidateBundle(digest+schema validation on an already-assembled wire shape, bundle.ts:10) andverifyAgentCandidateBundle(execution-boundary re-verification, verify.ts:37). Every product had to hand-assembleAgentCandidateBundleInputthemselves — reproducing the profile-freezing rules, Git-diff byte hashing, and diff-id derivation, each with - Assessment: Sound and in the grain of the codebase. It composes with the existing primitives rather than reinventing them: uses
sealAgentCandidateBundle(bundle.ts),canonicalCandidateDigest/embeddedCandidateArtifact/canonicalCandidateBytes(digest.ts),verifyCodeSurfacefrom agent-eval, and theagentProfileSchema/agentCandidateProfileSchema/applyAgentProfileDifffrom agent-interface. The thre - Better / existing approach: Searched src/ for any existing profile→candidate-profile mapping, CodeSurface-to-bundle assembly, or
AgentCandidateBundleInputconstructor. Found only the inverse:candidateProfileAsAgentProfilein improvement-cycle.ts:324 (candidate→generic, used for round-trip binding verification).lifecycle/tool-build.ts:verifiedBuildbuilds a different shape (BuiltCandidatefor tool generation, not `A - Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 2
- Bridge warning: opencode/kimi-for-coding/k2p7: bridge stream ended without value-audit content
🎯 Usefulness — sound-with-nits
Adds the canonical high-level builder that compiles typed profiles/diffs + verified CodeSurface bytes + knowledge + memory into a sealed AgentCandidateBundle, composing (not competing with) the existing low-level sealAgentCandidateBundle and filling the gap that the intelligence improvement-cycle's
- Integration: Reachable and wired. Exported from src/candidate-execution/index.ts:1-11 on the ./candidate-execution package subpath (package.json:67-70), and exercised end-to-end by scripts/verify-package-exports.mjs which imports, calls buildAgentCandidateBundle, and verifies the result. It wraps sealAgentCandidateBundle (bundle.ts:10), which is already consumed by the live intelligence path at src/intelligenc
- Fit with existing patterns: Fits the codebase's grain precisely. It composes established primitives rather than inventing new ones: sealAgentCandidateBundle + embeddedCandidateArtifact + canonicalCandidateDigest from digest.ts, verifyCodeSurface from @tangle-network/agent-eval/campaign, and agentProfileSchema/agentProfileDiffSchema/agentCandidateProfileSchema/applyAgentProfileDiff from agent-interface. It does not compete wi
- Real-world viability: Holds up past the happy path. It is synchronous and deterministic; CodeSurface bytes are re-read and verified via verifyCodeSurface before embedding, with an explicit drift check (builder.ts:149-156). assertCanonicalParse (builder.ts:304-308) round-trips every parsed object against its canonical bytes so no unsupported field is silently dropped. The test file covers the realistic failure modes: di
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
🎯 Usefulness Audit
🟡 Builder returns sealed bundle but the buildCandidate seam expects unsealed input [ergonomics] ``
buildAgentCandidateBundle returns AgentCandidateBundle (digest included, deeply frozen), but src/intelligence/improvement-cycle.ts:115-118's buildCandidate callback signature is () => AgentCandidateBundleInput | Promise (digest omitted). A caller who wants to use the new canonical builder inside the improvement cycle must wrap it: omitTopLevelDigest(buildAgentCandidateBundle(...)). The cycle re-seals the result anyway (improvement-cycle.ts:173), so it is functionally f
💰 Value Audit
🟡 Forward and inverse profile mappings now live in different modules with parallel field lists [maintenance] ``
freezeGenericProfile(builder.ts:167-217, generic→candidate) andcandidateProfileAsAgentProfile(improvement-cycle.ts:324-406, candidate→generic) are inverse mappings that each hardcode the same top-level field list (name/description/version/tags/prompt/harness/permissions/tools/confidential) and parallel MCP/resource handling. They are not duplicates — the freeze is stricter (rejects hooks-with-commands, github resources, non-stdio MCP) while the unfreeze shell-quotes hooks — so both are ge
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.
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 12346649
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.
tangletools · auto-approval · reason: drewstone_author · 2026-07-11T17:53:40Z
tangletools
left a comment
There was a problem hiding this comment.
🟢 Value Audit — sound
| Verdict | sound |
| Concerns | 1 (1 weak-concern) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 106.2s (2 bridge agents) |
| Total | 106.2s |
💰 Value — sound
Adds a canonical, fail-closed public builder for sealed agent candidate bundles, extracting profile-freezing logic from improvement-cycle.ts into the candidate-execution package where it belongs — coherent and in-grain.
- What it does: Introduces
buildAgentCandidateBundle(src/candidate-execution/builder.ts:80), the single public entry point that compiles typed profile sources (profile / profile-diffs / candidate-profile), code sources (disabled / no-op / code-surface with byte-verified CodeSurface), execution policy, optional knowledge, and memory into an immutable, schema-validated, canonically-digested AgentCandidateBundle. - Goals it achieves: 1) Make bundle construction safe-by-construction: the only path from an agent-eval CodeSurface to embedded patch bytes goes through
verifyCodeSurface(builder.ts:146), eliminating the possibility of sealing unverified or drifted code. 2) Centralize profile freezing so both the improvement cycle and external consumers share one implementation rather than each adapter reimplementing the AgentProfi - Assessment: Good change, built in the grain of the codebase. The profile-freezing logic was already in the repo (inlined in improvement-cycle.ts at main, 506 lines) and is moved — not copied — to candidate-execution/profile.ts, which is the correct layer (the improvement cycle is a consumer of candidate-execution, not its owner). The builder fills a genuine gap: before this, the only public constructor was `s
- Better / existing approach: none — this is the right approach. Searched for existing equivalents: (1)
sealAgentCandidateBundlein bundle.ts is the low-level sealer this builder wraps — correct to keep, not duplicate. (2)lifecycle/tool-build.tsconsumesCodeSurfacebut for a different purpose (building tools/MCP servers in worktrees viaworktreeBuildCandidate, not sealing execution bundles) — not the same concern. (3 - Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 2
- Bridge warning: opencode/kimi-for-coding/k2p7: bridge stream ended without value-audit content
🎯 Usefulness — sound
Promotes the profile-freezing and bundle-building logic from a private inline helper inside the intelligence module into a canonical, exported public builder in candidate-execution — the logic was already live, this just surfaces it as the blessed product entry point and removes the duplication.
- Integration: Fully reachable.
buildAgentCandidateBundleis consumed by thebuildCandidatecallback inproposeAgentImprovement(src/intelligence/improvement-cycle.ts:174-177), which also widens its callback type to accept the sealedAgentCandidateBundlereturn. The profile helpers (assertCandidateProfileBinding,parseExactAgentProfile) are imported and called by the live improvement-cycle at improve - Fit with existing patterns: Fits the codebase grain precisely. This is a de-duplication, not a competing pattern: the diff vs origin/main shows src/intelligence/improvement-cycle.ts loses ~175 lines of inline
freezeGenericAgentCandidateProfile/freezeResources/freezeMcpServers/shellQuote/candidateProfileAsAgentProfilehelpers that now live in src/candidate-execution/profile.ts. The builder reuses the pre-existing ca - Real-world viability: Holds up off the happy path. The builder is deliberately fail-closed: it rejects caller-supplied
profileDiffIds(builder.ts:83), empty diff lists (builder.ts:125), non-canonical schema parses (builder.ts:170), CodeSurface byte drift between verified bytes and the surface's content identity (builder.ts:148-153), and every generic-profile field that cannot be safely tokenized — connections/metadat - Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
💰 Value Audit
🟡 omitUndefinedObjectFields (builder.ts:176) and canonicalJsonValue (improvement-cycle.ts:362) overlap in purpose [maintenance] ``
Both recursively strip undefined fields from objects/arrays. builder.ts:176
omitUndefinedObjectFieldscleansapplyAgentProfileDiffoutput; improvement-cycle.ts:362canonicalJsonValuedoes the same plus type validation for proposal serialization. Neither calls the other. If a third consumer appears, these should fold into one shared helper in digest.ts or a canonical-serialize utility. Not blocking — they serve slightly different contracts (one throws on undefined array entries, the other i
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.
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 2e6eb28b
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.
tangletools · auto-approval · reason: drewstone_author · 2026-07-11T17:58:20Z
tangletools
left a comment
There was a problem hiding this comment.
🟡 Value Audit — sound-with-nits
| Verdict | sound-with-nits |
| Concerns | 1 (1 weak-concern) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 168.4s (2 bridge agents) |
| Total | 168.4s |
💰 Value — sound-with-nits
Adds a canonical fail-closed builder that compiles profiles, verified code bytes, and execution policy into sealed candidate bundles — a good extraction + elevation of logic previously trapped inside improvement-cycle.ts, with one minor internal duplication.
- What it does: Introduces buildAgentCandidateBundle (src/candidate-execution/builder.ts:80), a public high-level API that accepts typed profile sources (full profile, profile-diffs, or pre-frozen candidate-profile), a code source (CodeSurface whose bytes are re-verified via agent-eval's verifyCodeSurface, or explicit disabled/no-op), execution policy, knowledge, and memory — and compiles them into a schema-valid
- Goals it achieves: 1) Give callers ONE safe path to construct candidate bundles instead of hand-assembling the low-level AgentCandidateBundleInput (where they could embed unverified code bytes, supply contradictory lineage, or drop profile fields silently). 2) Make the profile-freezing/binding logic reusable — it was private inside improvement-cycle.ts and is now a shared module both the improvement cycle and direct
- Assessment: Sound change in the grain of the codebase. The layering is correct: sealAgentCandidateBundle (bundle.ts) remains the low-level sealer; buildAgentCandidateBundle sits above it as the compiler that assembles inputs safely. The fail-closed design is thorough — it rejects unsupported profile fields (connections, metadata, extensions), derives profileDiffIds from the profile source (callers cannot cont
- Better / existing approach: none — this is the right approach. The builder correctly delegates code verification to agent-eval's verifyCodeSurface (the substrate), reuses sealAgentCandidateBundle for the actual sealing, and extracts profile logic that was previously trapped in improvement-cycle.ts. No existing equivalent in the codebase does what buildAgentCandidateBundle does.
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 2
- Bridge warning: opencode/kimi-for-coding/k2p7: bridge stream ended without value-audit content
🎯 Usefulness — sound
Canonical builder + extracted profile-freezing module that deduplicates inline logic from the intelligence layer and exposes one public entry point for compiling measured candidates into sealed, byte-verified execution bundles.
- Integration: Fully wired and reachable.
buildAgentCandidateBundle(builder.ts:80) is exported from the public./candidate-executionpackage path (index.ts:6) and verified by scripts/verify-package-exports.mjs:81-122. It feeds the intelligence lifecycle:proposeAgentImprovement(improvement-cycle.ts:159) accepts abuildCandidatecallback whose JSDoc (improvement-cycle.ts:113) names `buildAgentCandidateB - Fit with existing patterns: Fits the codebase grain and removes duplication. Before this PR,
parseExactAgentProfile,assertCandidateProfileBinding, andcandidateProfileAsAgentProfilewere inlined in improvement-cycle.ts; the PR extracts them into candidate-execution/profile.ts and re-imports them (improvement-cycle.ts:30-32). The new builder wraps — does not compete with — the pre-existing low-level `sealAgentCandidate - Real-world viability: Defensive on the paths that matter. Fails closed on unsupported profile fields (connections/metadata/extensions/model.metadata), caller-supplied
profileDiffIds, raw Git patches (must go through agent-evalverifyCodeSurface), and code/profile identity drift (builder.ts:83, 146-153, profile.ts:32-35, 224-227). CodeSurface bytes are re-read and hash-checked before embedding (builder.ts:146-153). - Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
💰 Value Audit
🟡 assertCanonicalParse duplicated identically in builder.ts and profile.ts [duplication] ``
assertCanonicalParse is defined byte-for-byte identically in builder.ts:170 and profile.ts:246 (same Buffer.from(canonicalCandidateBytes(...)).equals(...) check, same error message template). Both files are in the same candidate-execution/ directory and both already import from digest.ts. Extract this helper into digest.ts (or a shared internal util) and import it from both, the same way canonicalCandidateDigest and canonicalCandidateBytes are already shared. Does not gate shipping — purely a lo
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.
Summary:
Validation: