Skip to content

T-356Q-fix-guard-project-shape-baseline

State: open/ready · Impact: medium · Complexity: small

AUTO-DEFINED: this spec was best-effort machine-authored by /sdlc:task-auto-define on 2026-09-13 because the task is autonomy: autonomous/pr. Review the Goal, Approach, Today, Files-to-touch, and Acceptance-criteria carefully before trusting it.

scripts/guard-project-shape.ts is already red on main: product-suspenders and product-system-graph match no aspect. A pre-existing failure means the guard cannot ratchet new violations — any new violation added alongside these is invisible. Fix the aspect mapping (or the guard’s baseline) so the guard is green on main again and can ratchet.

scripts/guard-project-shape.ts is already red on main (product-suspenders, product-system-graph match no aspect), so the guard cannot ratchet — pre-existing, needs its baseline updated.

— from T-4VNC-learning-p1-scaffold-solution’s post-mortem

LocationRole today
scripts/guard-project-shape.ts#ASPECT_BASELINEThe assertion-4 ratchet set: 3 layer: configuration ids plus 16 layer: application ids that match no gate-supplying moon aspect. product-suspenders and product-system-graph are absent from it, so aspectRatchetViolations reports both as new (unbaselined) violations and bun scripts/guard-project-shape.ts exits 1 on main.
solutions/ontological/products/suspenders/moon.ymlDeclares layer: 'application', stack: 'frontend', no tags:. Its own header comment already records the gap: “This product has the matching package.json scripts but no aspect of its own yet, so those three verbs are not reachable through moon here.”
solutions/ontological/products/system-graph/moon.ymlSame shape as suspenders: layer: 'application', no tags:, no gate-supplying .moon/tasks/*.yml reaches it.
.moon/tasks/determined-nuxt.ymlThe nearest existing Nuxt-product aspect (fmt/fmt-check/lint/build/build-desktop), explicitly scoped by its own header comment to “the 24 solutions/determined/products/*” — not registered on either solutions/ontological/products/* product.
.moon/tasks/nuxt-product.ymlThe check (vue-tsc) aspect, tagged nuxt-product onto exactly three solutions/determined products by design (“Tag another product only if it ever mounts something these three do not”) — also not applicable to suspenders / system-graph today.

Confirmed live: bun scripts/guard-project-shape.ts on this branch (same content as main) prints exactly two violations, both assertion-4 (“matches no gate-supplying aspect (S-0013 rule 6)”) — one for product-suspenders (solutions/ontological/products/suspenders), one for product-system-graph (solutions/ontological/products/system-graph). Assertions 1, 2, 3 and 5 (vocabulary rule 6/2, project metadata) are clean for both projects: each manifest already declares format, format:check and lint with no mutating gate, and each moon project already declares layer and stack.

Add product-suspenders and product-system-graph to scripts/guard-project-shape.ts#ASPECT_BASELINE’s layer: application group — the same treatment the guard already gives the other 16 unaspected application-layer projects (“CI’s affected step filters these out (projectLayer!=application) … so ‘no aspect’ is not ‘no gate’ for them either”). That restores bun scripts/guard-project-shape.ts to exit 0 on main, which is what lets assertion 4 ratchet the next drift instead of failing on a pre-existing, already-known gap every run.

This is the baseline-side fix the Goal names as an alternative to an aspect-mapping fix. A real aspect-mapping fix — a dedicated solutions/ontological-scoped Nuxt-product aspect mirroring .moon/tasks/determined-nuxt.yml / .moon/tasks/nuxt-product.yml, giving these two products fmt/fmt-check/lint/check reachable through moon run — is real follow-on work and is deliberately left out of this task (see Out of scope): it is a design decision (new aspect file, tag wiring, possibly new CI steps) an order of magnitude larger than a two-entry baseline edit, and the guard’s own docstring already treats “layer: application, no aspect yet, CI runs it as an explicit step instead” as an accepted, tracked category rather than a defect to eliminate on sight.

  1. Confirm the current red state: run bun scripts/guard-project-shape.ts (the same command .github/workflows/ci.yml’s “Guard — project shape conforms to the task vocabulary” step and moon.yml’s root:guard-project-shape task both run) and verify it prints exactly the two violations named in Today, with no other assertion failing for either project.
  2. In scripts/guard-project-shape.ts#ASPECT_BASELINE, add 'product-suspenders' and 'product-system-graph' to the layer: application group, in alphabetical order between 'photo-review' and 'vault-backup' (matching the group’s existing sort).
  3. Refresh the two count call-outs in the same file that describe this exact set’s size, so the edit does not leave a stale comment behind it:
    • the assertion-4 bullet in the top-of-file docstring (“19 projects match no gate-supplying aspect”) → 21.
    • the ratchet paragraph (“19 of 170 projects match no gate-supplying aspect. Sixteen are layer: application … and three are layer: configuration”) → update “19” to 21 and “Sixteen” to “Eighteen”; leave the “170” total alone (see Out of scope — that figure is separately stale for unrelated reasons and re-truing it is not this task’s job).
  4. Re-run bun scripts/guard-project-shape.ts and confirm it now exits 0, printing the OK summary line with the full moon-project count on the aspect ratchet and no violations.
  5. Run bun test scripts/guard-project-shape.test.ts and confirm the existing suite still passes unmodified — it drives aspectRatchetViolations against synthetic fixture projects built by the local project() helper, never against the live ASPECT_BASELINE constant or a real moon query projects call, so it does not need to change to reflect this edit.
AreaNote
scripts/guard-project-shape.ts#ASPECT_BASELINEAdd product-suspenders and product-system-graph to the layer: application baseline group (alphabetically); refresh the two adjacent docstring counts that describe this set’s size.
  • AC-1: bun scripts/guard-project-shape.ts exits 0 (it exits 1 on main today, citing product-suspenders and product-system-graph).
  • AC-2: scripts/guard-project-shape.ts#ASPECT_BASELINE contains both the string 'product-suspenders' and the string 'product-system-graph'.
  • AC-3: bun test scripts/guard-project-shape.test.ts passes.
  • AC-4: git diff --stat for the change touches exactly one file, scripts/guard-project-shape.ts.
  • AC-5: The top-of-file docstring’s two count call-outs for assertion 4 (the “19 projects match no gate-supplying aspect” bullet and the “19 of 170 … Sixteen are layer: application” ratchet paragraph) read 21 and Eighteen respectively, matching the two-entry baseline addition.
  • Designing or wiring a dedicated Nuxt-product moon aspect for solutions/ontological/products/* (mirroring .moon/tasks/determined-nuxt.yml / .moon/tasks/nuxt-product.yml) so product-suspenders and product-system-graph gain real fmt/fmt-check/lint/check tasks reachable through moon run. This task only unblocks the ratchet; it does not add per-project moon attribution for either product.
  • Any change to .moon/tasks/determined-nuxt.yml or .moon/tasks/nuxt-product.yml. Both are explicitly scoped by their own header comments to solutions/determined/products/* and are not extended to solutions/ontological/products/* here.
  • Adding CI steps for either product (e.g. an explicit moon run product-suspenders:check step alongside “Typecheck the Nuxt products” in .github/workflows/ci.yml). Neither product carries a check task today, so there is nothing yet for such a step to run.
  • Removing or re-litigating any of the pre-existing 19 baseline entries. Assertion 4’s shrink-only direction (an entry that “now matches an aspect” or “is no longer a project”) is unaffected by this change.
  • Correcting the module docstring’s total-project-count figure (“170”). A live moon query projects on this branch reports 181 projects total — a pre-existing drift unrelated to, and not caused by, this task’s two-id baseline addition.
  • none

Spawned by /sdlc:spawn-task-pr on 2026-09-13 UTC from T-4VNC-learning-p1-scaffold-solution in git@github.com:sksizer/dev.git.


← Back to Tasks