Files
fusion/docs/missions-completion-contract.md
gsxdsm acad46cc10 FN-5764: expose mission assertion backfill through API and CLI
Expose mission assertion backfill controls and run paths across engine, API, and CLI surfaces.

- add mission assertion backfill gating classification and reliability coverage for assertion-linked validation recovery
- add dashboard mission routes plus legacy API coverage and e2e checks for running assertion backfill
- expose new extension tool support and update Fusion skill docs/capability references
- add a changeset for @runfusion/fusion and refresh mission documentation

Files changed:
 .changeset/fn-5764-mission-backfill-assertions.md  |   9 ++
 docs/missions-completion-contract.md               |   7 +-
 docs/missions.md                                   |   7 +-
 packages/cli/skill/fusion/SKILL.md                 |   2 +-
 .../cli/skill/fusion/references/extension-tools.md |   9 ++
 .../skill/fusion/references/fusion-capabilities.md |   1 +
 packages/cli/src/__tests__/extension.test.ts       |  41 +++++++
 packages/cli/src/extension.ts                      |  43 +++++++
 .../dashboard/app/__tests__/api-missions.test.ts   |  44 +++++++
 packages/dashboard/app/api/legacy.ts               |  34 ++++++
 .../dashboard/src/__tests__/mission-e2e.test.ts    | 127 +++++++++++++++++++++
 packages/dashboard/src/mission-routes.ts           |  29 +++++
 .../mission-validation-trigger-gap.test.ts         |  66 +++++++++++
 .../workflow-step-readonly-allowlist.test.ts       |   1 +
 packages/engine/src/gating-classifications.ts      |   1 +
 15 files changed, 418 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-5764

Fusion-Task-Lineage: b16123c2-7cfe-4b17-a899-4e30044a7a49
2026-05-31 08:32:01 -07:00

176 lines
11 KiB
Markdown

# Mission Completion Gate Contract
## Status
- **Decision date:** 2026-05-30
- **Task:** FN-5718
- **Depends on enforcement behavior from:** FN-5715 (reference implementation of the trigger/recovery path)
- **Scope:** Product contract and implementation requirements only (no code changes in this task)
- **Implementation status:** Realized by FN-5733 (loop auto-pass advancement, mission/store guard telemetry, MissionManager label reconciliation)
## Problem
Mission validation has had a recurring ambiguity: users can see feature acceptance text and milestone "completion criteria" text, but autopilot enforcement is actually driven by assertion linkage + validator outcomes. This document defines the canonical enforced gate so mission completion cannot silently stall or be misread.
## Canonical Completion Gate (Enforced)
### Decision
A feature is autopilot-complete only when **its linked contract assertions are satisfied**.
Canonical authored source and enforcement path:
1. `MissionFeature.acceptanceCriteria` is the canonical authored criteria text (authoring surface).
2. MissionStore must maintain a **store-managed per-feature `MissionContractAssertion`** derived from feature content, with text priority:
- `feature.acceptanceCriteria`
- `feature.description`
- `Verify implementation of: {feature.title}`
3. The mission validator enforces completion using the feature's **linked assertions** (including its store-managed assertion and any additional linked milestone assertions).
4. Feature/slice/mission advance is gated by the validator outcome (or explicit no-assertions auto-pass behavior defined below).
### Precedence and interpretation rules
- `MissionFeature.acceptanceCriteria` is the canonical authoring field for feature-level intent.
- The **linked assertion set** is the canonical enforcement set.
- Milestone `MissionContractAssertion` rows are additive contract rows. They are enforced **only when linked to a feature**.
- `milestone.acceptanceCriteria` is descriptive/informational milestone text and is not directly executed by the validator.
### Worked examples
1. **Feature has acceptance criteria; store-managed assertion linked; validator passes**
- Result: feature may move to done/passed and contribute to slice completion.
2. **Feature has acceptance criteria; additive milestone assertion also linked; one linked assertion fails**
- Result: feature is not complete; no slice advance.
3. **Feature has acceptance criteria visible, but no linked assertions (legacy FN-5696 shape)**
- Result: data inconsistency; must not be interpreted by operators as a separate enforced gate. Repair links (FN-5696 backfill) so enforcement matches displayed intent.
## Enforced vs. Informational Surfaces
| Surface | Category | Contract meaning |
|---|---|---|
| `MissionFeature.acceptanceCriteria` | Informational authoring source | Canonical authored feature criteria text; enforcement happens through derived/linked assertions |
| Store-managed per-feature `MissionContractAssertion` | Enforced | Primary validator gate for the feature |
| Additive milestone `MissionContractAssertion` (linked to feature) | Enforced | Additional validator gate for that linked feature |
| Additive milestone `MissionContractAssertion` (unlinked) | Informational until linked | Contract candidate, not yet a feature gate |
| `milestone.acceptanceCriteria` | Informational | Milestone summary/pass-bar text for humans; not directly validator-executed |
| MissionManager `milestone-feature-acceptance-rollup` UI (`data-testid="milestone-feature-acceptance-rollup"`) | Informational display | Display-only rendering of feature acceptance text, not a separate enforcement mechanism |
## Zero-Assertion Behavior and FN-5696 Failure Shape
### Zero-assertions runtime behavior (canonical FN-5738 path)
When a feature reaches completion trigger points and has **zero linked assertions**, mission execution must take exactly one canonical auto-pass path (not a silent stall and not a competing behavior):
- mark feature terminal as `status="done"`, `loopState="passed"`, `lastValidatorStatus="passed"`,
- emit explicit observability/audit evidence with mission event code `validation_auto_passed_no_assertions`,
- continue normal slice/mission advancement checks idempotently (no duplicate re-fire on repeated recovery).
### FN-5696 legacy shape clarification
A feature can show acceptance text while links are missing (legacy pre-repair data). This must be treated as a **linkage/data integrity problem**, not as proof that milestone text alone is enforced. Assertion authoring/backfill (FN-5696) is outside the execution loop; the loop must not synthesize `mission_feature_assertions` rows. The contract prevents ambiguity by separating:
- authored/informational text surfaces, from
- linked assertion enforcement surfaces.
Operators should use the mission assertion backfill operator path to restore expected store-managed linkage for FN-5696 legacy rows:
- Agent/tool: `fn_mission_backfill_assertions` with `{ missionId?, dryRun? }` (defaults to dry-run).
- API: `POST /api/missions/:missionId/backfill-assertions` with body `{ dryRun?: boolean }` (defaults to `true`).
- Run dry-run first, then apply (`dryRun=false`) once repaired rows look correct.
- This remediation is additive: it derives/links one store-managed assertion per unlinked feature so runtime enforcement uses validator-linked assertions rather than the zero-assertion auto-pass branch.
## Slice Status and Mission Autopilot Advance Derivation
Autopilot may advance only when each active-slice feature is resolved under this contract:
- Feature with linked assertions: all linked assertions must pass.
- Feature with zero linked assertions: explicit auto-pass path completes it.
- Feature with failed/blocked validation: slice remains incomplete.
- Feature stranded without a task link in an active autopilot slice (`taskId == null`): startup + maintenance reconciliation must repair it (title-match link first, otherwise defined-status re-triage) so `allDone` remains reachable instead of stalling on never-triaged features.
Then:
1. All features resolved complete → slice flips to `complete`.
2. Completed active slice with pending next slice → next slice activates.
3. All milestone slices complete → milestone complete.
4. All mission milestones complete → mission complete.
This keeps completion logic deterministic and consistent with FN-5715 trigger/recovery behavior.
## UI Reconciliation Requirements (for follow-on engineering task)
✅ Implemented in FN-5733 with MissionManager labels:
- `Contract assertions (autopilot gate)` + enforced indicator
- `Feature acceptance criteria (informational)` + not-enforced indicator
- warning badge when `hasProseButNoAssertions === true`
Target surface: `packages/dashboard/app/components/MissionManager.tsx`
1. **Disambiguate labels**
- Use distinct wording for:
- feature-authored acceptance text, and
- milestone contract assertions.
- Do not reuse "Completion criteria" to refer to both categories.
- Required wording baseline (or semantically equivalent copy):
- Feature rollup heading: `Feature acceptance criteria (informational source)`
- Assertion list heading: `Contract assertions (validator-enforced when linked)`
2. **Per-row enforcement indicator**
- Every displayed row in the assertions/criteria area must show whether it is:
- `Enforced gate` (validator-blocking when linked), or
- `Informational` (display-only).
3. **Empty-state contract-correct copy**
- Replace the current implication that completion criteria are absent when assertion rows are empty.
- Empty-state text must acknowledge when feature acceptance text exists but no assertion rows are defined/linked.
- Required behavior:
- If feature acceptance text exists but no assertion rows are present, show copy equivalent to: `No contract assertions are linked yet. Feature acceptance criteria are present below and remain informational until assertions are linked.`
- If neither feature acceptance text nor assertions exist, show copy equivalent to: `No feature acceptance criteria or contract assertions defined yet.`
4. **No button/mobile scope expansion**
- No button touch-target/mobile-reflow requirements (standing directive).
## Engineering Acceptance Criteria (follow-on implementation)
✅ Implemented in FN-5733:
- Auto-pass path now advances `loopState` to `passed` and emits mission event code `validation_auto_passed_no_assertions` while preserving the `validation:passed` emit contract (`"No assertions linked"` summary).
- Milestone rollup/store guard now exposes `hasProseButNoAssertions` and emits warning mission event code `milestone_missing_structured_assertions` (debounced on transition into condition).
- MissionManager UI now distinguishes enforced assertion gate vs informational feature acceptance criteria.
1. **Data/model contract**
- Preserve the canonical relationship: feature-authored criteria -> store-managed assertion -> linked assertion enforcement.
- If any model/UI metadata is added for enforced-vs-informational badges, it must be backward compatible with existing mission rows.
2. **Validator/loop behavior**
- Maintain FN-5715 invariants:
- done mission-linked tasks with linked assertions trigger validation,
- completion-trigger starts loop if needed,
- startup recovery replays done-implementing features with unpassed assertions,
- periodic self-heal maintenance replays the same `recoverActiveMissions` path so historically stranded `implementing` features recover without restart,
- zero-linked-assertions path remains explicit canonical auto-pass.
3. **UI behavior**
- Implement the Step-2 label reconciliation and per-row indicator requirements.
- Ensure no shared ambiguous terminology remains between feature acceptance text and assertion rows.
4. **Regression coverage**
- Add at least one regression test pinning the Goals-mission shape:
- feature has `acceptanceCriteria`,
- parent milestone has zero `MissionContractAssertion` rows / no links,
- autopilot behavior is deterministic and observable (explicit auto-pass path, no silent stall).
5. **Operational observability**
- Ensure mission/audit surfaces make no-assertions auto-pass and subsequent advance decisions queryable in logs/events.
## Success Metric
For 30 days after the follow-on implementation ships:
- **Primary metric:** zero autopilot stalls of the FN-5715 class (done mission task + unresolved validation trigger gap) in production mission runs.
- **Evidence source:** mission audit/event stream (`feature_completed`, `slice_completed`, `mission_completed`) plus `mission_validator_runs` records showing:
- explicit no-assertions auto-pass evidence (summary/reason path such as `No assertions linked` when no validator run is started), and
- downstream advancement evidence without stalled active slices.
## Follow-on Task Requirement
Implementation must land in a separate engineering task that references this document and FN-5715 as the enforcement baseline.