docs(10): re-verify after quick-261011-mag, hygiene closed, gaps_found on --all go stage

This commit is contained in:
2026-10-11 16:29:35 +02:00
parent 6c7434243e
commit fc7cfaf51c

View File

@@ -1,8 +1,8 @@
---
phase: 10-admin-vue-spa
verified: 2026-10-11T13:53:00Z
verified: 2026-10-11T14:32:00Z
status: gaps_found
score: "4/4 roadmap success criteria hold in substance; plan truths 43/46 (3 failed, one root cause: the Phase 10 hygiene gate is red at HEAD after later phases added SPA files)"
score: "4/4 roadmap success criteria hold; plan truths 45/46 (1 failed: the phase acceptance command check-phase10.sh --all is red at its --go stage, for causes outside Phase 10 code)"
covered_files:
- ".gitignore"
- ".planning/phases/10-admin-vue-spa/10-01-PLAN.md"
@@ -85,6 +85,8 @@ covered_files:
- "admin/src/views/NotFoundView.vue"
- "admin/src/views/SettingsFormView.vue"
- "admin/src/views/SettingsIndexView.vue"
- "admin/tests/account/ApiTokenCreateDialog.test.ts"
- "admin/tests/account/ApiTokensPanel.test.ts"
- "admin/tests/app/client.test.ts"
- "admin/tests/app/controllerRoutes.test.ts"
- "admin/tests/app/i18n.test.ts"
@@ -106,14 +108,17 @@ covered_files:
- "admin/tests/fixtures/widgets.relation-candidates.json"
- "admin/tests/fixtures/widgets.relation-linked.json"
- "admin/tests/fixtures/widgets.relation-schema.json"
- "admin/tests/form/FileCaptionModal.test.ts"
- "admin/tests/form/FormField.test.ts"
- "admin/tests/form/FormGrid.test.ts"
- "admin/tests/form/FormTabs.test.ts"
- "admin/tests/form/FormView.test.ts"
- "admin/tests/form/MLField.test.ts"
- "admin/tests/form/RelationField.test.ts"
- "admin/tests/form/Settings.test.ts"
- "admin/tests/form/fields.test.ts"
- "admin/tests/form/formState.test.ts"
- "admin/tests/form/mlLocale.test.ts"
- "admin/tests/form/registry.test.ts"
- "admin/tests/helpers.ts"
- "admin/tests/list/CellValue.test.ts"
@@ -219,7 +224,7 @@ covered_files:
- "scripts/check-admin-dist.sh"
- "scripts/check-admin-openapi.sh"
- "scripts/check-phase10.sh"
covered_digest: "v2:sha256:fd0f803078fe0f4843d26e78ff531ce7b6f2271a193aac732dbd6b3ba7272a9b"
covered_digest: "v2:sha256:5507fd87e64537741dc9c3ffffadce6ff2e21e1366c2ee6364878edc4c54c356"
behavior_unverified: 0
overrides_applied: 0
mvp_mode_note: "ROADMAP marks Phase 10 mode: mvp, but the goal is not a User Story. Following the Phase 1/3/5/8 precedent, the four ROADMAP success criteria are the contract and User Flow Coverage is derived from them."
@@ -228,53 +233,44 @@ decision_coverage:
total: 28
not_honored: []
re_verification:
previous_status: human_needed
previous_score: "4/4 roadmap success criteria verified by automated evidence (plan truths 46/46; 1 browser re-check pending)"
previous_head: c05ad09
reason: "Stale (covered_changed): 76 covered files changed between c05ad09 and 07e579a (phases 10.1, 12.2, 14.2.1, 16.1, 16.2, 16.3 and admin quick fixes). The two content-hashed bundles are now index-BeX-076N.css / index-CXQZEJp2.js."
gaps_closed: []
gaps_remaining: []
previous_status: gaps_found
previous_score: "4/4 roadmap success criteria hold in substance; plan truths 43/46 (3 failed, one root cause: the Phase 10 hygiene gate is red at HEAD)"
previous_head: 07e579a
head: 6c74342
reason: "Gap closure by quick task 261011-mag (42b5cf8 gate exemption and self-test plants, 1541cd4 direct-import tests). Only scripts/check-phase10.sh and five admin test files changed since 07e579a; admin/src, modules/ and modules/boardwalk/dist are unchanged."
gaps_closed:
- "SC-4 mechanical enforcement: scripts/check-phase10.sh --hygiene passes"
- "Every .ts and .vue file under admin/src except main.ts, api/schema.d.ts and env.d.ts is imported by at least one test file"
- "--self-test proves each detector fails closed (self-test now exit 0, with new xhr and apifile plants)"
gaps_remaining:
- "scripts/check-phase10.sh --all is green at HEAD (now red at the --go stage; previously masked because --self-test, the first stage, already failed)"
regressions:
- "scripts/check-phase10.sh --hygiene and --self-test exit 1 at HEAD (first broken by ea33296, 12.2-04, 2026-10-02, after the 2026-10-01 full gate run; the 2026-10-05 refresh only recomputed the digest)."
- "10-05 truth 'both repositories pass go vet ./... and go test ./...' was carried from baseline in the previous report without a run. Running the gate's --go stage this session fails it: the framework run is refused for the opt-in skip of modules/sunrise TestBootstrapEndToEnd (cfd110e, 14.3-02, 2026-10-08), and the app run fails git.golem15.com/golem15/sm-user-plugin/updates TestCreateOrganisationsMigration (history test not updated after f0d3b8b, 14.1-02, 2026-10-05)."
gaps:
- truth: "SC-4 mechanical enforcement: scripts/check-phase10.sh --hygiene passes (admin/src/api holds only schema.d.ts, client.ts and types.ts; no file other than api/client.ts calls the network directly)"
status: failed
reason: "Phase 12.2-04 (ea33296) added admin/src/api/files.ts, which uploads through XMLHttpRequest for progress events. The hygiene stage refuses it twice: 'direct fetch outside admin/src/api/client.ts: admin/src/api/files.ts:150' and 'unexpected files in admin/src/api: admin/src/api/files.ts'. The substance of SC-4 holds (files.ts types every wire shape through the generated aliases FileItem, FileMutationResult, AdminFileCaptionRequest, ErrorBody from types.ts and reuses the client's X-Requested-With and refresh), but the gate was never updated, unlike the precedents for MarkdownField v-html (27711b7) and listState storage (9cac45c)."
- truth: "scripts/check-phase10.sh --all, the phase acceptance command, passes at HEAD: both repositories pass go vet ./... and go test ./... with no unexpected skip (10-05 must-haves)"
status: partial
reason: "--self-test, --hygiene, --security, --postgres, --openapi, --dist and --evidence all exit 0 this session, and Vitest plus typecheck pass. The --go stage exits 1 for two drifts introduced after Phase 10, neither in Phase 10 code: (a) summercms.go go test ./... exits 0 but includes the env-gated skip 'set SUMMERCMS_BOOTSTRAP_CHECK=1 to run the bootstrap script end to end' in modules/sunrise TestBootstrapEndToEnd (cfd110e, 14.3-02), and the Phase 10 detector refuses every unexpected skip; (b) in fonoteka.go, git.golem15.com/golem15/sm-user-plugin/updates TestCreateOrganisationsMigration fails because its expected migration history lacks 202610050001_create_oauth_identities (added by f0d3b8b, 14.1-02). The detectors themselves behave as designed: they caught both."
artifacts:
- path: "scripts/check-phase10.sh"
issue: "hygiene_checks has no allowlist entry for admin/src/api/files.ts (XHR upload) or for the api/ directory listing"
- path: "admin/src/api/files.ts"
issue: "direct XMLHttpRequest outside client.ts; a fourth file in admin/src/api"
issue: "run_go has no expected-skip entry for the framework's opt-in TestBootstrapEndToEnd; the APP_PENDING_SKIPS/PHASE10_EXPECT_SKIP mechanism exists but is only used for the app run"
- path: "../fonoteka.go/plugins/golem15/user/updates/organisations_test.go"
issue: "want list stops at 202610040003_create_frontend_permissions; the run also applies 202610050001_create_oauth_identities"
missing:
- "Either allowlist admin/src/api/files.ts in both hygiene rules (narrow pattern for the single 'new XMLHttpRequest()' line, as done for MarkdownField and listState), or move the XHR upload behind client.ts; record the decision in the 12.2 or 10 notes"
- truth: "Every .ts and .vue file under admin/src except main.ts, api/schema.d.ts and env.d.ts is imported by at least one test file (10-05 Task 1, checked by the hygiene stage)"
status: failed
reason: "Five later-phase files are imported by no test file: admin/src/components/account/ApiTokenCreateDialog.vue and ApiTokensPanel.vue (16.3-02), admin/src/components/form/fields/FileCaptionModal.vue (12.2-04), admin/src/components/form/fields/MLField.vue (a913eec), admin/src/components/form/mlLocale.ts (14.2.1-03). The two account components are exercised indirectly (admin/tests/account/*.test.ts mount the app at /account), but the rule requires a direct import."
artifacts:
- path: "admin/tests"
issue: "no test imports src/components/account/ApiTokenCreateDialog, src/components/account/ApiTokensPanel, src/components/form/fields/FileCaptionModal, src/components/form/fields/MLField or src/components/form/mlLocale"
missing:
- "Add a direct import (a focused component/unit test) for each of the five files, e.g. import ApiTokensPanel in admin/tests/account/ApiTokensPanel.test.ts"
- truth: "scripts/check-phase10.sh --all is the phase acceptance command and --self-test proves each detector fails closed"
status: failed
reason: "--self-test exits 1 with 'refuse: self-test hygiene rejected the clean scratch copy', because the scratch copy of HEAD already carries the two violations above. --all therefore cannot pass. The detectors themselves still work (they caught real drift); the stage goes green once the two gaps above are closed."
artifacts:
- path: "scripts/check-phase10.sh"
issue: "self-test and all stages red at HEAD as a consequence of gaps 1 and 2"
missing:
- "Close gaps 1 and 2, then re-run scripts/check-phase10.sh --self-test and --hygiene"
- "check-phase10.sh run_go: accept exactly the modules/sunrise TestBootstrapEndToEnd skip with its SUMMERCMS_BOOTSTRAP_CHECK text (PHASE10_EXPECT_SKIP plus PHASE10_SKIP_TEXT for the ROOT run, or -skip '^TestBootstrapEndToEnd$' with a comment pointing at check-phase14.3.sh, which runs it for real), and prove it in --self-test as the existing pending-skip cases do"
- "sm-user-plugin: add 202610050001_create_oauth_identities to TestCreateOrganisationsMigration's want list, commit and push in that repo, then bump the plugins/golem15/user pointer in fonoteka.go as a separate commit"
- "Re-run scripts/check-phase10.sh --all (or --go) and record the result"
human_verification:
- test: "Re-walk the Phase 10 admin flows in a real browser on the current build: run the fonoteka binary, open /plytadmin as a superuser and as a genres-only admin, then use the list and form of each of the five controllers (search, sort, filter, paging, save, 422 field errors), link and unlink a Collection editor, open Ustawienia, and glance at light and dark mode."
expected: "Everything still behaves as approved in 10-UAT.md tests 2 to 5. The limited admin sees only fonoteka > Genres. Lists and forms render. The editor round trip works. The Albums form's later widgets, partials and field types do not break the Phase 10 form; list state persisted in the URL and storage does not confuse paging or filtering."
why_human: "10-UAT.md was approved on 2026-09-27 against c7487f6. Since then phases 10.1, 12.2, 14.2.1, 16.1, 16.2 and 16.3 changed ListView.vue (+97), FormView.vue, FormField.vue, formState.ts, registry.ts, AppShell.vue, PluginRail.vue, UserMenu.vue, useAuth.ts and main.css. Vitest and the Postgres acceptance test cover behavior, but D-23 keeps the real browser out of the automated suite. 10.1-UAT.md (tests 1 and 4) is still status: testing with all items pending; closing those with Genres, Collections and Settings included also closes this item."
why_human: "10-UAT.md was approved on 2026-09-27 against c7487f6. Since then phases 10.1, 12.2, 14.2.1, 16.1, 16.2 and 16.3 changed ListView.vue, FormView.vue, FormField.vue, formState.ts, registry.ts, AppShell.vue, PluginRail.vue, UserMenu.vue, useAuth.ts and main.css. Vitest and the Postgres acceptance test cover behavior, but D-23 keeps the real browser out of the automated suite. 10.1-UAT.md is still status: testing with all six items pending; closing its tests 1 and 4 with Genres, Collections and Settings included also closes this item. Quick 261011-mag did not touch admin/src, so this item is unchanged."
- test: "Carried: decide CR-01 (refresh ignores tokens_valid_after / is_activated)"
expected: "Fix now or accept with override"
why_human: "Security-policy decision"
resolution: "Fixed (be4a923, a13a121), approved in 10-UAT.md test 1. TestAdminRefreshRevocation re-run this session: PASS."
resolution: "Fixed (be4a923, a13a121), approved in 10-UAT.md test 1. TestAdminRefreshRevocation passes in this session's --security/--evidence run."
- test: "Carried: Secure cookie on http://localhost (assumption A3)"
expected: "Chrome and Firefox store summer_admin with default cookie_secure"
why_human: "Browser cookie policy, non-inferable"
resolution: "Approved in 10-UAT.md test 6. auth.go change since c05ad09 is only the /auth/me profile builder (profileFor with avatar); cookie attributes untouched."
resolution: "Approved in 10-UAT.md test 6. No auth.go or cookie change since the previous report."
- test: "Carried: review the 17 judgment-tier prohibitions"
expected: "Accept or reject the verifier's non-authoritative verdicts"
why_human: "Judgment-tier prohibitions need human resolution"
@@ -291,20 +287,66 @@ human_verified:
# Phase 10: Admin Vue SPA Verification Report
**Phase Goal:** A minimal Vue 3 + TypeScript admin SPA renders login, permission-gated navigation, lists, forms and the relation manager for Albums, Artists, Collections, Genres and Styles, typed from the generated OpenAPI document.
**Verified:** 2026-10-11T13:53:00Z (summercms.go HEAD 07e579a, fonoteka.go HEAD e074028)
**Verified:** 2026-10-11T14:32:00Z (summercms.go HEAD 6c74342, fonoteka.go HEAD e074028 with the plugins/golem15/user submodule checked out at 7a6fa0e, uncommitted; recorded pointer cf5c6b9 differs only in go.mod)
**Status:** gaps_found
**Re-verification:** Yes (quick mode). The previous report (c05ad09, human_needed) went stale because 76 covered files changed.
**Re-verification:** Yes, after quick task 261011-mag closed the three hygiene gaps of the 07e579a report.
## What changed since c05ad09
## What changed since 07e579a
| Source | Covered code touched | Effect |
| Commit | Files | Effect |
|---|---|---|
| 12.2-04 (ea33296) | adds `admin/src/api/files.ts` (XHR upload) and `FileCaptionModal.vue` | Phase 10 hygiene gate goes red (gaps 1-3) |
| 14.2.1 (a04116d, a913eec) | `mlLocale.ts`, `MLField.vue`, `MarkdownField.vue` (sanitized v-html, gate allowlisted in 27711b7) | `mlLocale.ts`, `MLField.vue` imported by no test (gap 2) |
| 16.1 / quick fixes (9cac45c, cd25af0) | list state kept in URL and localStorage (`listState.ts`), gate allowlisted | Storage rule still enforced; no token stored (comment and code checked) |
| 16.2 (717d46e..4adb48a) | plugin field types: cabana `form_schema.go`, `registry.go`, `pact/capabilities.go`, `FormField.vue`, `formState.ts`, `registry.ts` | Phase 10 tests still pass |
| 16.3 (b9273c1..b45af8e) | API tokens: cabana `http.go`, `contracts.go`, `admin_openapi.go`, `ApiTokensPanel.vue`, `ApiTokenCreateDialog.vue`; OpenAPI and `schema.d.ts` regenerated; `types.ts` +12 aliases | Two components imported by no test (gap 2); types.ts still aliases only |
| My account / avatars (143eca5, 64d21c8), shell fixes | `auth.go` `/auth/me` profile via `profileFor`, `UserMenu.vue`, `AppShell.vue`, `PluginRail.vue`, `Breadcrumbs.vue`, `useAuth.ts` | Phase 10 Go tests and fonoteka acceptance pass |
| 42b5cf8 | `scripts/check-phase10.sh` | Network rule exempts one line-anchored statement in `admin/src/api/files.ts`; api-listing rule exempts the exact path `admin/src/api/files.ts`; self-test gains `xhr` and `apifile` plants |
| 1541cd4 | `admin/tests/form/{mlLocale,MLField,FileCaptionModal}.test.ts` (new), `admin/tests/account/{ApiTokensPanel,ApiTokenCreateDialog}.test.ts` (extended) | Direct imports and behavior assertions for the five untested modules |
| 6c74342 | planning docs | none on code |
`git diff 07e579a HEAD` touches no file under `admin/src`, `modules/` or `modules/boardwalk/dist`.
## Gap closure
### Gap 1 (closed): SC-4 hygiene rule vs `admin/src/api/files.ts`
`bash scripts/check-phase10.sh --hygiene`: `phase10 hygiene passed`, exit 0.
**Is the exemption narrow?** Yes. I reproduced the gate's `hygiene_checks` on a scratch copy of the hygiene directories and planted violations next to the exemption:
| Plant (scratch copy) | Result |
|---|---|
| clean copy | exit 0 |
| `fetch("/y")` appended to `admin/src/api/files.ts` | refused: `direct fetch outside admin/src/api/client.ts: admin/src/api/files.ts:320` |
| a second, inline `const r = new XMLHttpRequest()` in `files.ts` | refused (the filter is anchored to the whole line `const request = new XMLHttpRequest()`) |
| `admin/src/api/sub/files.ts` (same name, other path) | refused three ways: direct fetch, `unexpected files in admin/src/api`, imported by no test (the listing rule uses `-path`, not `-name`) |
| the exact exempted line in `admin/src/components/x.ts` | refused: direct fetch (the filter is anchored to the path `admin/src/api/files.ts`) |
The one residual hole is a second byte-identical `const request = new XMLHttpRequest()` line inside `files.ts`; that matches the precision of the accepted MarkdownField (27711b7) and listState (9cac45c) precedents.
**Is it justified?** Yes. The single XHR exists because only XHR reports upload progress (`files.ts:7`, `uploadWithProgress`). It sends `X-Requested-With` from `client.ts`'s `REQUESTED_WITH`, refreshes through `client.ts`'s `refreshSession`/`reportUnauthorized`, and every wire shape is a generated alias imported from `./types` (`FileItem`, `FileMutationResult`, `AdminFileCaptionRequest`, `ErrorBody`, `ControllerParams`). The adapter types `files.ts` declares (`FileCallResult`, `UploadResult`, `UploadHandle`, `FileRoutes`, the local `TypedResult` envelope) describe client-side results, not server payloads. The `types.ts` alias-only rules are unchanged. SC-4's "no hand-maintained duplicate type" still holds, and the gate now records the exception with a reason instead of being red.
### Gap 2 (closed): every SPA module imported by a test
The hygiene stage's import rule passes. Direct imports confirmed: `tests/form/FileCaptionModal.test.ts:11`, `tests/form/MLField.test.ts:9,12`, `tests/form/mlLocale.test.ts:10`, `tests/account/ApiTokenCreateDialog.test.ts:3`, `tests/account/ApiTokensPanel.test.ts:3`. The tests assert behavior rather than just importing (19, 16 and 19 `expect` calls in the three new form tests; the account tests assert request counts, POST bodies, emitted events and DOM state). `npx vitest run` on the five files: 5 files, 61 tests passed.
### Gap 3 (partly closed): `--self-test` and `--all`
`bash scripts/check-phase10.sh --self-test`: `phase10 self-test passed`, exit 0. The plant loop now covers `vhtml fetch appname storage xhr apifile`, and each plant must be refused for its own rule. The `--self-test` half of the truth is verified.
The `--all` half is not. Docker was available, so I ran the stages `--all` chains (except `--spa`'s `npm ci`, replaced by a direct typecheck and Vitest run so the shared `admin/node_modules` of concurrent sessions was not reinstalled):
| Stage | Result |
|---|---|
| `--self-test` | exit 0 |
| `--go` | **exit 1** (see below) |
| `--security`, `--postgres`, `--openapi` (via `--evidence`) | exit 0, `phase10 evidence passed` |
| `--spa` (equivalent) | `npm run typecheck` exit 0; `npm test` 83 files, 1279 tests passed |
| `--dist` (`check-admin-dist.sh`) | exit 0 |
| `--hygiene` | exit 0 |
| `--evidence` | exit 0 |
`--go` refusals:
1. `refuse: skipped git.golem15.com/golem15/summercms/modules/sunrise TestBootstrapEndToEnd` then `refuse: go test ./... in .../summercms.go (test=0 detect=2)`. The framework's `go vet ./...` and `go test ./...` themselves pass (test exit 0). The skip is the opt-in guard `SUMMERCMS_BOOTSTRAP_CHECK=1` added by cfd110e (14.3-02, 2026-10-08); `check-phase14.3.sh` runs that test for real. The Phase 10 detector refuses any skip it was not told to expect.
2. With the framework half bypassed (gate functions sourced, same detector and env): fonoteka `go vet` passes, then `refuse: failed git.golem15.com/golem15/sm-user-plugin/updates TestCreateOrganisationsMigration`. Re-run alone: `organisations_test.go:54: history = [... 202610040003_create_frontend_permissions 202610050001_create_oauth_identities]`. The test's `want` list was not updated when f0d3b8b (14.1-02, 2026-10-05) added the OAuth identities migration. The submodule working tree is at 7a6fa0e (an uncommitted pointer bump from another session), but `git diff cf5c6b9 7a6fa0e` is `go.mod` only, so the recorded pointer fails the same way.
Neither cause is Phase 10 code, and both detectors did exactly what 10-05 asked of them. Still, the phase acceptance command is red at HEAD and the 10-05 truth "both repositories pass go vet ./... and go test ./..." is not met by the command that is meant to prove it. The previous report carried that truth from baseline without running it; this run evidences the failure with named tests, so it blocks.
## Goal Achievement
@@ -312,75 +354,70 @@ human_verified:
| # | Truth | Status | Evidence (this session) |
|---|---|---|---|
| 1 | An admin logs in through the SPA and sees only the navigation items their permissions allow. | ✓ VERIFIED | fonoteka `TestPhase10AssembledAcceptance` PASS (exact nav sets for limited admin and developer, 403 on albums for the limited admin). cabana `TestNavigationDropsDeniedParentAndRepointsTarget`, `TestAdminRefreshRevocation`, `TestAdminLogoutRevokesExpiredRefreshableToken`, `TestPhase10*` PASS. SPA nav/auth Vitest is in the orchestrator's parallel regression run. |
| 2 | Each of the five controllers renders a working list and form generated from its JSON schema. | ✓ VERIFIED | `TestPhase10Controllers` and SC-2 loop of `TestPhase10AssembledAcceptance` PASS; `TestCRUDOperationsFollowDeclarations` PASS. `ListView.vue`/`FormView.vue` still load `/schema/list`, `/schema/form` and records through the typed client. Browser re-check of the changed views remains the open human item. |
| 3 | The Collections form's relation manager lets an admin search, link and unlink an editor. | ✓ VERIFIED | SC-3 block of `TestPhase10AssembledAcceptance` PASS. `RelationManager.vue` and `RelationPickerModal.vue` unchanged since c05ad09. |
| 4 | API calls in the SPA use TypeScript types generated from the OpenAPI document, with no hand-maintained duplicate type. | ✓ VERIFIED (substance) | `client.ts` is `createClient<paths>`; no `fetch(` elsewhere in `admin/src`. `types.ts` still contains only aliases (new 16.2/16.3 aliases onto `Schemas['cabana.*']`). `files.ts` types all wire shapes through those aliases; its XHR exists only for upload progress. `check-admin-openapi.sh --check`: exit 0. The mechanical gate for this SC is red, see gaps. |
| 1 | An admin logs in through the SPA and sees only the navigation items their permissions allow. | ✓ VERIFIED | `--postgres` (via `--evidence`) passes `TestPhase10AssembledAcceptance`, `TestPhase10AdminAuth`, `TestPhase10TracerSPA`; `--security` passes `TestPhase10CookieAuth`, `TestPhase10CSRF`, `TestPhase10CookieGuard`, `TestPhase10CollectionOwnerReadOnly`. Full Vitest green. No `admin/src` change since the previous report. |
| 2 | Each of the five controllers renders a working list and form generated from its JSON schema. | ✓ VERIFIED | `TestPhase10Controllers` and the SC-2 block of `TestPhase10AssembledAcceptance` pass. Browser re-check of the views changed by later phases stays the open human item. |
| 3 | The Collections form's relation manager lets an admin search, link and unlink an editor. | ✓ VERIFIED | `TestPhase10AlbumRelations`, `TestPhase10RelationOptions`, `TestPhase10RelationSave` and the SC-3 block of the assembled acceptance pass. |
| 4 | API calls in the SPA use TypeScript types generated from the OpenAPI document, with no hand-maintained duplicate type. | ✓ VERIFIED | `--hygiene` exit 0 (mechanical gate now green, exemption judged narrow and justified above). `check-admin-openapi.sh --check` exit 0; `TestPhase10OpenAPIConformance`, `TestPhase09ContractInventory` pass; `types.ts` alias-only rules unchanged. |
**Score:** 4/4 ROADMAP truths hold in substance. Plan truths 43/46: three 10-05 truths about the phase gate fail (one root cause).
**Score:** 4/4 ROADMAP truths verified. Plan truths 45/46 (0 present, behavior-unverified).
### Plan must-have truths
The 43 truths not listed in `gaps` are carried from the baseline: their named tests were re-run this session where they touch changed code (cabana, phrasebook, surf, boardwalk Phase 10 tests; fonoteka Postgres acceptance; dist and OpenAPI drift gates; `--security`), and the rest sit in Vitest, which the orchestrator runs in parallel.
| Truth (10-05) | Status | Evidence |
|---|---|---|
| SC-4 hygiene: `admin/src/api` holds only schema.d.ts, client.ts, types.ts; no direct network call outside client.ts | ✗ FAILED | `check-phase10.sh --hygiene` exit 1: `admin/src/api/files.ts:150 new XMLHttpRequest()`, `unexpected files in admin/src/api: admin/src/api/files.ts` |
| Every `admin/src` .ts/.vue (except main.ts, schema.d.ts, env.d.ts) imported by a test | ✗ FAILED | `--hygiene`: ApiTokenCreateDialog.vue, ApiTokensPanel.vue, FileCaptionModal.vue, MLField.vue, mlLocale.ts "imported by no test" |
| `--all` is the acceptance command; `--self-test` proves detectors fail closed | ✗ FAILED | `--self-test` exit 1: "self-test hygiene rejected the clean scratch copy" |
| SC-4 hygiene: `admin/src/api` holds only the generated schema, client, aliases (and now the files.ts adapters); no direct network call outside client.ts | ✓ VERIFIED | `--hygiene` exit 0; scratch plants above |
| Every `admin/src` .ts/.vue (except main.ts, schema.d.ts, env.d.ts) imported by a test | ✓ VERIFIED | `--hygiene` exit 0; five direct imports listed above; 61 tests pass |
| `--all` exits non-zero on any failing stage, a zero-test run or a skip, drift, a hygiene violation or an evidence gap; `--self-test` proves each detector fails closed | ✓ VERIFIED | `--self-test` exit 0; the live `--go` run refused a skip and a failure as designed |
| Every Phase 10 Go change has named tests, and both repositories pass go vet ./... and go test ./... | ✗ FAILED (gate) | `--go` exit 1: sunrise opt-in skip refused; sm-user-plugin `TestCreateOrganisationsMigration` fails. Named Phase 10 tests all pass. |
| TestPhase10AssembledAcceptance proves SC-1..SC-4 | ✓ VERIFIED | `--postgres` exit 0 |
Backstop truths (A1 prefix, A3 cookie, A10 blacklist grace, A8 pivot order, required-relation hint, A6 dark mode) are unchanged: their source files are untouched in substance and the A3 approval (10-UAT test 6) carries over.
The remaining 41 plan truths are carried from the baseline. Their code is unchanged since 07e579a, and the stages that cover them (`--security`, `--postgres`, `--openapi`, `--dist`, `--hygiene`, full Vitest, typecheck) passed this session.
Backstop truths (A1 prefix, A3 cookie, A10 blacklist grace, A8 pivot order, required-relation hint, A6 dark mode) are unchanged; the A3 approval (10-UAT test 6) carries over.
### Prohibitions (judgment tier)
Accepted in 10-UAT.md test 7, re-checked at HEAD:
- No consumer application names in `admin/src`, `admin/tests`, `admin/openapi`, `modules/boardwalk/dist` (grep empty).
- Raw HTML: one `v-html` in `admin/src` (`MarkdownField.vue:128`, `sanitizedHtml`, set only from the server's 2xx sanitized answer, allowlisted in the gate by 27711b7, Phase 14.2.1 scope). Plugin labels and comments are still rendered as text.
- Browser storage holds the sidebar flag and per-list query state only; `listState.ts` documents and implements no token or record data.
- `modules/boardwalk/dist` references no foreign origin (`--hygiene` reached and passed that rule; only the rules in `gaps` fired).
- Cookie login/refresh never return the JWT in a body (`TestPhase10CookieAuth` in `--security` PASS).
All 17 remain not violated.
Accepted in 10-UAT.md test 7, re-checked at HEAD through the green `--hygiene` stage: no consumer application names in `admin/src`, `admin/tests`, `admin/openapi`, `modules/boardwalk`, `modules/cabana`, `modules/phrasebook`; one allowlisted `v-html` (`MarkdownField.vue`, `sanitizedHtml`); browser storage only in `useSidebar.ts` and `listState.ts`; no foreign origin in `modules/boardwalk/dist`; cookie login/refresh never return the JWT in a body (`TestPhase10CookieAuth` pass). All 17 remain not violated.
### Required Artifacts
| Artifact | Status | Details |
|---|---|---|
| `admin/` SPA | ✓ VERIFIED | Embedded via `modules/boardwalk/dist`; `check-admin-dist.sh` exit 0 (bundles index-BeX-076N.css, index-CXQZEJp2.js) |
| `admin/openapi/admin.json`, `schema.d.ts`, `types.ts` | ✓ VERIFIED | `check-admin-openapi.sh --check` exit 0; types.ts alias-only |
| `modules/cabana/*`, `modules/bouncer/*`, `modules/pact/capabilities.go`, `modules/phrasebook/*`, `modules/surf/router.go`, `modules/boardwalk/boardwalk.go` | ✓ VERIFIED | Targeted Phase 10 tests ok in all four packages |
| `scripts/check-phase10.sh` | ✗ RED | `--security` exit 0; `--hygiene` and `--self-test` exit 1 (gaps) |
| `scripts/check-admin-dist.sh`, `scripts/check-admin-openapi.sh` | ✓ VERIFIED | exit 0 |
| fonoteka `admin_phase10_*_test.go` | ✓ VERIFIED | Acceptance, Tracer, Controllers PASS at e074028 |
| `admin/` SPA | ✓ VERIFIED | Unchanged; `check-admin-dist.sh` exit 0 |
| `admin/openapi/admin.json`, `schema.d.ts`, `types.ts` | ✓ VERIFIED | `check-admin-openapi.sh --check` exit 0 |
| `admin/tests/form/{mlLocale,MLField,FileCaptionModal}.test.ts`, `admin/tests/account/*` | ✓ VERIFIED | Exist, import their modules directly, 61 tests pass |
| `modules/cabana`, `bouncer`, `surf`, `boardwalk`, `phrasebook` Phase 10 code | ✓ VERIFIED | `--security` and `--postgres` named tests pass; framework `go test ./...` exit 0 |
| `scripts/check-phase10.sh` | ⚠️ PARTIAL | `--self-test`, `--hygiene`, `--security`, `--postgres`, `--openapi`, `--dist`, `--evidence` exit 0; `--go` exit 1 (gap) |
| fonoteka `admin_phase10_*_test.go` | ✓ VERIFIED | Acceptance, Tracer, Controllers, AdminAuth, AlbumRelations, CollectionOwnerReadOnly pass |
### Key Link Verification
| From | To | Via | Status |
|---|---|---|---|
| `admin/src/api/client.ts` | generated `schema.d.ts` | `createClient<paths>` | WIRED |
| `admin/src/api/files.ts` | generated aliases + client refresh | imports from `./types` and `./client` | WIRED (outside the gate's allowlist) |
| `useAuth.ts` logout | `POST /auth/logout` | outside the guard, always clears cookie | WIRED (`TestAdminLogoutRevokesExpiredRefreshableToken` PASS) |
| `cabana/auth.go` refresh | `bouncer.RefreshAudienceFor` | `s.users` | WIRED (`TestAdminRefreshRevocation` PASS) |
| `ListView.vue` / `FormView.vue` / `RelationManager.vue` | schema, record and relation endpoints | typed client | WIRED |
| `admin/src/api/files.ts` | generated aliases + client headers/refresh | imports from `./types` and `./client` | WIRED (now inside the gate's recorded exception) |
| `scripts/check-phase10.sh` hygiene | `admin/src/api/files.ts` exception | line- and path-anchored filters | WIRED, fail-closed (`xhr`, `apifile` plants) |
| `scripts/check-phase10.sh` run_go | `go test -json` both repos | `phase10_detect` skip/failure detection | WIRED (it refused the two drifts) |
| `ListView.vue` / `FormView.vue` / `RelationManager.vue` | schema, record and relation endpoints | typed client | WIRED (unchanged) |
| `modules/boardwalk` | `admin` build | `go:embed dist`, drift gate | WIRED |
### Data-Flow Trace (Level 4)
Unchanged in structure; every flow FLOWING (navigation from `GET /navigation` filtered server-side, lists/forms from schema endpoints and records, relations from `/relations/{name}` and `/candidates`, strings from `GET /lang`).
Unchanged since the previous report (no `admin/src` or Go change): every flow FLOWING (navigation from `GET /navigation` filtered server-side, lists and forms from schema endpoints and records, relations from `/relations/{name}` and `/candidates`, strings from `GET /lang`).
### Behavioral Spot-Checks (run this session)
| Behavior | Command | Result | Status |
|---|---|---|---|
| Phase 10 framework tests | `go test -count=1 -run 'TestPhase10\|TestAdminLogoutRevokesExpiredRefreshableToken\|TestNavigationDropsDeniedParentAndRepointsTarget\|TestAdminRefreshRevocation\|TestCRUDOperationsFollowDeclarations' ./modules/{cabana,phrasebook,surf,boardwalk}/` | 4 packages ok | ✓ PASS |
| SC-1..SC-3 on Postgres | fonoteka.go `go test -count=1 -run '^(TestPhase10AssembledAcceptance\|TestPhase10TracerSPA\|TestPhase10Controllers)$' ./plugins/golem15/fonoteka/` | 3 PASS | ✓ PASS |
| Embedded dist drift | `scripts/check-admin-dist.sh` | exit 0 | ✓ PASS |
| OpenAPI and types drift | `scripts/check-admin-openapi.sh --check` | exit 0 | ✓ PASS |
| Gate security stage | `scripts/check-phase10.sh --security` | exit 0 | ✓ PASS |
| Gate hygiene stage | `scripts/check-phase10.sh --hygiene` | exit 1, 7 refusals (files.ts x2, five untested modules) | ✗ FAIL |
| Gate self-test | `scripts/check-phase10.sh --self-test` | exit 1, "rejected the clean scratch copy" | ✗ FAIL |
| go vet, full `go test -short`, Vitest | orchestrator's parallel regression gate | not duplicated here | — |
| Hygiene gate | `bash scripts/check-phase10.sh --hygiene` | `phase10 hygiene passed`, exit 0 | ✓ PASS |
| Gate self-test | `bash scripts/check-phase10.sh --self-test` | `phase10 self-test passed`, exit 0 | ✓ PASS |
| Exemption narrowness | `hygiene_checks` on a scratch copy with 4 plants | all 4 refused, clean copy exit 0 | ✓ PASS |
| Five direct tests | `npx vitest run` on the five test files | 5 files, 61 tests passed | ✓ PASS |
| SPA suite | `npm run typecheck`; `npm test` | exit 0; 83 files, 1279 tests | ✓ PASS |
| Security, Postgres, OpenAPI, evidence | `bash scripts/check-phase10.sh --evidence` | `phase10 evidence passed`, exit 0 | ✓ PASS |
| Dist and OpenAPI drift | `scripts/check-admin-dist.sh`; `scripts/check-admin-openapi.sh --check` | exit 0; exit 0 | ✓ PASS |
| Go stage | `bash scripts/check-phase10.sh --go` | exit 1, skipped sunrise `TestBootstrapEndToEnd` | ✗ FAIL |
| Go stage, app half | gate functions sourced, `phase10_go "$APP" ./... ./plugins/golem15/fonoteka/... ./plugins/golem15/user/...` | go vet ok; `sm-user-plugin/updates TestCreateOrganisationsMigration` FAIL | ✗ FAIL |
### Probe Execution
@@ -390,7 +427,7 @@ No `probe-*.sh` declared or present; `check-phase10.sh` is the phase gate (stage
| Requirement | Source Plan | Description | Status | Evidence |
|---|---|---|---|---|
| ADMIN-06 | 10-01..10-05 | Minimal Vue 3 + TS SPA renders login, permission-gated navigation, lists, forms and the relation manager for the five controllers using generated types | ✓ SATISFIED (substance); gate red; browser re-check pending | Truths 1-4 |
| ADMIN-06 | 10-01..10-05 | Minimal Vue 3 + TS SPA renders login, permission-gated navigation, lists, forms and the relation manager for the five controllers using generated types | ✓ SATISFIED (substance and SC-4 gate); acceptance command red on `--go`; browser re-check pending | Truths 1-4; REQUIREMENTS.md marks it Complete for Phase 10 |
Orphaned requirements: none.
@@ -398,11 +435,12 @@ Orphaned requirements: none.
| File | Pattern | Severity | Impact |
|---|---|---|---|
| `scripts/check-phase10.sh` vs `admin/src/api/files.ts` | Phase gate not updated for a later-phase exception | 🛑 Blocker (evidenced: gate run red) | Phase 10 acceptance command fails |
| five later-phase SPA modules | imported by no test | 🛑 Blocker (evidenced: gate run red) | Breaks the 10-05 every-module-tested rule |
| Phase 10 review WR-04..WR-08 | carried from baseline | ⚠️ Warning | Unchanged, out of this re-check's scope |
| `scripts/check-phase10.sh` run_go vs `modules/sunrise` | Phase gate not updated for a later-phase opt-in skip | 🛑 Blocker (evidenced: `--go` run red) | Phase 10 acceptance command fails |
| sm-user-plugin `updates/organisations_test.go` | Migration history test not updated after a new migration | 🛑 Blocker for the gate (evidenced: named test FAIL); defect lives in the sibling repo | Phase 10 acceptance command fails |
| `admin/src/api/files.ts` | Local adapter types (`TypedResult` mirrors the openapi-fetch envelope) | ℹ️ Info | Wire payloads are generated aliases; not a duplicate API type |
| Phase 10 review WR-04..WR-08 | carried from baseline | ⚠️ Warning | Unchanged |
No unreferenced `TBD`/`FIXME`/`XXX` in changed covered files.
No `TBD`/`FIXME`/`XXX`/`TODO`/`HACK` in the six files changed since 07e579a.
### Human Verification Required
@@ -416,15 +454,16 @@ Carried items CR-01, A3 and the 17 prohibitions stay resolved by 10-UAT.md tests
### Gaps Summary
One root cause, three failed plan truths: the Phase 10 acceptance gate `scripts/check-phase10.sh` is red at HEAD because later phases added SPA files without updating its hygiene rules or adding direct-import tests. It has been red since ea33296 (12.2-04, 2026-10-02); the 2026-10-05 refresh only recomputed the digest and did not re-run the gate.
Quick task 261011-mag closed what it set out to close: the hygiene stage and the self-test are green. The files.ts exemption is narrow (line- and path-anchored, each half proven fail-closed by a self-test plant and by my own scratch plants) and justified (upload progress needs XHR; headers, refresh and all wire types come from `client.ts` and the generated aliases). The gate was not weakened.
- `admin/src/api/files.ts` (XHR upload) trips the "direct fetch outside client.ts" and "unexpected files in admin/src/api" rules. Its wire types are the generated aliases, so SC-4's intent holds. The fix is a narrow allowlist entry like the MarkdownField and listState precedents, or routing the upload through client.ts.
- `ApiTokenCreateDialog.vue`, `ApiTokensPanel.vue`, `FileCaptionModal.vue`, `MLField.vue` and `mlLocale.ts` are imported by no test. The fix is a direct import in a focused test for each.
- `--self-test` fails only as a consequence of the two items above.
One gap remains, and it is new evidence rather than a regression from the fix: the phase acceptance command `check-phase10.sh --all` is red at its `--go` stage. The previous report never got that far because `--self-test` (the first stage) already failed, and it carried the "both repositories pass go test" truth without running it. Two later-phase drifts cause it:
The ROADMAP success criteria themselves hold on re-run evidence (fonoteka Postgres acceptance, Phase 10 Go tests, drift gates). No later phase in the roadmap takes over this gate, so nothing is deferred. A small `/msd-quick` fix that closes both items and re-runs `check-phase10.sh --self-test --hygiene` should restore human_needed (the browser re-walk stays open).
- the framework's opt-in `modules/sunrise` `TestBootstrapEndToEnd` skip (14.3-02), which the Phase 10 skip detector refuses; fix it in `check-phase10.sh` as a narrow expected skip with its text and a self-test case;
- `sm-user-plugin` `TestCreateOrganisationsMigration`, whose expected history misses `202610050001_create_oauth_identities` (14.1-02); fix it in the plugin repo, then bump the pointer in fonoteka.go.
No later roadmap phase takes over this gate, so nothing is deferred. Once both are fixed and `--all` (or `--go`) passes, the phase returns to human_needed for the browser re-walk.
---
_Verified: 2026-10-11T13:53:00Z_
_Verified: 2026-10-11T14:32:00Z_
_Verifier: Claude (msd-verifier)_