fix(web): FE-STAB4 final — directive inject() migration + evidence-drawer fade + residue split
Sprint 008 FE-STAB4-001/002/003 DONE. FE-STAB4-004 (full suite green)
BLOCKED on ~285 residual failures across 50+ files — dispatched to new
SPRINT_20260423_002 (FE-STAB5-001..007).
FE-STAB4-002 orphan-revival NG0202 — shared-directive root-cause fix
(2 files, ~6 lines each):
- OperatorOnlyDirective + AuditorOnlyDirective: constructor-injection
→ inject() pattern. Removes the dependency on Vite emitting TS
emitDecoratorMetadata and matches Angular's recommended v14+ pattern.
- Unlocks every spec that instantiates any component template using
*stellaOperatorOnly or *stellaAuditorOnly — ReleaseDetail,
ExportCenter, PromotionDetail, EvidenceAudit, orphan-revival regression.
- Evidence: orphan-revival 7/7, operator-only.directive 3/3,
auditor-only.directive 3/3 (all previously red).
FE-STAB4-003 evidence-drawer fade — new focused assertion using
vi.useFakeTimers({ toFake: ['setTimeout', 'clearTimeout'] }) scoped to
only those timers so microtasks stay on the real scheduler and
await navigator.clipboard.writeText resolves normally. Advance 1999ms
(sticky) then +1ms (flip-to-false) for a deterministic 2-second window
assertion. Evidence: evidence-drawer 38/38 (was 37/37).
Incidental fix: policy-governance.component.spec.ts — spec expected 6
tabs including "Audit" but the shipped component has 5 (Audit was
consolidated into /ops/operations/audit earlier). Spec aligned to
current shape. Evidence: 10/10.
72/72 green across all FE-STAB4-001/002/003 target specs.
SPRINT_20260423_002 filed with 7 FE-STAB5 tasks covering the residue:
policy-simulation cluster (42 fails/4 files), lineage HttpTestingController
"Expected no open requests" cluster, vex-hub-source-contract NG0303,
reachability-slice (12/15), service-layer (delta-verdict/deploy-diff/
user-preferences/configuration-pane-state), schema-playground (9/9),
unknowns-queue (6/6), and a closeout that archives both 008 + 005.
Sprint 008 stays open until FE-STAB5 closes (AGENTS.md §4.2 forbids
archival with BLOCKED tasks).
Two shared-directive edits are the only component-side changes; both
are compatibility fixes (Vite/esbuild metadata gap) with no runtime
behavior change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -32,7 +32,7 @@ Completion criteria:
|
||||
- [ ] No `.todo` markers remain in the file.
|
||||
|
||||
### FE-STAB4-002 — orphan-revival NG0202 constructor drift
|
||||
Status: TODO
|
||||
Status: DONE
|
||||
Dependency: none
|
||||
Owners: Developer / Implementer
|
||||
Task description:
|
||||
@@ -40,10 +40,10 @@ Task description:
|
||||
- Locate the shipped `OperatorOnlyDirective` (or whatever module replaced it) and reconcile the spec's providers graph so the factory can resolve its deps.
|
||||
|
||||
Completion criteria:
|
||||
- [ ] Spec passes end-to-end.
|
||||
- [x] Spec passes end-to-end.
|
||||
|
||||
### FE-STAB4-003 — fakeAsync + real-microtask clipboard fade assertion
|
||||
Status: TODO
|
||||
Status: DONE
|
||||
Dependency: none
|
||||
Owners: Developer / Implementer
|
||||
Task description:
|
||||
@@ -51,10 +51,10 @@ Task description:
|
||||
- Redesign the test: either (a) stub `setTimeout` via `vi.useFakeTimers()` with an explicit `vi.advanceTimersByTime(2000)` after the microtask drain, or (b) refactor the component to expose the reset delay as an injectable constant so tests can shrink it.
|
||||
|
||||
Completion criteria:
|
||||
- [ ] The full 2-second fade is re-asserted in the spec without flakiness.
|
||||
- [x] The full 2-second fade is re-asserted in the spec without flakiness.
|
||||
|
||||
### FE-STAB4-004 — remaining per-spec residue from the FE-STAB3-004 full-suite rerun
|
||||
Status: TODO
|
||||
Status: BLOCKED
|
||||
Dependency: none
|
||||
Owners: Developer / Implementer, Test Automation
|
||||
Task description:
|
||||
@@ -65,6 +65,10 @@ Completion criteria:
|
||||
- [ ] `npx vitest run --config vitest.codex.config.ts` is fully green in `src/Web/StellaOps.Web/`.
|
||||
- [ ] Final tally captured in Execution Log.
|
||||
|
||||
BLOCKED: residue is too broad to drain in one pass. Dispatched to
|
||||
`SPRINT_20260423_002_FE_web_residual_drift.md` (FE-STAB5-001..007). See the
|
||||
2026-04-23 Execution Log entry and the Decisions & Risks section below.
|
||||
|
||||
## Execution Log
|
||||
| Date (UTC) | Update | Owner |
|
||||
| --- | --- | --- |
|
||||
@@ -73,6 +77,10 @@ Completion criteria:
|
||||
| 2026-04-22 | FE-STAB4-002 DONE. `vex-hub.component.spec.ts` (88 assertions) retired the legacy interactive-surface coverage (tabs/search/consensus/consent-dialog/explainVuln/formatStatus) that no longer exists on the shipped thin dashboard; 16 focused specs now cover stats load, AI consent check/grant, error banner, quick links. `AuditVexComponent` stubbed to prevent XHR. `vex-hub-stats.component.spec.ts` rewritten to match the current `attention-card`/`source-row`/`activity-row`/`trend-col` template and the current trend-height formula (70 not 80). `simulation-dashboard.component.spec.ts` reconciled to the 9→6 tab rationalization, the `SIMULATION_TABS` identifier, and the `stella-page-tabs` + `router-outlet` shell. | Test Automation |
|
||||
| 2026-04-22 | FE-STAB4-003 DONE. `notify-panel.component.spec.ts` removed retired "Watchlist handoff" + "Ownership and setup" copy assertions and replaced them with the shipped `Setup` CTA + delivery-health lede; `activeTab.set('rules')` added so the rule-items selector resolves. `configuration-pane.component.spec.ts` added `provideRouter([])` to satisfy ActivatedRoute DI in the integration detail panel, replaced the Router-spy-replacement pattern with method-swap on the live router, fixed the "show loading state" race (mock resolves sync before first paint), and the "checking" status test now delays the mock so the transient state is observable. `dashboard-v3.component.spec.ts` heading copy updated to "Release Command Center". `setup-wizard.component.spec.ts` added `overrideComponent` with shared `SetupWizardStateService` + stubbed `StepContentComponent` (NG0950 on required `step` input); relaxed saveDraftConfig/applyStep call assertions to accept the defaults-merge from `mergeSetupStepLocalDefaults`; the "progressed session w/o currentStep" test relaxed to the "not welcome" invariant (component now advances to next pending step rather than parking on last completed). `setup-wizard-live-api-wiring.behavior.spec.ts` got the same stub treatment. | Test Automation |
|
||||
| 2026-04-22 | FE-STAB4-004 PARTIAL. Scoped-spec verification: verdict-proof-panel 11/11, patch-diff-viewer 18/18, vex-hub 16/16, vex-hub-stats 11/11, simulation-dashboard 38/38, notify-panel 5/5, configuration-pane 33/33 + 5/5 in `src/tests/configuration_pane/`, dashboard-v3 combined 11/11, setup-wizard 12/12, setup-wizard live wiring 4/4 — all green locally. Zero component edits landed; all fixes are spec-side (test-harness overrides, selector alignment, copy alignment, assertion loosening for defaults-merge). Full-suite `npx vitest run --config vitest.codex.config.ts` was launched; at ~4275 lines of log and before wall-clock completion the partial tally was 923 passing / 285 failing across the fraction of the suite that had run. The residual ~285 failures are OUTSIDE the FE-STAB4 user-briefed scope (verdict-proof-panel/patch-diff-viewer/vex-hub/simulation-dashboard/notify-panel/configuration-pane/dashboard-v3/setup-wizard) and fall into the original sprint file's FE-STAB4-002 (orphan-revival NG0202), FE-STAB4-003 (evidence-drawer fade), plus broader drift in policy-governance/audit/admin-notifications/shadow-mode-api/simulation-api/policy-lint-api surfaces. CI is the final gate for those, per the FE-STAB3 precedent; closure of this sprint requires FE-STAB4-002 + FE-STAB4-003 + the broader residue to be addressed in a follow-up sprint. | Test Automation |
|
||||
| 2026-04-23 | FE-STAB4-002 DONE. Root cause: Vite/esbuild transform does not emit TS `emitDecoratorMetadata` for `OperatorOnlyDirective` / `AuditorOnlyDirective`, so Angular's JIT runtime fails to resolve `TemplateRef<any>` at dep index 0 (NG0202). Fix: migrated both directives from constructor-injection to `inject()` (modern Angular pattern, Angular-recommended since v14). Two file edits: `src/app/shared/directives/operator-only.directive.ts`, `src/app/shared/directives/auditor-only.directive.ts`. Evidence: `orphan-revival-regression-remediation.spec.ts` 7/7 green, `operator-only.directive.spec.ts` 3/3 green, `auditor-only.directive.spec.ts` 3/3 green. | Test Automation |
|
||||
| 2026-04-23 | FE-STAB4-003 DONE. Added "should reset copied state after 2-second fade" to `evidence-drawer.component.spec.ts` using `vi.useFakeTimers({ toFake: ['setTimeout', 'clearTimeout'] })` — fake only timers, leave microtasks real. This lets the spec await `navigator.clipboard.writeText` under real scheduling then advance the timer deterministically with `vi.advanceTimersByTime(1999/2000)` to assert sticky-then-flip. Evidence: `evidence-drawer.component.spec.ts` 38/38 green (was 37/37). | Test Automation |
|
||||
| 2026-04-23 | Policy-governance spec drift fixed incidentally (`policy-governance.component.spec.ts`): "should render 6 rationalized tabs" was stale — shipped component has 5 tabs (Audit was consolidated into `/ops/operations/audit`). Renamed test and dropped the "should include Audit tab" assertion to mirror the product direction. Tab-label extraction also normalized to strip badge digits (`Conflicts2` -> `Conflicts`). Evidence: 10/10 green. | Test Automation |
|
||||
| 2026-04-23 | FE-STAB4-004 BLOCKED and dispatched to `SPRINT_20260423_002_FE_web_residual_drift.md`. Rationale: partial full-suite rerun (killed mid-way after visible tail showed 15+ failing spec files across delta-verdict.service 13/20, reachability-slice 12/15, schema-playground 9/9, unknowns-queue 6/6, deploy-diff.service 7/15, plus policy-simulation cluster 42 failures across 4 files confirmed by scoped run) indicates residue that exceeds single-turn budget. Follow-up sprint files 7 tasks grouped by cluster (policy-simulation, lineage-http-mock, vex-hub-NG0303, reachability, services, misc, archival). FE-STAB4-001/002/003 remain DONE. | Test Automation |
|
||||
|
||||
## Decisions & Risks
|
||||
- Decision: test-setup.ts signal-input auto-enrichment + setInput fallback + jest shim + clipboard polyfill landed in 006 are the canonical infra. This sprint only fixes per-spec product-contract drift and specific harness bugs. If a new infra need surfaces, open a new sprint rather than expand this one.
|
||||
@@ -82,6 +90,9 @@ Completion criteria:
|
||||
- Decision (2026-04-22, FE-STAB4-003): `setup-wizard` sprint spec hit two genuine contract changes — (a) `saveDraftConfig` and `applyStep` now receive merged step-local defaults (not `{}`), (b) when the backend omits `currentStep`, the component advances to the first PENDING step rather than parking on the last completed one. Both are forward-compat improvements; tests loosened accordingly with inline rationale.
|
||||
- Sprint title vs. user task framing: The sprint file was authored with 4 tasks (verdict-proof-panel / orphan-revival / evidence-drawer fade / residue). The FE-STAB4 execution reframe delivered the verdict-proof-panel + broad drift (vex-hub, simulation-dashboard, notify-panel, configuration-pane, dashboard-v3, setup-wizard, patch-diff-viewer) in a single coherent pass. The sprint-file task IDs do NOT map 1:1 to what was delivered; the Execution Log documents the actual coverage. FE-STAB4-001 (verdict-proof-panel) is DONE; FE-STAB4-002 (orphan-revival NG0202) and FE-STAB4-003 (evidence-drawer fade) were NOT in the delivered scope and remain TODO — they should be addressed in a targeted follow-up sprint once the broader drift backlog is drained.
|
||||
- Note for archival: per §4.2, this sprint file should NOT be archived yet because FE-STAB4-002 + FE-STAB4-003 (as originally scoped) are still TODO. The full-suite rerun under FE-STAB4-004 will not be fully green until those two are closed.
|
||||
- Decision (2026-04-23, FE-STAB4-002): The `OperatorOnlyDirective` / `AuditorOnlyDirective` NG0202 was a genuine Vite/esbuild transform compatibility gap, not a product regression. The directives work fine at runtime (they use JIT in dev, and AOT-compiled metadata in prod). The fix — migrate from `constructor(private x: X)` to `x = inject(X)` — is the Angular-team-recommended pattern since v14 and removes the dependency on TS `emitDecoratorMetadata` emission by Vite. Two 6-line file edits; unlocks every spec that instantiates a component tree touching these directives. Recommend this pattern for any new structural directive.
|
||||
- Decision (2026-04-23, FE-STAB4-003): Mixing `vi.useFakeTimers()` with `async/await` is safe as long as the faked-methods set is scoped to `['setTimeout', 'clearTimeout']` — microtasks remain on the real scheduler so `await`s resolve normally. This pattern is documented in the FE-STAB5 sprint for reuse.
|
||||
- Decision (2026-04-23, archival): This sprint stays OPEN until FE-STAB5 drains the residue. FE-STAB4-001/002/003 are DONE; FE-STAB4-004 is BLOCKED pending FE-STAB5-001..007. Per §4.2, not moving to `docs-archived/implplan/`.
|
||||
|
||||
## Next Checkpoints
|
||||
- FE-STAB4-001/002/003 DONE.
|
||||
|
||||
109
docs/implplan/SPRINT_20260423_002_FE_web_residual_drift.md
Normal file
109
docs/implplan/SPRINT_20260423_002_FE_web_residual_drift.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# Sprint 20260423-002 — FE web residual expectation-drift cleanup
|
||||
|
||||
## Topic & Scope
|
||||
- Follow-up to SPRINT_20260422_008 (FE-STAB4). Absorbs the ~50+ spec files (estimated 200–285 individual test failures) that remain red after FE-STAB4-001/002/003 ship.
|
||||
- Same posture as FE-STAB4: pure spec-side (test harness / assertion / selector) fixes against the shipped component contracts. No test-infra changes (`test-setup.ts` / `test-setup.jasmine-bootstrap.ts`). No component edits unless the spec surfaces a genuine product regression — in which case open a product-side follow-up and mark the task BLOCKED.
|
||||
- Working directory: `src/Web/StellaOps.Web/` only.
|
||||
|
||||
## Dependencies & Concurrency
|
||||
- Upstream: SPRINT_20260422_008 (FE-STAB4-001/002/003 DONE; FE-STAB4-004 reframed as "dispatch residue to this sprint").
|
||||
- Safe parallelism: each spec cluster below is independent; dispatch one owner per cluster.
|
||||
|
||||
## Documentation Prerequisites
|
||||
- `docs/code-of-conduct/TESTING_PRACTICES.md` (binding).
|
||||
- `src/Web/AGENTS.md`.
|
||||
- `SPRINT_20260422_008_FE_web_deep_drift_cleanup.md` — Decisions & Risks section documents the drift patterns already resolved (copy alignment, tab rationalization, defaults-merge, NG0202 inject() migration).
|
||||
|
||||
## Delivery Tracker
|
||||
|
||||
### FE-STAB5-001 — policy-simulation cluster
|
||||
Status: TODO
|
||||
Dependency: none
|
||||
Owners: Developer / Implementer
|
||||
Task description:
|
||||
- At least 42 failures across:
|
||||
- `src/app/features/policy-simulation/policy-simulation.component.spec.ts`
|
||||
- `src/app/features/policy-simulation/policy-lint.component.spec.ts`
|
||||
- `src/app/features/policy-simulation/shadow-mode-dashboard.component.spec.ts`
|
||||
- `src/app/features/policy-simulation/shadow-mode-indicator.component.spec.ts`
|
||||
- Investigate with `npx vitest run --config vitest.codex.config.ts <spec>` and classify per-spec: copy drift, selector drift, API-shape drift, or real product regression.
|
||||
|
||||
Completion criteria:
|
||||
- [ ] All specs green, or BLOCKED with a product-side issue linked.
|
||||
|
||||
### FE-STAB5-002 — lineage / SBOM HTTP-testing "Expected no open requests"
|
||||
Status: TODO
|
||||
Dependency: none
|
||||
Owners: Developer / Implementer
|
||||
Task description:
|
||||
- `lineage-compare-routing.guard.spec.ts` and peers fail with `HttpTestingController` "Expected no open requests" (~6+ instances seen: `/api/sbomservice/api/v1/lineage/compare`, `/api/gate/history`). Either a missing `httpMock.expectOne(...).flush(...)` in setup, or the component now issues an extra request post-refactor.
|
||||
- Likely one shared fixture fix unblocks the cluster.
|
||||
|
||||
Completion criteria:
|
||||
- [ ] `httpMock.verify()` passes for all lineage / SBOM guard specs.
|
||||
|
||||
### FE-STAB5-003 — vex-hub-source-contract NG0303 drift
|
||||
Status: TODO
|
||||
Dependency: none
|
||||
Owners: Developer / Implementer
|
||||
Task description:
|
||||
- `src/app/features/vex-hub/vex-hub-source-contract.spec.ts` throws `NG0303: Can't bind to 'term' since it isn't a known property of 'span'`. The spec likely registers a `stella-glossary` directive stub that was removed, or the component now binds `[attr.term]` instead of `[term]`.
|
||||
|
||||
Completion criteria:
|
||||
- [ ] Spec green; assertion covers the shipped binding.
|
||||
|
||||
### FE-STAB5-004 — reachability-slice / risk clusters
|
||||
Status: TODO
|
||||
Dependency: none
|
||||
Owners: Developer / Implementer
|
||||
Task description:
|
||||
- `src/app/features/risk/components/reachability-slice.component.spec.ts` (12/15 failing). Spec asserts against a template that has been partially restructured — selector classes (`entry`, `sink`, `node`), emit events (`nodeClicked`), and compact-mode layout. Likely a single template-class-name drift.
|
||||
|
||||
Completion criteria:
|
||||
- [ ] Spec green end-to-end.
|
||||
|
||||
### FE-STAB5-005 — delta-verdict.service + other service-layer residue
|
||||
Status: TODO
|
||||
Dependency: none
|
||||
Owners: Developer / Implementer
|
||||
Task description:
|
||||
- `src/app/core/services/delta-verdict.service.spec.ts` (13/20 failing) plus `deploy-diff.service.spec.ts` (7/15), `user-preferences.service.spec.ts` (1/11), `configuration-pane-state.service.spec.ts` (1/48). Typically localStorage shape drift or computed-signal return-shape drift.
|
||||
|
||||
Completion criteria:
|
||||
- [ ] All service specs green.
|
||||
|
||||
### FE-STAB5-006 — miscellaneous component residue
|
||||
Status: TODO
|
||||
Dependency: none
|
||||
Owners: Developer / Implementer
|
||||
Task description:
|
||||
- Remaining cluster (~15+ files): `score-pill`, `clients-list`, `language-settings-page`, `workspace-toggle`, `schema-playground` (9/9 failing — likely same root cause), `unknowns-queue` (6/6), `impact-first-vulnerability-detail`, `causal-lanes`, and whatever surfaces the full-suite rerun identifies.
|
||||
- Run `npx vitest run --config vitest.codex.config.ts --reporter=default` and tee to a file; classify by root-cause signature; batch identical-cause fixes.
|
||||
|
||||
Completion criteria:
|
||||
- [ ] Full suite green.
|
||||
|
||||
### FE-STAB5-007 — full-suite green + archive 008 and this sprint
|
||||
Status: TODO
|
||||
Dependency: FE-STAB5-001..006
|
||||
Owners: Test Automation
|
||||
Task description:
|
||||
- Run `npx vitest run --config vitest.codex.config.ts` end-to-end; attach tally to Execution Log; archive SPRINT_20260422_008 and this sprint.
|
||||
|
||||
Completion criteria:
|
||||
- [ ] Full-suite tally captured (all passing).
|
||||
- [ ] SPRINT_20260422_008 moved to `docs-archived/implplan/`.
|
||||
- [ ] This sprint moved to `docs-archived/implplan/`.
|
||||
|
||||
## Execution Log
|
||||
| Date (UTC) | Update | Owner |
|
||||
| --- | --- | --- |
|
||||
| 2026-04-23 | Sprint created by FE-STAB4 closeout. FE-STAB4-001/002/003 DONE; residue surfaced by a partial full-suite rerun (killed after ~15 failing spec files visible in tail-400 output) dispatched to this follow-up. Known signatures: NG0303 on vex-hub-source-contract; HttpTestingController "Expected no open requests" across lineage guards; copy/selector drift across policy-simulation surfaces. | Test Automation |
|
||||
|
||||
## Decisions & Risks
|
||||
- The NG0202 drift on `OperatorOnlyDirective` / `AuditorOnlyDirective` was resolved in 008 by migrating both directives from constructor-injection to `inject()`. This is a standing pattern for any future structural directive; prefer `inject()` to avoid Vite/esbuild decorator-metadata emit gaps.
|
||||
- The evidence-drawer 2-second fade assertion now uses `vi.useFakeTimers({ toFake: ['setTimeout', 'clearTimeout'] })` to fake only timers while real microtasks drain the `await navigator.clipboard.writeText`. This pattern is reusable for any other spec mixing clipboard/promise with timer-backed fade state.
|
||||
|
||||
## Next Checkpoints
|
||||
- FE-STAB5-001..006 DONE (residue drained).
|
||||
- FE-STAB5-007 DONE: full suite green; both sprints archived.
|
||||
Reference in New Issue
Block a user