mirror of
https://github.com/motajs/template.git
synced 2026-09-13 02:08:50 +08:00
fix(03-data-completion): revise circular gate plan coverage
This commit is contained in:
parent
461e11c99e
commit
5c962520ef
139
.planning/phases/03-data-completion/03-16-PLAN.md
Normal file
139
.planning/phases/03-data-completion/03-16-PLAN.md
Normal file
@ -0,0 +1,139 @@
|
||||
---
|
||||
phase: 03-data-completion
|
||||
plan: 16
|
||||
type: execute
|
||||
wave: 9
|
||||
depends_on: [03-15]
|
||||
files_modified:
|
||||
- script/check-data-circular.ts
|
||||
- script/check-data-circular.test.ts
|
||||
- .planning/phases/03-data-completion/03-COMMON-CYCLE-CONTRACT.md
|
||||
autonomous: true
|
||||
requirements: [DATA-01]
|
||||
gap_closure: true
|
||||
gap_ids: [CORR-03-07]
|
||||
estimate:
|
||||
tokens: 14000
|
||||
raw_tokens: 14000
|
||||
tasks: 2
|
||||
confidence: low
|
||||
must_haves:
|
||||
truths:
|
||||
- "CORR-03-07: A cycle is outside scope for compatibility reasons only when every node is under packages-user/data-state/src/legacy/ or packages-user/client-modules/."
|
||||
- "Legacy-only and client-only cycles are outside scope, while legacy+data and legacy+common mixed cycles remain in-scope and fail the gate."
|
||||
- "A cycle touching approved non-compatibility data-common/data-base/data-system/data-state code, or packages/common/transitive common boundaries, remains in-scope and fails non-zero."
|
||||
- "A deterministic supported fixture mode exercises the real circular-gate classifier in a separate process: legacy-only/client-only fixtures exit 0, while legacy+data/legacy+common fixtures exit non-zero."
|
||||
- "The scope rationale is recorded without changing legacy implementation, save architecture, replay/event code, or user-owned replay-safety decorator placement."
|
||||
artifacts:
|
||||
- path: "script/check-data-circular.ts"
|
||||
provides: "Madge circular gate with a pure, normalized compatibility-only classifier, production fail-closed exit behavior, and validated deterministic fixture mode"
|
||||
- path: "script/check-data-circular.test.ts"
|
||||
provides: "Regression coverage for legacy-only, client-only, legacy+data, legacy+common, approved scope boundaries, and process exit behavior"
|
||||
- path: ".planning/phases/03-data-completion/03-COMMON-CYCLE-CONTRACT.md"
|
||||
provides: "Documented CORR-03-07 compatibility-cycle scope rationale"
|
||||
key_links:
|
||||
- "Madge cycle output -> normalized scope classifier -> in-scope/outside-scope report"
|
||||
- "all cycle members under compatibility prefixes -> compatibility-only exclusion; any approved member -> in-scope classification"
|
||||
- "in-scope cycle count -> existing non-zero circular-gate exit"
|
||||
- "validated synthetic fixture selector -> the same classifier/report/exit path used by Madge -> deterministic process status"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Close CORR-03-07 by correcting only the circular gate's scope classification: cycles entirely contained in legacy/client compatibility paths are outside scope, while every mixed cycle touching approved data-layer or common boundaries remains in-scope and fails the gate. Add a supported deterministic fixture mode so this process-level exit behavior does not depend on whether the current repository graph happens to contain a mixed cycle.
|
||||
|
||||
Purpose: The current predicate has no explicit compatibility-only rule, so the correction must distinguish an all-compatibility cycle from a mixed cycle without weakening the approved data/common boundary. The correction belongs in the gate classifier, not in compatibility implementation. Process-level coverage must use validated synthetic cycles rather than the incidental repository graph.
|
||||
Output: A pure tested classifier kept inside the circular script, the existing gate wired to its fail-closed result, a deterministic fixture CLI mode and focused process assertions, and an explicit scope-rationale update to the circular contract.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@C:/Users/book/.config/opencode/gsd-core/workflows/execute-plan.md
|
||||
@C:/Users/book/.config/opencode/gsd-core/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/REQUIREMENTS.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/03-data-completion/03-CONTEXT.md
|
||||
@.planning/phases/03-data-completion/03-VERIFICATION.md
|
||||
@.planning/phases/03-data-completion/03-15-SUMMARY.md
|
||||
@.planning/phases/03-data-completion/03-COMMON-CYCLE-CONTRACT.md
|
||||
@script/check-data-circular.ts
|
||||
@script/check-data-circular.test.ts
|
||||
@package.json
|
||||
@dev.md
|
||||
</context>
|
||||
|
||||
## Source Audit
|
||||
|
||||
| Source | ID | Item | Plan | Status |
|
||||
|---|---|---|---|---|
|
||||
| GOAL | — | Phase 3's independently verifiable data-layer quality gate | 03-16 | COVERED |
|
||||
| REQ | DATA-01 | Data-layer systems and Node validation retain a truthful final circular gate | 03-16 | COVERED |
|
||||
| RESEARCH | D-20 boundary | Four data packages plus the transitive common/data-common boundary are checked; only all-members compatibility-only cycles receive the compatibility exclusion, while mixed approved-boundary cycles remain failures | 03-16 | COVERED |
|
||||
| CONTEXT | D-16, D-20, S-01 | Preserve the approved gate boundary and treat legacy as compatibility-only | 03-16 | COVERED |
|
||||
| CONTEXT | S-04 | Keep user-owned replay-safety decorator placement outside this correction | 03-16 | COVERED |
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="tracer">
|
||||
<name>Task 1: CORR-03-07 wire the compatibility-only circular scope classifier</name>
|
||||
<gap_id>CORR-03-07</gap_id>
|
||||
<read_first>script/check-data-circular.ts, .planning/phases/03-data-completion/03-COMMON-CYCLE-CONTRACT.md, .planning/phases/03-data-completion/03-CONTEXT.md, dev.md</read_first>
|
||||
<files>script/check-data-circular.ts, script/check-data-circular.test.ts, .planning/phases/03-data-completion/03-COMMON-CYCLE-CONTRACT.md</files>
|
||||
<action>Keep the classifier in `script/check-data-circular.ts` and make its pure cycle-classification functions importable by the focused test without launching Madge during import. Normalize slash direction, define compatibility prefixes (`packages-user/data-state/src/legacy/` and `packages-user/client-modules/`), and define approved prefixes for `packages-user/data-common/`, `packages-user/data-base/`, `packages-user/data-system/`, non-compatibility `packages-user/data-state/`, and `packages/common/` including transitive common nodes. Compute the compatibility exclusion with an all-members check: a cycle is compatibility-only only when every normalized node matches one of the legacy/client compatibility prefixes; never exclude a cycle merely because one member matches. Compute approved scope independently: any cycle member touching an approved non-compatibility data path or packages/common/transitive common boundary is in-scope, so legacy+data and legacy+common mixed cycles stay in-scope and use the existing non-zero `inScope.length > 0` exit. Preserve Madge entries, TypeScript options, reporting, and direct-script behavior. Add a supported `--fixture <legacy-only|client-only|legacy-data|legacy-common>` mode with an allow-listed synthetic cycle table and input validation; each selected fixture must pass through the same normalization, scope classification, reporting, and process-exit function used by Madge, without launching Madge or consulting the current repository graph. The fixture mode must return 0 for the two compatibility-only cases and non-zero for both mixed cases. Update the contract to state the exact all-members rule, mixed-cycle failure rule, fixture names, and expected process statuses (D-16, D-20, S-01). Keep this correction limited to the gate, its focused test, and contract documentation; do not edit legacy implementation, save architecture, replay/event code, or user-owned replay-safety decorator placement (S-01, S-04).</action>
|
||||
<verify>
|
||||
<automated>$script = Get-Content -Raw 'script/check-data-circular.ts'; foreach ($token in @('packages-user/data-state/src/legacy/', 'packages-user/client-modules/', 'packages-user/data-common/', 'packages-user/data-base/', 'packages-user/data-system/', 'packages-user/data-state/', 'packages/common/', 'every', 'inScope.length > 0', 'process.exit(1)', '--fixture', 'legacy-only', 'client-only', 'legacy-data', 'legacy-common')) { if ($script -notmatch [regex]::Escape($token)) { throw "Missing explicit classifier/gate token: $token" } }; $contract = Get-Content -Raw '.planning/phases/03-data-completion/03-COMMON-CYCLE-CONTRACT.md'; foreach ($token in @('packages-user/data-state/src/legacy', 'packages-user/client-modules', 'compatibility-only', 'mixed', 'in-scope', 'CORR-03-07', 'legacy-only', 'client-only', 'legacy-data', 'legacy-common', 'exit 0', 'non-zero')) { if ($contract -notmatch [regex]::Escape($token)) { throw "Missing documented scope rationale: $token" } }; pnpm exec vitest run script/check-data-circular.test.ts; if ($?) { pnpm exec eslint script/check-data-circular.ts script/check-data-circular.test.ts }; if ($?) { pnpm exec prettier --check script/check-data-circular.ts script/check-data-circular.test.ts .planning/phases/03-data-completion/03-COMMON-CYCLE-CONTRACT.md }</automated>
|
||||
<fails_when>The gate can classify a cycle as outside scope because it contains one compatibility node, an approved data/common prefix is omitted or treated as compatibility-only, the all-members compatibility rule or validated fixture selector is absent, the in-scope non-zero exit is removed, the scope rationale or expected fixture statuses are absent, or focused lint/format checks fail.</fails_when>
|
||||
</verify>
|
||||
<done>The live circular gate has an explicit all-members compatibility-only rule, keeps mixed approved-boundary cycles fail-closed, and the contract records why the boundary is intentional.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: CORR-03-07 regression-test compatibility-only and mixed-cycle boundaries</name>
|
||||
<gap_id>CORR-03-07</gap_id>
|
||||
<read_first>script/check-data-circular.ts, .planning/phases/03-data-completion/03-COMMON-CYCLE-CONTRACT.md, .planning/phases/03-data-completion/03-CONTEXT.md, dev.md</read_first>
|
||||
<files>script/check-data-circular.test.ts</files>
|
||||
<action>Add focused Vitest cases against the exported pure classifier using normalized and backslash paths. Cover at least: legacy-only cycle => outside scope; client-only cycle => outside scope; legacy+data (including an approved data-state or data-base member) => in-scope; legacy+common (including `packages/common/` or a transitive common member) => in-scope; and a non-legacy data-only cycle plus a packages/common-to-data-common cycle => in-scope. Also cover a legacy+client cycle as compatibility-only only when every member remains within the two compatibility prefixes. Invoke the supported process command as child processes for the four validated synthetic fixtures (`pnpm exec tsx script/check-data-circular.ts --fixture legacy-only`, `client-only`, `legacy-data`, and `legacy-common`) and assert the actual exit status is respectively 0, 0, non-zero, and non-zero; assert allowed fixtures report outside-scope classification and mixed fixtures report an in-scope cycle/failing gate. This process-level assertion must run the real script entry and its real classifier, not reproduce the expected status with test-only logic or inspect the current repository graph. Assert the classifier's in-scope result is the value consumed by the existing non-zero gate branch, rather than turning the exclusion into a blanket allow-list. Add the repository-required Chinese coverage comment before every `it`. Keep the test and fixture mode as circular-gate coverage only and do not add files or edits in legacy, save, replay, event, or user-owned state-method paths (D-16, D-20, S-01, S-04).</action>
|
||||
<verify>
|
||||
<automated>$lines = Get-Content -LiteralPath 'script/check-data-circular.test.ts'; for ($i = 0; $i -lt $lines.Count; $i++) { if ($lines[$i] -match '^\s*it(?:\.[A-Za-z]+)*\s*\(') { if ($i -eq 0 -or $lines[$i - 1] -notmatch '^\s*//\s*[\u4e00-\u9fff]') { throw "Missing Chinese coverage comment before it at line $($i + 1)" } } }; pnpm exec vitest run script/check-data-circular.test.ts; if ($?) { pnpm exec eslint script/check-data-circular.ts script/check-data-circular.test.ts }; if ($?) { pnpm exec prettier --check script/check-data-circular.ts script/check-data-circular.test.ts .planning/phases/03-data-completion/03-COMMON-CYCLE-CONTRACT.md }</automated>
|
||||
<fails_when>Any legacy-only or client-only fixture process exits non-zero, any legacy+data or legacy+common fixture process exits zero, the process assertions do not execute the actual script entry/classifier, any approved data/common fixture is outside scope, the gate's non-zero in-scope behavior is not preserved, a required Chinese test comment is missing, the focused Vitest/lint/Prettier checks fail, or the test/fixture mode changes any legacy, save, replay, event, or decorator implementation.</fails_when>
|
||||
</verify>
|
||||
<done>Regression coverage proves legacy-only and client-only exclusions are all-members compatibility cases, legacy+data and legacy+common mixed cycles remain failing in-scope cases, and no unrelated implementation or decorator changes are planned.</done>
|
||||
</task>
|
||||
</tasks>
|
||||
|
||||
<threat_model>
|
||||
## Trust Boundaries
|
||||
|
||||
| Boundary | Description |
|
||||
|---|---|
|
||||
| Madge graph -> scope classifier | Dependency paths are untrusted diagnostic data that determine whether the quality gate blocks. |
|
||||
| Scope classifier -> process exit | Classification controls the gate's pass/fail result and must not hide approved cycles. |
|
||||
| Compatibility paths -> legacy/client behavior | Existing compatibility cycles must remain intact; only compatibility-only cycles are outside this gate, while mixed approved-boundary cycles remain failures. |
|
||||
|
||||
## STRIDE Threat Register
|
||||
|
||||
| Threat ID | Category | Component | Severity | Disposition | Mitigation Plan |
|
||||
|---|---|---|---|---|---|
|
||||
| T-03-37 | Tampering | circular scope classifier | high | mitigate | Use an all-members compatibility predicate, explicit approved prefixes, synthetic cycle fixtures, and a live gate run. |
|
||||
| T-03-38 | Denial of service | legacy/client compatibility cycles | medium | mitigate | Exclude only cycles whose every member is in the named compatibility prefixes; do not let one compatibility member exempt a mixed cycle. |
|
||||
| T-03-39 | Tampering | non-legacy data/common boundary | high | mitigate | Regression-test data-only, legacy+data, and legacy+common cycles as in-scope and retain the existing non-zero exit branch. |
|
||||
| T-03-SC | Tampering | npm/pip/cargo installs | low | accept | No package installation is planned. |
|
||||
</threat_model>
|
||||
|
||||
<verification>
|
||||
- `pnpm exec vitest run script/check-data-circular.test.ts`
|
||||
- `pnpm exec eslint script/check-data-circular.ts script/check-data-circular.test.ts`
|
||||
- `pnpm exec prettier --check script/check-data-circular.ts script/check-data-circular.test.ts .planning/phases/03-data-completion/03-COMMON-CYCLE-CONTRACT.md`
|
||||
- The focused test launches the supported fixture mode in separate processes and proves `legacy-only` and `client-only` exit 0, while `legacy-data` and `legacy-common` exit non-zero, using synthetic cycles rather than the current repository graph.
|
||||
- `$cases = @(@('legacy-only', 0), @('client-only', 0), @('legacy-data', 1), @('legacy-common', 1)); foreach ($case in $cases) { & pnpm exec tsx script/check-data-circular.ts --fixture $case[0] 2>&1 | Out-String | Out-Null; $actual = $LASTEXITCODE; if ($actual -ne $case[1]) { throw "Fixture $($case[0]) exited $actual, expected $($case[1])" } }`
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
CORR-03-07 is closed when the actual circular gate uses an all-members compatibility-only exclusion, its supported deterministic fixture mode drives the real process entry and proves allowed versus failing exit statuses for all required cycle classes, and the documented rationale makes clear that no compatibility, save, replay, event, or user-owned decorator implementation was changed. The production Madge path remains fail-closed for any in-scope cycle; this plan does not depend on the current repository graph containing a mixed cycle and does not change those implementations.
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
Create `.planning/phases/03-data-completion/03-16-SUMMARY.md` when done
|
||||
</output>
|
||||
Loading…
Reference in New Issue
Block a user