Skip to content

feat: 01-project-setup spec (requirements, design, tasks) - #3

Merged
toolpathguy merged 13 commits into
mainfrom
spec/01-project-setup
Jul 22, 2026
Merged

feat: 01-project-setup spec (requirements, design, tasks)#3
toolpathguy merged 13 commits into
mainfrom
spec/01-project-setup

Conversation

@toolpathguy

Copy link
Copy Markdown
Owner

Summary

Adds the complete spec for 01-project-setup — the Nuxt 4 + TypeScript workspace scaffold that all subsequent builder features depend on.

Files added/modified

  • .kiro/specs/01-project-setup/requirements.md — 9 requirements with acceptance criteria
  • .kiro/specs/01-project-setup/design.md — Architecture, data models, testing strategy
  • .kiro/specs/01-project-setup/tasks.md — 18 sub-tasks across 9 top-level tasks with dependency graph

Scope

This PR contains only the spec documents (no implementation code). Once merged, the tasks can be executed to scaffold the project.

What was tested

  • tasks.md passes Kiro spec format diagnostics with no issues

Maps 1:1 to MD Instructions/01-project-setup.md with formal EARS-style
acceptance criteria for each of the 9 requirements.
@toolpathguy

Copy link
Copy Markdown
Owner Author

Review summary (Request changes)
Strong spec overall: full requirements→design→tasks traceability, every PR #2 correction is properly incorporated (@nuxt/test-utils/config, nuxt typecheck, no compat flag, Nuxt UI v4, zod ^4), and it catches things the MD file didn't specify — the wrapper (required in Nuxt UI v4 for toasts/tooltips later), the main.css Tailwind import chain, app.config.ts correctly inside app/, and the correct unique-symbol branding pattern for NodeId. Two blocking issues will cause real build stalls; two smaller ones can be folded into the same edit.

📄 requirements.md — Requirement 2 / tasks.md — task 2.2 (blocking)
typescript and vue-tsc are missing from the dependency list. Both R1.2 (typescript.typeCheck: true) and R5.6 (nuxt typecheck) require them as devDependencies — nuxt typecheck errors out asking for them when absent. They don't appear in R2, the design's dependency graph, or task 2.2. Add to R2:
suggestion3. THE Scaffold SHALL install vitest, @vue/test-utils, @nuxt/test-utils, happy-dom, typescript, and vue-tsc in package.json devDependencies.
…and mirror in task 2.2's bullet list. Cheap fix now; a confusing mid-build failure otherwise.

📄 tasks.md — task 1.1 (blocking)
npx nuxi@latest init . will stall or refuse in this repo, for two reasons:

The directory is not empty (.git, .kiro/, MD Instructions/ already present) — nuxi init balks or prompts on non-empty targets.
The init wizard asks interactive questions (package manager, git init) that an agent execution context handles badly. "(or equivalent)" isn't enough guidance to avoid the stall.

Recommend rewriting 1.1 to skip the wizard entirely: author package.json, nuxt.config.ts, and tsconfig.json by hand — the design doc already specifies all three completely, so manual authoring is both simpler and more deterministic than init-into-temp-and-move. Suggested task text:
suggestion - [ ] 1.1 Author the base Nuxt 4 project files manually (do NOT run nuxi init — the repo is non-empty and the wizard prompts interactively)
- Create package.json with nuxt v4.5+ as a dependency, per the design doc
- Create nuxt.config.ts and tsconfig.json per the design doc
- Run npm install to generate the lockfile
- Requirements: 1.1, 1.5, 1.6

📄 requirements.md — R1.5 (non-blocking, fold into the same edit)
"THE Scaffold SHALL always complete successfully without halting due to internal errors" is unfalsifiable and contradicts R3.5, which (correctly) mandates halting on filesystem errors. Trim to the testable clause:
suggestion5. WHEN the scaffold is complete, THE project SHALL compile successfully via npx nuxi build with zero TypeScript errors.

📄 requirements.md — R3.2 / tasks.md — task 3.1 (non-blocking)
The empty /specs directory is a leftover from the original MD layout (where instruction files were going to live at /specs). In this repo they live at /MD Instructions/, and Kiro's specs live in .kiro/specs/ — creating a third, empty "specs" location is a trap for future agents deciding where things belong. Either drop specs from the skeleton, or make it real by moving MD Instructions/ into it and updating AI-MAP's references. Dropping it is the one-word fix.

💬 Minor / no action required

R1.4's "or by setting it to a value less than 5" is a strange allowance — simpler to require the future key be absent entirely.
The fast-check tests for makeNodeId aren't genuinely property-based (zero-arg function, no generated inputs) — harmless ceremony, correctly marked optional. Keeping the fast-check dep is still worthwhile: Task 03's validateAgainstRegistry will benefit from real PBT.
Task list places Checkpoint 6 between tasks 5 and 7, but the wave graph runs 5.x and 7.x in the same wave — if waves drive execution, the checkpoint is bypassed. Align one to the other (moving 7.x to wave 5 alongside 4.2/4.3/8.1 is the smallest change).

@toolpathguy

Copy link
Copy Markdown
Owner Author

Implementation Complete ✅

All 27 tasks from the spec have been executed and verified. This PR now includes the full implementation alongside the spec documents.

What was added

  • Nuxt 4 projectnuxt.config.ts, tsconfig.json, package.json with all deps
  • Dependencies@nuxt/ui v4, @pinia/nuxt, pinia, zod v4, @formkit/drag-and-drop, vitest, fast-check, @nuxt/eslint, etc.
  • Directory skeletonapp/components/blocks/, app/components/editor/, app/composables/, app/stores/, types/, registry/, compiler/, server/, tests/
  • Base shared typestypes/shared.ts with PropType, PropSchema (discriminated union), branded NodeId, and makeNodeId()
  • Tooling — ESLint flat config, Vitest with Nuxt environment, all npm scripts (dev, build, generate, lint, lint:fix, typecheck, test, test:watch)
  • Placeholder pagesapp/pages/index.vue (UButton → /editor), app/pages/editor.vue (stub)
  • Themeapp/app.config.ts with indigo/slate colors
  • Tests — Smoke test + 2 property-based tests (format validity, uniqueness) — all passing in ~350ms

Test results

✓ tests/smoke.test.ts (2 tests) 4ms
✓ tests/makeNodeId.property.test.ts (2 tests) 13ms

Test Files  2 passed (2)
Tests       4 passed (4)
Duration    346ms

@toolpathguy
toolpathguy marked this pull request as draft July 22, 2026 19:17
@toolpathguy
toolpathguy marked this pull request as ready for review July 22, 2026 19:17
@toolpathguy
toolpathguy marked this pull request as draft July 22, 2026 19:20
@toolpathguy
toolpathguy marked this pull request as ready for review July 22, 2026 19:20
@claude

claude Bot commented Jul 22, 2026

Copy link
Copy Markdown

Claude finished @toolpathguy's task in 3m 12s —— View job


Review: PR #3 — 01-project-setup spec + implementation

Verdict: 🔴 Request changes — one blocking item (a trivial one-line fix). CI is green (build/typecheck/lint/tests pass in 49s), so this is a latent trap, not a current failure.

The spec is genuinely strong: full requirements→design→tasks traceability, all PR #2 corrections carried through (@nuxt/test-utils/config, nuxt typecheck, no compat flag, zod ^4), and the implementation matches the design almost verbatim — the <UApp> wrapper, the main.css import chain, app.config.ts correctly inside app/, and the correct unique symbol branding for NodeId. The aggressive major-version pins (typescript ^6, pinia ^4, @pinia/nuxt ^1, vitest ^4) all resolve and build cleanly under CI, so no concern there.


🔴 Blocking

vitest.config.tsenvironmentMatchGlobs: [['tests/**', 'node']] (inline)
This forces every file under tests/** into the node environment. Since AI-MAP puts all Vitest files in /tests, the first component test written in Task 04/05/06 — following the CLAUDE.md convention (default nuxt, opt into node via docblock) — will silently run under node and mountSuspended will fail, which is precisely the failure R8 exists to prevent. It's also an undocumented deviation (design + task 5.2 specify only environment: 'nuxt') and redundant with the // @vitest-environment node docblocks the two current unit tests already carry. Fix is a one-line removal.

🟡 Nits (non-blocking)

  • tests/makeNodeId.property.test.ts — Property 1 uses fc.property(fc.constant(null), …), i.e. no generated input — it's just 100 identical runs, not genuinely property-based. Already acknowledged in the PR chore: apply spec-fix corrections from plan review #2 review as acceptable ceremony; Property 2 (generated count) is fine. Worth keeping fast-check for Task 03's validateAgainstRegistry.
  • tasks.md wave graph omits checkpoints 6 and 9 entirely (they're list nodes but appear in no wave). If waves drive execution, both checkpoints are bypassed. Minor — align the graph or the list.

Nice work — the sole blocker is a one-liner. Once environmentMatchGlobs is dropped, this is an approve.
· branch spec/01-project-setup

Comment thread vitest.config.ts Outdated
Comment on lines +5 to +8
environment: 'nuxt',
environmentMatchGlobs: [
['tests/**', 'node']
]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

environmentMatchGlobs: [['tests/**', 'node']] is a latent trap that defeats the whole point of R8 — please remove it.

Three problems, all pointing the same way:

  1. Undocumented deviation from the design. Both design.md (vitest.config.ts block) and tasks.md task 5.2 specify only test.environment: 'nuxt'. This glob was added during implementation with no spec basis.

  2. It contradicts R8.3 and the CLAUDE.md testing convention. AI-MAP places all Vitest files under /tests, and the convention is "default nuxt environment; pure unit tests opt into node via a // @vitest-environment node docblock." This glob inverts that: every file under tests/** is forced to node. The first component test written in Task 04/05/06 — placed in tests/, following the convention, with no docblock — will silently run under node, and mountSuspended will fail with exactly the environment error R8 exists to prevent. Whoever hits it will be baffled, because the config looks like it sets nuxt globally.

  3. It's redundant. The two current node-only tests already carry // @vitest-environment node docblocks (the sanctioned per-file opt-in), which take precedence anyway. The glob adds nothing for them and only creates the trap for future files.

Suggested change
environment: 'nuxt',
environmentMatchGlobs: [
['tests/**', 'node']
]
environment: 'nuxt'

Fix this →

@toolpathguy
toolpathguy marked this pull request as draft July 22, 2026 19:55
@toolpathguy
toolpathguy marked this pull request as ready for review July 22, 2026 19:55
@claude

claude Bot commented Jul 22, 2026

Copy link
Copy Markdown

Claude finished @toolpathguy's task in 1m 34s —— View job


Review: PR #3 — 01-project-setup spec + implementation

Verdict: 🟢 Approve (with minor nits)

The prior blocking issue is resolved. vitest.config.ts now cleanly exports only environment: 'nuxt' (commit 198208f), so the environmentMatchGlobs trap that would have broken future mountSuspended component tests is gone. This matches R8.2, the design block, and the CLAUDE.md convention (default nuxt; opt into node per-file via docblock — which both current unit tests correctly do).

CI is still pending, so this pass is code-level only — the build/typecheck/lint/test gate has the final word on version-pin resolution.

Spec traceability — all 9 requirements met

Req Status Evidence
R1 (Nuxt 4, strict TS, SSR, no compat flag) nuxt.config.ts strict/typeCheck/ssr: true, no future.compatibilityVersion; nuxt ^4.5.0
R2 (deps + modules) @nuxt/ui ^4, @pinia/nuxt+pinia, zod ^4, @formkit/drag-and-drop; devDeps incl. typescript+vue-tsc; eslint.config.mjs applies flat config
R3 (skeleton) All dirs present with .gitkeep; the stray specs/ from the MD layout was correctly dropped
R4 (shared types) PropType, discriminated PropSchema, unique symbol-branded NodeId, makeNodeId() — matches design verbatim
R5 (scripts) typecheck uses nuxt typecheck (no Vitest); test = vitest run; watch isolated to test:watch
R6 (pages) index.vue UButton to="/editor"; editor.vue renders "Editor coming soon"
R7 (smoke test) tests/smoke.test.ts imports makeNodeId, asserts UUID v4 + uniqueness
R8 (Vitest env) Fixed — see above
R9 (theme) app.config.ts primary: indigo, neutral: slate

Registry purity holds: /compiler and /server are empty placeholders; types/shared.ts imports nothing that touches .vue.

🟡 Nits (non-blocking — no action required to merge)

  • tests/makeNodeId.property.test.ts:15 — Property 1 uses fc.property(fc.constant(null), …), so it's 100 identical runs rather than a genuine property over generated input. Already acknowledged in prior reviews as acceptable ceremony; Property 2 (generated count) is real. Keeping fast-check is worthwhile for Task 03's validateAgainstRegistry.
  • tasks.md:138 wave graph — checkpoints 6 and 9 are list nodes but appear in no wave. If waves drive execution, both are bypassed. Cosmetic; align the graph or the list.
  • .nuxtrc — a @nuxt/test-utils generated setup marker committed to the repo. Harmless, but generated config like this is usually gitignored; worth a glance to confirm it's intentional.

Nice work — clean requirements→design→tasks→code traceability, and the implementation tracks the design almost line-for-line (the <UApp> wrapper, the main.css import chain, app.config.ts correctly under app/). The sole prior blocker is fixed; this is good to merge once CI goes green.
· branch spec/01-project-setup

@toolpathguy
toolpathguy merged commit f142f32 into main Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant