Skip to content

feat(interface): bind exact improvement sources#69

Open
drewstone wants to merge 1 commit into
mainfrom
feat/agent-profile-improvement-source
Open

feat(interface): bind exact improvement sources#69
drewstone wants to merge 1 commit into
mainfrom
feat/agent-profile-improvement-source

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

Problem

Improvement proposals had no product-neutral way to retain the exact source state they measured.

Change

Adds one validated source reference and metadata helper in @tangle-network/agent-interface: source kind, source identity, source digest, and source revision.

Proof

  • pnpm --filter @tangle-network/agent-interface test (141 passed)
  • pnpm --filter @tangle-network/agent-interface check-types
  • pnpm --filter @tangle-network/agent-interface build
  • git merge-tree --write-tree origin/main HEAD

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Auto-approved drewstone PR — dc2990e4

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-23T07:40:26Z

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Value Audit — sound-with-nits

Verdict sound-with-nits
Concerns 2 (2 weak-concern)
Heuristic 0.0s
Duplication 0.0s
Interrogation 173.5s (2 bridge agents)
Total 173.5s

💰 Value — sound-with-nits

Adds a small, validated schema + read/write helpers that bind an improvement proposal to the exact external provider state it was measured against, slotted into the measured-comparison's existing free-form metadata bag — coherent and in-grain.

  • What it does: Introduces agentImprovementSourceSchema (kind/sourceIdentity/sourceDigest/sourceRevision) plus agentImprovementSourceMetadata() (write) and readAgentImprovementSource() (read) in a new 52-line module. The write helper parks one validated source reference under the typed key agentImprovementSource inside the measured comparison's existing free-form metadata field (agent-candidate-promotio
  • Goals it achieves: Gives improvement proposals a product-neutral, tamper-evident way to record which exact external source state (e.g. the ap_reviewer provider's profile at revision 17) a measurement was taken against, so a later stale-source mismatch (the provider moved on) is detectable and intelligible to callers. The system gains a reusable, schema-validated provenance slot instead of every consumer inventing
  • Assessment: Good change on its merits. It is built in the grain of the package: it reuses sha256DigestSchema and AgentCandidateJsonValue from existing modules, uses the same .strict() zod-object convention as every neighbor, targets the intended extension point (the optional metadata record on agentImprovementMeasuredComparisonSchema), and is proportionate — 52 lines + a tight round-trip/rejection t
  • Better / existing approach: none — this is the right approach. I searched for existing equivalents (rg sourceIdentity|sourceDigest|sourceRevision|improvementSource, all consumers of agentImprovementSource*, the provenance object at agent-candidate-promotion-schema.ts:314-323, and the activation-target shape at agent-candidate-promotion-schema.ts:878-884). The existing provenance and activation shapes bind different thing
  • 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

A small, in-grain typed metadata helper for binding improvement proposals to their exact source state; reuses existing primitives, fits the metadata-slot pattern, and will attach cleanly once a producer adopts it.

  • Integration: Exported via packages/agent-interface/src/index.ts:827. No internal callers yet (grep across the repo found only the new file + its test) — purely additive, which the rubric treats as fine. The attach point is real: AgentImprovementMeasuredComparison carries metadata?: { [key: string]: AgentCandidateJsonValue } (agent-candidate.ts:909), reached from a proposal as proposal.evaluation.metadata.
  • Fit with existing patterns: Reuses sha256DigestSchema and AgentCandidateJsonValue — the established primitives in agent-candidate-schema-common.ts. Grep for agentImprovementSource/AgentImprovementSource/readAgentImprovementSource found no prior equivalent. Minor divergence: every other kind discriminator in this package is a closed z.literal(...) (e.g. agent-candidate-schema-common.ts:330 z.literal("github"), promotion s
  • Real-world viability: Holds up off the happy path. .strict() rejects unknown keys (asserted at test line 42-44); sha256DigestSchema validates format (asserted line 30-35); sourceRevision union accepts both numeric counters and textual IDs like git:abc123 (asserted line 36-41); readAgentImprovementSource throws a clear message on a missing key (line 27-29). Round-trip is proven. Plain Error (not typed) is consistent
  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 1

🎯 Usefulness Audit

🟡 Docstrings name the wrong carrier type [problem-fit] ``

agent-improvement-source.ts:32,42,49 say the source binds to 'signed improvement proposal metadata' / 'signed improvement proposal is missing its source reference', but AgentImprovementProposal (agent-candidate.ts:912-920) has no metadata field — the slot lives on its evaluation sub-object, AgentImprovementMeasuredComparison.metadata (agent-candidate.ts:909). The helper is slot-agnostic so behavior is correct, but the wording will mislead the first adopter about where to attach it. Suggest rewor

💰 Value Audit

🟡 No in-tree producer or consumer of the new contract [maintenance] ``

rg 'agentImprovementSource|readAgentImprovementSource|AGENT_IMPROVEMENT_SOURCE' outside the new files returns zero hits, so the contract ships with no exerciser. This matches the package's interface-first cadence (PRs #63/#59 publish contracts ahead of implementations), so it is not blocking; just flagging that the schema's real-world fit (especially the sourceRevision string|number union and the kind regex) is unproven until a provider emits and a consumer reads it.


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.

value-audit · 20260723T074506Z

@tangletools

Copy link
Copy Markdown

✅ No Blockers — dc2990e4

Review health 100/100 · Reviewer score 89/100 · Confidence 70/100 · 2 findings (2 low)

glm: Correctness 89 · Security 89 · Testing 89 · Architecture 89

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.

🟡 LOW readAgentImprovementSource rejection paths for non-object metadata are untested — packages/agent-interface/src/agent-improvement-source.test.ts

readAgentImprovementSource accepts unknown and runs z.record().parse() on it, but the test only exercises the missing-key case ({}). Untested: null/array/string/number metadata (throws ZodError from z.record), and key-present-but-value-null (falls through === undefined check then throws ZodError from the source schema). These all throw, so there's no correctness bug, but the outer-record rejection contract is unverified. Add 1-2 expect().toThrow cases for non-object inputs to lock the boundary behavior.

🟡 LOW agentImprovementSourceMetadata re-parses an already-typed AgentImprovementSource input — packages/agent-interface/src/agent-improvement-source.ts

The parameter is typed AgentImprovementSource yet the body calls agentImprovementSourceSchema.parse(source) again. This is defensible defense-in-depth (callers may have constructed the value from unvalidated input despite the type), and the cost is negligible, but it is technically redundant. Not a bug; noting for awareness.


tangletools · 2026-07-23T07:45:51Z · trace

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Approved — 2 non-blocking findings — dc2990e4

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-07-23T07:45:51Z · immutable trace

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants