FN-8694: add content-addressed validation memoization
Memoizes mission validation inputs and bounds repeat failures. - Persist validator input fingerprints and atomically admit validation runs. - Reuse unchanged static passes while enforcing per-fingerprint failure budgets. - Add migration coverage, execution-loop tests, and operator documentation. Files changed: .changeset/fn-8694-validation-memoization.md | 7 + docs/missions.md | 6 + docs/storage.md | 6 + .../__tests__/postgres/mission-store.pg.test.ts | 40 +++- packages/core/src/async-mission-store-queries.ts | 24 ++- packages/core/src/async-mission-store.ts | 65 +++++- packages/core/src/mission-store.ts | 10 +- packages/core/src/mission-types.ts | 19 ++ .../0042_fn_8694_validator_input_fingerprint.sql | 9 + packages/core/src/postgres/schema-applier.ts | 13 +- packages/core/src/postgres/schema/project.ts | 5 + .../src/__tests__/mission-execution-loop.test.ts | 72 ++++++- packages/engine/src/mission-execution-loop.ts | 217 +++++++++++++++++---- 13 files changed, 443 insertions(+), 50 deletions(-) Fusion-Task-Id: FN-8694 Fusion-Task-Lineage: 92a790d5-f2fc-4e71-b9ee-8334ff38b20d Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
@@ -749,3 +749,9 @@ A completed cited research finding may become a normal Mission Feature. Its feat
|
||||
### Autonomous mission admission
|
||||
|
||||
Autonomous no-task heartbeat agents may create or delegate implementation work only with an approved Feature → Slice → Milestone → Mission lineage. Interactive and task-scoped calls remain governed by `task_agent_mutation` policy as described in [Agent task-creation admission](#agent-task-creation-admission). The created task stores that lineage as task metadata; it does not replace the canonical feature `taskId` link except at the documented `defined`-feature first-task bootstrap. Missing or invalid autonomous lineage is rejected before a task is persisted. Roadmap reconciliation marks done tasks done, returns cancelled/requeued tasks to triaged, keeps failed work non-complete, and treats archives as non-promoting no-ops.
|
||||
|
||||
## Validator memoization and failure budget (FN-8694)
|
||||
|
||||
Automatic feature validation is content-addressed by landed SHA, resolved judge provider/model, and exact built prompts. Admission is atomic per project, feature, and fingerprint: a matching running run is not duplicated; the latest terminal history is selected deterministically; static-only passes are reused; and matching failures permit at most three dispatched runs before the feature is blocked. Behavioral or mixed assertions never reuse a pass, but failures are still budgeted.
|
||||
|
||||
Every automatic suppression appends one visible `validation memoized` activity event (`running`, `reuse-pass`, or `budget-exhausted`) with fingerprint and referenced run ID where available. Initial exhaustion additionally appends one `validation-stuck` event; later unchanged sweeps append only their memoized event. No synthetic validator run or verdict is created for reuse or exhaustion. Missing landed SHA, fallback checkout, unknown judge identity, and preparation failures fail open to ordinary validation; `error`/`blocked` outcomes are transient. Manual validation bypasses memoization and the budget. Recovery revisits only a feature bearing FN-8694's budget-block provenance: unchanged inputs remain blocked, while a changed prepared fingerprint can be admitted; unrelated blocked/remediation/operator states stay closed.
|
||||
|
||||
@@ -814,3 +814,9 @@ Direct chat tags are stored in the project PostgreSQL schema as `chat_tags` and
|
||||
Events use `(project_id, seq)` and a deterministic `evt_` SHA-256 identity over project, event type, task ID, and deletion timestamp. `project.task_lifecycle_event_seq` allocates that per-project sequence through a transactional counter upsert. Its lock is held until commit, so allocation order equals commit order, committed rows are in-order and gap-free, and rollback reverts the counter without consuming a number. Payloads contain only task IDs, previous lane/status, deletion timestamp, resurrection/issue action, and actor ID fields.
|
||||
|
||||
FN-8685 adds `task_lifecycle_consumer_registrations`, `task_lifecycle_consumer_cursors`, `task_lifecycle_consumer_receipts`, and `task_lifecycle_consumer_dead_letters`. Every table is scoped by project and consumer; receipts and dead letters use `(project_id, consumer_id, event_id)` uniqueness. Registrations provide durable liveness for retention. Retention runs from self-healing at most every six hours per project, is bounded to 5,000 rows per sweep, and does not prune rows unacknowledged by live consumers. If no identity is live, it only age-prunes events older than 30 days so a within-bound restart can catch up.
|
||||
|
||||
## Mission validator input memoization (FN-8694)
|
||||
|
||||
`project.mission_validator_runs.input_fingerprint` stores a nullable SHA-256 content address for eligible automatic validator runs. The address hashes UTF-8 bytes of `JSON.stringify(["mission-validation-input-v1", landedSha, provider, modelId, systemPrompt, userPrompt])`; the versioned array avoids delimiter ambiguity and ordinary prompt-template changes invalidate naturally. The `(project_id, feature_id, input_fingerprint)` index scopes lookup and admission, so history never crosses projects or features.
|
||||
|
||||
Automatic admission locks the project-scoped feature row, records a running row only for an admitted dispatch, and writes one `validation memoized` mission activity event for each suppressed running/pass/budget decision. Matching static passes are reused without fabricating a run. Matching failed rows consume the per-fingerprint budget; exhaustion records `loop_state = blocked` plus fingerprint/run/timestamp provenance and emits exactly one additional `validation-stuck` event for that feature/fingerprint. Repeated unchanged suppressions remain individually auditable but do not repeat the stuck event. Reaped `error` and `blocked` runs are transient and do not seed reuse or the failure count.
|
||||
|
||||
Reference in New Issue
Block a user