Skip to content

feat(dynamic-workflow): opt-in content-addressed cross-run reuse - #49

Open
modacker wants to merge 1 commit into
MiniMax-AI:mainfrom
modacker:community/addressing-reuse
Open

modacker wants to merge 1 commit into
MiniMax-AI:mainfrom
modacker:community/addressing-reuse

Conversation

@modacker

@modacker modacker commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

What changes

Implements opt-in content-addressed cross-run reuse for the dynamic-workflow plugin: a run can now adopt succeeded nodes from any prior run in the same workspace store when both the execution context and the call spec hash identically — not only within a repair lineage.

Design provenance: the derived-stable-identifier approach ("the key is the identity") follows our deterministic-addressing tool (sih-engine family, sih-tools/locator).

Design

  • Opt-in at run level: reuseAcrossRuns: true on start/update (default false). The key is absent from the definition unless explicitly true — an always-present default key would change requestHash and break the legacy idempotent-replay path (caught by the "legacy limits … old idempotent requests still work" test; the fix follows the same absent-means-default pattern as DEFAULT_LIMITS).
  • Key equality: context = hash({workspace, input, executor, fingerprints}) (same four factors as repair's contextHash, cached per run), spec = hash(spec) (prompt/schema/input included — a different schema is a different contract). Lookup joins steps × runs via json_extract, newest first, this run excluded, only succeeded agent nodes.
  • Provenance: adopted steps carry reusedFrom — the original producer's lineage when present, otherwise {runId, stepId, endedAt, crossRun: true} — and emit step.reused. Reuse consumes no call budget (attempt: 0, before the budget gate).
  • Schema revalidated per candidate against today's validator before adoption; a candidate that no longer validates is skipped (fresh call instead).
  • Honest boundary (documented in README): cross-run reuse proves context identity and storage fidelity, not first-run semantic correctness. For critical nodes, put evidence fields in the schema and place an independent verification node downstream.

Test evidence

  • New checks/cross-reuse.check.mjs: 11 tests — default-off, opt-in hit (zero new calls, provenance, event), input/executor/prompt/schema/fingerprint changes all miss, failed nodes never reused, newest-wins, pure reuse on a one-call budget, requestId idempotency across a flipped flag.
  • TDD order: tests first (red 6/11 — the five positive feature cases failed on the missing API), implementation second → 11/11.
  • Full plugin suite: 83/83 (72 baseline + 11 new). One regression was caught and fixed during development: an always-present default key broke the legacy idempotent replay — exactly what the legacy-compat test guards.
  • Packaged MCP smoke passes; npm run build byte-reproducible; repository validator green on a clean checkout.
  • macOS arm64, Node v26.7.0, based on main (00878c7).

Follow-up seam

Once #48 (integrity ledger) merges, a small follow-up can route accepted cross-run reuses through the ledgered surface so "what reuse trusts" is covered by the same tamper-evidence chain.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

- run-level reuseAcrossRuns flag (default false, part of requestHash)
- agent() consults prior succeeded nodes from other runs in the same
  workspace store when context (workspace/input/executor/fingerprints)
  and spec hash match; newest first, schema revalidated per candidate
- reused results carry reusedFrom provenance (crossRun marker, original
  producer preserved) and consume no call budget
- store.findCrossRunReuse joins steps x runs with json_extract filters
- README documents the semantics and the honest boundary: reuse proves
  context identity and storage fidelity, not first-run correctness

@hetaoBackend hetaoBackend left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Request changes for exact current head 35223d3.

Blocking correctness/contract issues:

  1. reuseAcrossRuns is implemented in engine.mjs:48,77, but is absent from the public MCP schemas in src/tools.mjs:13-14 (and the generated dist/main.mjs). Those schemas use additionalProperties:false, so a normal MCP client cannot discover or reliably send the documented feature. Add the field and description to workflow_start and workflow_update, rebuild dist, and add a packaged MCP contract test that enables it through the public tool surface.
  2. Cross-run reuse does not track upstream lineage. engine.mjs:199-208 and store.mjs:52 match only the downstream node request hash and a run-level context hash; dependsOn is only the upstream ID. I reproduced this on the exact head: run 1 executed a(prompt=old) -> b(prompt=same), run 2 executed a(prompt=new) and then reused b from run 1, producing a=out:new with b=out:same and reusedFrom.crossRun=true. A changed/rerun upstream must invalidate downstream reuse, as the README promises. Persist/compare effective dependency lineage or upstream output/spec hashes, and add the R1/R2 regression test.
  3. For MCode nodes without an explicit spec.model, the effective default model/provider/config comes from the CLI environment, but the cache identity contains only executor: 'mcode' and the node spec. A changed MCode default model/config/CLI can therefore reuse an old result. Require an explicit model for cross-run MCode reuse or include a resolved model/config/CLI identity in the cache key and test that a default-model change misses.
  4. store.findCrossRunReuse() applies LIMIT 20 before filtering by context hash (store.mjs:52), so 20 newer same-node results from other contexts can hide an older valid candidate forever. Filter in SQL using a persisted/indexed context key or scan/paginate until a valid candidate is found.
  5. Cross-run adoption of a repair-reused step preserves the old reusedFrom object (engine.mjs:205-206) while emitting a crossRun:true event (:207), so stored provenance can disagree with the event. Preserve immediate source and original producer as separate provenance fields and add a repair-to-cross-run test.

Current GitHub checks are green, but they do not cover the public MCP schema path or the reproduced stale-lineage case. Rebase/rebuild against the current main before requesting another review.

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