@davidbalzan/groundwork 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +323 -0
  3. package/docs/DECISIONS.md +170 -0
  4. package/package.json +38 -0
  5. package/payload/doc-templates/COMMANDS.md +419 -0
  6. package/payload/doc-templates/DECISIONS.md +168 -0
  7. package/payload/doc-templates/FACTS.md +43 -0
  8. package/payload/doc-templates/GROUNDWORK_METHODOLOGY.md +1300 -0
  9. package/payload/doc-templates/STACK_MAP.md +90 -0
  10. package/payload/doc-templates/WORKSTREAMS.md +79 -0
  11. package/payload/doc-templates/_INDEX.md +54 -0
  12. package/payload/doc-templates/phases/README.md +36 -0
  13. package/payload/doc-templates/phases/templates/README.md +63 -0
  14. package/payload/doc-templates/phases/templates/TASK_TEMPLATE.md +302 -0
  15. package/payload/doc-templates/phases/templates/task_template_prompt.md +229 -0
  16. package/payload/doc-templates/templates/ARCHITECTURE_GUIDE_TEMPLATE.md +250 -0
  17. package/payload/doc-templates/templates/DESIGN_SYSTEM_TEMPLATE.md +336 -0
  18. package/payload/doc-templates/templates/DONE_TEMPLATE.md +21 -0
  19. package/payload/doc-templates/templates/PHASES_README_TEMPLATE.md +144 -0
  20. package/payload/doc-templates/templates/PHASE_README_TEMPLATE.md +142 -0
  21. package/payload/doc-templates/templates/PRD_TEMPLATE.md +348 -0
  22. package/payload/doc-templates/templates/PRODUCTION_ROADMAP_TEMPLATE.md +168 -0
  23. package/payload/doc-templates/templates/QUEUE_TEMPLATE.md +17 -0
  24. package/payload/doc-templates/templates/TECH_STACK_TEMPLATE.md +199 -0
  25. package/payload/scripts/check-task.mjs +98 -0
  26. package/payload/scripts/check-versions.mjs +113 -0
  27. package/payload/scripts/phase-status.mjs +69 -0
  28. package/payload/scripts/set-fact.mjs +86 -0
  29. package/payload/skills/add-data-layer/SKILL.md +129 -0
  30. package/payload/skills/check-task/SKILL.md +35 -0
  31. package/payload/skills/check-versions/SKILL.md +47 -0
  32. package/payload/skills/create-prd/SKILL.md +90 -0
  33. package/payload/skills/domain-model/SKILL.md +90 -0
  34. package/payload/skills/kickstart/SKILL.md +157 -0
  35. package/payload/skills/log-decision/SKILL.md +65 -0
  36. package/payload/skills/next/SKILL.md +65 -0
  37. package/payload/skills/plan-phase/SKILL.md +108 -0
  38. package/payload/skills/remember/SKILL.md +77 -0
  39. package/payload/skills/start-session/SKILL.md +52 -0
  40. package/payload/skills/update-workstreams/SKILL.md +60 -0
  41. package/src/cli.mjs +115 -0
  42. package/src/commands/add.mjs +39 -0
  43. package/src/commands/artifacts.mjs +24 -0
  44. package/src/commands/doctor.mjs +292 -0
  45. package/src/commands/init.mjs +147 -0
  46. package/src/commands/knowledge.mjs +148 -0
  47. package/src/commands/list.mjs +61 -0
  48. package/src/commands/status.mjs +96 -0
  49. package/src/commands/update.mjs +128 -0
  50. package/src/lib/adr-tripwire.mjs +171 -0
  51. package/src/lib/artifacts.mjs +124 -0
  52. package/src/lib/config.mjs +43 -0
  53. package/src/lib/fs.mjs +46 -0
  54. package/src/lib/log.mjs +22 -0
  55. package/src/lib/paths.mjs +36 -0
  56. package/src/lib/progress.mjs +26 -0
  57. package/src/lib/skills.mjs +42 -0
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: next
3
+ description: Figure out where the project is in the Groundwork flow and recommend the next step. Use when the user asks "what's next", "where are we", "what should I do now", or seems unsure which Groundwork skill to run.
4
+ argument-hint: "[optional: area to focus on]"
5
+ allowed-tools: Read, Glob, Grep
6
+ ---
7
+
8
+ # Next - Groundwork Flow Guide
9
+
10
+ Act as the project's flow coach. Inspect the current state, tell the user exactly where
11
+ they are in the Groundwork lifecycle, and recommend the single best next action (with a
12
+ short why). This skill never edits files — it orients and points.
13
+
14
+ ## How to assess (read these, in order)
15
+
16
+ 1. `docs/TECH_STACK.md` / `docs/PRODUCTION_ROADMAP.md` — do the project docs exist yet?
17
+ 2. `docs/STACK_MAP.md` — are versions pinned and recently audited (`Last audited` date)?
18
+ 3. `docs/PRD.md` (or `docs/PRD_*.md`) — is there a PRD?
19
+ 4. `docs/phases/phase*/PHASE*_TASKS.md` — do task files exist, and how many checkboxes
20
+ are open vs done? (For exact counts, suggest `groundwork status` or
21
+ `docs/.groundwork/scripts/phase-status.mjs`.)
22
+ 5. `docs/WORKSTREAMS.md` — any active streams in flight?
23
+ 6. `docs/QUEUE.md` (or legacy `docs/BACKLOG.md`) — what is the next unblocked `- [ ]` item in `## Queue`?
24
+ 7. `docs/DECISIONS.md` — recent or pending ADRs.
25
+
26
+ ## Decision tree
27
+
28
+ Pick the FIRST matching state and recommend its action:
29
+
30
+ | State detected | Recommend |
31
+ | -------------- | --------- |
32
+ | No `PRD.md` (and no project docs) | `/create-prd "<idea>"` — **first step**: define the product before scaffolding |
33
+ | PRD exists, but no `TECH_STACK.md` / `PRODUCTION_ROADMAP.md` | `/kickstart` — scaffold the project docs **from the PRD** |
34
+ | Designing and terminology is fuzzy/conflicting, or no `CONTEXT.md` yet | `/domain-model` — pin the ubiquitous language (+ bounded contexts) |
35
+ | Docs exist, a `package.json` is present, `STACK_MAP` never audited or stale | `/check-versions` — pin to latest stable before building |
36
+ | Roadmap exists but no `PHASE*_TASKS.md` | `/plan-phase 1 "<name>"` — break the first phase into tasks |
37
+ | Task file has open `- [ ]` items, no active stream | `/start-session`, then work the next task; `/check-task <id>` as you finish |
38
+ | Work in progress | `/update-workstreams` to record state; `/log-decision` for any new choices |
39
+ | All tasks in current phase done | `groundwork status` to confirm, then `/plan-phase N+1` for the next phase |
40
+ | A reusable cross-project lesson surfaced, knowledge repo configured | `/remember` it (or `/remember --adr` if it's a real decision with trade-offs) |
41
+ | A lesson surfaced but no knowledge repo set (no `$GROUNDWORK_KNOWLEDGE` and no `~/.config/groundwork/config.json`) | `groundwork knowledge init` first, then `/remember` |
42
+ | A project-specific decision was made | `/log-decision` (writes this project's `docs/DECISIONS.md`) |
43
+ | A feature now needs persistence and there's no DB | `/add-data-layer` |
44
+
45
+ If several apply, choose the one earliest in the flow that is incomplete — finishing the
46
+ foundation beats jumping ahead.
47
+
48
+ ## Output format
49
+
50
+ ```
51
+ ## Where you are
52
+ <one or two sentences: current phase/task, what's done, what's open>
53
+
54
+ ## Recommended next step
55
+ **`/<skill> <args>`** — <why this, now>
56
+
57
+ ## Also worth doing
58
+ - <secondary suggestion, if any>
59
+ - <blocker to clear, if any>
60
+ ```
61
+
62
+ Keep it short and decisive — one clear recommendation, not a menu. If the user passed
63
+ `$ARGUMENTS`, bias the recommendation toward that area.
64
+
65
+ Focus area (optional): $ARGUMENTS
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: plan-phase
3
+ description: Generate a new phase task document using the project template
4
+ argument-hint: "<phase number> <phase name>"
5
+ ---
6
+
7
+ # Plan Phase - Task Document Generator
8
+
9
+ Generate a comprehensive phase task document following the Groundwork methodology.
10
+
11
+ ## Obsidian Format (Required)
12
+
13
+ Both generated files start with YAML frontmatter and use `[[wikilinks]]` (to
14
+ `[[PRODUCTION_ROADMAP]]`, `[[ARCHITECTURE_GUIDE]]`, `[[TECH_STACK]]`, `[[DECISIONS]]`,
15
+ `[[WORKSTREAMS]]`, sibling phases). Frontmatter:
16
+
17
+ ```yaml
18
+ # docs/phases/phaseN/README.md
19
+ ---
20
+ title: "Phase N: [Name]"
21
+ tags: [groundwork/phase]
22
+ aliases: ["Phase N"]
23
+ ---
24
+ # docs/phases/phaseN/PHASEN_TASKS.md
25
+ ---
26
+ title: "Phase N Tasks"
27
+ tags: [groundwork/phase, groundwork/tasks]
28
+ aliases: ["Phase N Tasks"]
29
+ ---
30
+ ```
31
+
32
+ Base the README on `docs/templates/PHASE_README_TEMPLATE.md` and the tasks file on
33
+ `docs/phases/templates/TASK_TEMPLATE.md` (both already have frontmatter — keep it, update titles).
34
+
35
+ ## Instructions
36
+
37
+ Follow the 6-stage approach from `docs/phases/templates/task_template_prompt.md`:
38
+
39
+ 1. **Discovery & scope** — read existing phase docs; review PRODUCTION_ROADMAP.md objectives.
40
+ 2. **Technical analysis** — explore relevant code + patterns; check ARCHITECTURE_GUIDE.md
41
+ (constraints) and TECH_STACK.md. Read `docs/CONTEXT.md` (if present) and use its
42
+ canonical terms for task names, types, and APIs; if the phase introduces/sharpens
43
+ domain terms, run `/domain-model`.
44
+ 3. **Impact & risk** — phase dependencies, risks + mitigations, blockers.
45
+ 4. **Component inventory** — components to create/modify, mapped to packages; shared types.
46
+ 5. **Task planning** — 4–6 major tasks, each 3–7 sub-steps, priorities
47
+ (CRITICAL/HIGH/MEDIUM/LOW), inter-task dependencies.
48
+ 6. **Success criteria** — functional, technical, and quality criteria.
49
+ 7. **Confidence report** — end the tasks file with a short `## Low-confidence decisions`
50
+ list: the choices in this plan you are least sure about and why (naming, boundaries,
51
+ library picks, ordering). Cheap to fix now, expensive after code exists.
52
+
53
+ ## Task format
54
+
55
+ ```markdown
56
+ ### Task N: [Task Name]
57
+
58
+ **Priority**: [CRITICAL/HIGH/MEDIUM/LOW]
59
+ **Package**: [client/server/shared]
60
+ **Dependencies**: [Task numbers or "None"]
61
+
62
+ #### Sub-tasks
63
+ - [ ] N.1 [First sub-task]
64
+ - [ ] N.2 [Second sub-task]
65
+
66
+ #### Deliverables
67
+ - [What this task produces]
68
+
69
+ #### Interfaces / contracts (if the task introduces or changes any)
70
+ ```ts
71
+ // signatures only — types, function/method signatures, endpoint shapes, table columns.
72
+ // No bodies. This is the level a reviewer can skim before code exists.
73
+ ```
74
+
75
+ #### Rollback Plan (if high-risk)
76
+ - [How to revert if needed]
77
+ ```
78
+
79
+ ## Output
80
+
81
+ 1. Generate `docs/phases/phaseN/README.md` (overview) and `PHASEN_TASKS.md` (detailed tasks).
82
+ 2. Update PRODUCTION_ROADMAP.md to include the new phase.
83
+ 3. Update `docs/QUEUE.md` (see below).
84
+ 4. Summarize what was created.
85
+
86
+ ## QUEUE.md Integration
87
+
88
+ After generating the tasks file, update `docs/QUEUE.md` — the inbound queue that bridges
89
+ Groundwork phase planning and whoever executes (you solo, or a coordinator's live multi-agent
90
+ dispatch). Completions land in `docs/DONE.md`, which this skill never writes.
91
+
92
+ ```markdown
93
+ # QUEUE — <project>
94
+
95
+ ## Queue
96
+ - [ ] (P1) Phase N: [Phase Name] — see [[phases/phaseN/PHASEN_TASKS]] for full breakdown · acceptance: all Phase N success criteria met
97
+ - [ ] (P2) <ad-hoc task added by David>
98
+ ```
99
+
100
+ Rules:
101
+ - **One Queue item per phase** — reference the PHASEN_TASKS file, don't inline sub-tasks; the executor reads the linked file for the full contract.
102
+ - **Priority mapping**: CRITICAL → P1, HIGH → P2, MEDIUM/LOW → P3. Default new phases to P1 unless the roadmap says otherwise.
103
+ - **If `docs/QUEUE.md` doesn't exist**, create it from `docs/templates/QUEUE_TEMPLATE.md`; if it exists, append to `## Queue` — never overwrite or reorder existing items (David owns this file).
104
+ - **Ad-hoc tasks** live alongside phase items in the Queue — don't remove or reorder them.
105
+ - **Never touch `docs/DONE.md`** — executor-only, append-only.
106
+ - **Legacy layout:** if the project still has a `docs/BACKLOG.md` with a `## Queue` section, append there instead and suggest migrating to the QUEUE/DONE split.
107
+
108
+ Phase to plan: $ARGUMENTS
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: remember
3
+ description: Capture a cross-project lesson in the central git knowledge repo — a quick dated note by default, or a formal ADR when it's a real decision with trade-offs (use --adr). Use when the user says "remember that…" or a reusable lesson/decision surfaces worth keeping beyond this project.
4
+ argument-hint: "[--adr] [tag:] <lesson>"
5
+ ---
6
+
7
+ # Remember - Capture a Lesson (central, git-level)
8
+
9
+ Persist cross-project lessons to the **central knowledge repo** so they live at git level
10
+ (shared across projects, machines, and the swarm). Two modes:
11
+
12
+ - **note** (default) — a quick dated one-liner in `notes/lessons.md`.
13
+ - **ADR** (`--adr`, or when the lesson is a real decision) — a formal record in
14
+ `adr/NNNN-*.md` with rationale and trade-offs, indexed in `INDEX.md`.
15
+
16
+ Use the ADR mode **only when** the lesson is *hard to reverse*, *surprising without
17
+ context*, and *a real trade-off*. Otherwise a note is enough.
18
+
19
+ ## Resolve the knowledge repo (per-user — never hardcode)
20
+
21
+ Order: `$GROUNDWORK_KNOWLEDGE` → `knowledgeRepo` in
22
+ `${XDG_CONFIG_HOME:-$HOME/.config}/groundwork/config.json` → else stop and tell the user to
23
+ run `groundwork knowledge init` (or `link <dir>`).
24
+
25
+ ```bash
26
+ KB="$GROUNDWORK_KNOWLEDGE"
27
+ [ -z "$KB" ] && KB=$(groundwork knowledge path 2>/dev/null | head -1)
28
+ [ -z "$KB" ] && { echo "No knowledge repo configured — run: groundwork knowledge init"; exit 1; }
29
+ ```
30
+
31
+ Always `git -C "$KB" pull --rebase --autostash 2>/dev/null || true` before writing (the
32
+ swarm/other machines push here too), and commit + push after.
33
+
34
+ ## Note mode (default)
35
+
36
+ 1. Parse `$ARGUMENTS` into an optional `tag:` prefix (lowercase, e.g. `tooling:`) + the lesson; infer a tag if none.
37
+ 2. Resolve `$KB`. Pull.
38
+ 3. Append to `$KB/notes/lessons.md` (create with `# Lessons` if absent), today's date:
39
+ ```markdown
40
+ - [YYYY-MM-DD] (tag) <lesson> · src: <project/repo, if relevant>
41
+ ```
42
+ 4. `git add notes/lessons.md && git commit -m "note: <summary>" && git push 2>/dev/null || true`.
43
+ 5. Confirm. If it reads like a real decision, offer to upgrade it with `--adr`.
44
+
45
+ ## ADR mode (`--adr`)
46
+
47
+ 1. Resolve `$KB`. Pull.
48
+ 2. Gather (briefly, from `$ARGUMENTS` + conversation): **Context**, **Decision**,
49
+ **Consequences** (positive + negative), **Alternatives considered**.
50
+ 3. Next number: scan `$KB/adr/` for the highest `NNNN`, increment, zero-pad to 4 digits.
51
+ 4. Write `$KB/adr/NNNN-kebab-title.md`:
52
+ ```markdown
53
+ # ADR-NNNN: <Title>
54
+
55
+ **Status**: Accepted
56
+ **Date**: YYYY-MM-DD
57
+ **Tags**: <comma-separated>
58
+ **Origin**: <project/repo, if relevant>
59
+
60
+ ## Context
61
+ ## Decision
62
+ ## Consequences
63
+ **Positive**
64
+ **Negative**
65
+ ## Alternatives Considered
66
+ ```
67
+ 5. Add a row to `$KB/INDEX.md` (ID, linked title, tags, date).
68
+ 6. `git add adr/ INDEX.md && git commit -m "adr: NNNN <title>" && git push 2>/dev/null || true`.
69
+ 7. If promoting an existing note, append `→ ADR-NNNN` to it in `notes/lessons.md`. Confirm and show the ADR.
70
+
71
+ ## Scope
72
+
73
+ Cross-project lessons/decisions belong here. **Project-specific** decisions stay in that
74
+ project's `docs/DECISIONS.md` via `/log-decision`. Tool-agnostic by design — just git +
75
+ markdown, so any agent or human shares the repo.
76
+
77
+ ## Lesson to capture: $ARGUMENTS
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: start-session
3
+ description: Load project context from Groundwork docs at the start of a session
4
+ argument-hint: "[optional: specific area to focus on]"
5
+ allowed-tools: Read, Glob, Grep
6
+ ---
7
+
8
+ # Start Session - Groundwork Context Loader
9
+
10
+ Load context from the Groundwork docs to understand current project state, then summarize.
11
+
12
+ ## Instructions
13
+
14
+ Read, in order (skip any that are absent):
15
+
16
+ 1. **`docs/PRODUCTION_ROADMAP.md`** — the "Current Status" section is the primary entry point.
17
+ 2. **`docs/WORKSTREAMS.md`** — live state of parallel streams (what's in flight now).
18
+ 3. **Active phase** `docs/phases/phaseN/README.md` + `PHASEN_TASKS.md` — goals + task breakdown.
19
+ 4. **`docs/DECISIONS.md`** — recent/relevant ADRs.
20
+ 5. **`docs/CONTEXT.md`** — the ubiquitous language; use its canonical terms.
21
+ 6. **`docs/QUEUE.md`** (or legacy `docs/BACKLOG.md`) — next unblocked Queue item + ad-hoc tasks.
22
+ 7. **Summarize** (see format). `docs/ARTIFACTS.md` maps where everything lives if unsure.
23
+
24
+ ## Output Format
25
+
26
+ ```
27
+ ## Session Context
28
+ **Active Phase**: Phase N - [Name]
29
+ **Current Task**: [description] **Status**: [In Progress / Blocked / …]
30
+
31
+ ### Recent Progress
32
+ - [what was completed]
33
+
34
+ ### Recent Decisions
35
+ - ADR-XXX: [Title] — [impact on current work]
36
+
37
+ ### Blockers
38
+ - [blocking items]
39
+
40
+ ### Next Backlog Item
41
+ - (P?) [next unblocked Queue item, or "No backlog found"]
42
+
43
+ ### Suggested Next Steps
44
+ 1. … 2. …
45
+ ```
46
+
47
+ If `$ARGUMENTS` is given, focus the summary on that area.
48
+
49
+ ## Decision relevance
50
+
51
+ Surface ADRs from the last 30 days, any related to the current phase, any "Proposed" ones
52
+ awaiting confirmation, and any that constrain the current task.
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: update-workstreams
3
+ description: Update docs/WORKSTREAMS.md with the live state of parallel work streams
4
+ argument-hint: "[stream id or summary of progress]"
5
+ ---
6
+
7
+ # Update Workstreams - Live Parallel-Work Recorder
8
+
9
+ Update `docs/WORKSTREAMS.md` to reflect the live state of every parallel stream of work —
10
+ a table of **active streams**, not a single focus (the swarm-native replacement for
11
+ "current focus"). It is the live counterpart to `[[QUEUE]]`:
12
+
13
+ - **`QUEUE.md`** = the *inbound* queue (what to pick up next). Owned by the human + `/plan-phase`.
14
+ - **`WORKSTREAMS.md`** = the *live* state (what's in flight). Written by whoever's working,
15
+ including an external coordinator that pulls from QUEUE and opens a stream here. See
16
+ `[[GROUNDWORK_METHODOLOGY#multi-agent-seam]]`.
17
+ - **`DONE.md`** = the *completion log* (append-only, written by the executor).
18
+
19
+ Working alone is just the one-row case — the model scales solo → fleet unchanged.
20
+
21
+ Preserve the file's frontmatter; use `[[wikilinks]]` (`[[DECISIONS#adr-005|ADR-005]]`, `[[QUEUE]]`).
22
+
23
+ **Write only the core; preserve coordinator extensions.** Under a multi-agent coordinator,
24
+ `WORKSTREAMS.md` may carry coordinator-only sections after the `<!-- coordinator extensions -->`
25
+ fence (Open PRs, Cutover Gates, Needs David, Risks, Rooms, Decisions Recorded). You edit
26
+ **only** `## Active Streams` and `## Recently Closed`; copy everything from that fence onward
27
+ through **verbatim** on every rewrite — never edit or drop it. Within Active Streams, touch
28
+ only the row(s) you own, and if another agent may be writing, re-read immediately before
29
+ writing (read-before-write) so you don't clobber a concurrent row.
30
+
31
+ ## Instructions
32
+
33
+ 1. Read `docs/WORKSTREAMS.md`.
34
+ 2. From `$ARGUMENTS`/context: new stream → add a row; progress → update its Status / Last
35
+ note; finished → move the row to `## Recently Closed` with an outcome.
36
+ 3. Keep one row per active stream; update the `Last Updated` timestamp; confirm the result.
37
+
38
+ Write grammar is **`workstreams.v1`**: the 6-col Active Streams table below. Do not write a
39
+ 5-col Lanes table (`Lane | Owner | State | Current slice | Next GO`) — that shape is
40
+ parse-only.
41
+
42
+ ## Format
43
+
44
+ ```markdown
45
+ ## Active Streams
46
+
47
+ | Stream | Owner / Agent | Branch · Worktree | Status | Blocker | Last note |
48
+ | ----------------- | ------------- | ---------------------------- | -------------- | ------- | ------------------------------- |
49
+ | Phase 2 · Auth | agent-api | `feat/phase2-auth` · wt-auth | 🚧 In Progress | None | JWT done, RBAC next |
50
+ | Phase 3 · Search | — | — | ⏳ Queued | Phase 2 | pulled from [[QUEUE]] |
51
+
52
+ ## Recently Closed
53
+ - ✅ Phase 1 · Foundation — agent-api · `feat/phase1` · merged YYYY-MM-DD
54
+ ```
55
+
56
+ Guidelines: status = 🚧 In Progress · 🔍 In Review · ⏳ Queued · ⛔ Blocked · ✅ Done. Record
57
+ branch + worktree so any agent can resume the exact context. `Blocker` names the dependency
58
+ (another stream, a decision, a person), not just "yes". Dates `YYYY-MM-DD`.
59
+
60
+ Progress to record: $ARGUMENTS
package/src/cli.mjs ADDED
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync } from "node:fs";
3
+ import { init } from "./commands/init.mjs";
4
+ import { update } from "./commands/update.mjs";
5
+ import { add } from "./commands/add.mjs";
6
+ import { list } from "./commands/list.mjs";
7
+ import { status } from "./commands/status.mjs";
8
+ import { knowledge } from "./commands/knowledge.mjs";
9
+ import { artifacts } from "./commands/artifacts.mjs";
10
+ import { doctor } from "./commands/doctor.mjs";
11
+ import { log, bold, cyan, dim } from "./lib/log.mjs";
12
+
13
+ const argv = process.argv.slice(2);
14
+
15
+ /** Split flags (--foo) from positional args. */
16
+ function parse(args) {
17
+ const flags = {};
18
+ const pos = [];
19
+ for (const a of args) {
20
+ if (a.startsWith("--")) flags[a.slice(2)] = true;
21
+ else pos.push(a);
22
+ }
23
+ return { flags, pos };
24
+ }
25
+
26
+ function version() {
27
+ const pkg = JSON.parse(
28
+ readFileSync(new URL("../package.json", import.meta.url), "utf8")
29
+ );
30
+ console.log(pkg.version);
31
+ }
32
+
33
+ function help() {
34
+ console.log(
35
+ [
36
+ bold("groundwork") + dim(" — bolt the Groundwork AI workflow onto any repo"),
37
+ "",
38
+ bold("Usage:") + " groundwork <command> [dir] [flags]",
39
+ "",
40
+ bold("Commands:"),
41
+ ` ${cyan("init")} [dir] Install skills + IDE mirrors + docs into a repo (default: .)`,
42
+ ` ${cyan("update")} [dir] Upgrade skills + scripts in place (keeps your docs); ${dim("--all")} adds new skills, ${dim("--docs")} refreshes generic reference docs`,
43
+ ` ${cyan("add")} <skill> [dir] Add one optional skill (e.g. add-data-layer)`,
44
+ ` ${cyan("list")} [dir] List available skills and install state`,
45
+ ` ${cyan("status")} [dir] Show live workstreams, next backlog item, phase progress`,
46
+ ` ${cyan("doctor")} [dir] Flag doc↔reality drift (orphan links, stale phases/versions)`,
47
+ ` ${cyan("knowledge")} <cmd> Central ADR/lessons repo (init | link | sync [--push] | path)`,
48
+ ` ${cyan("artifacts")} [dir] Regenerate docs/ARTIFACTS.md from the manifest`,
49
+ ` ${cyan("help")} Show this help`,
50
+ ` ${cyan("version")} Print version`,
51
+ "",
52
+ bold("Flags:"),
53
+ ` --minimal init only the core 5 skills`,
54
+ ` --force overwrite files that already exist`,
55
+ ` --json machine-readable output (doctor / status / list)`,
56
+ "",
57
+ bold("Examples:"),
58
+ dim(" npx github:davidbalzan/groundwork init"),
59
+ dim(" groundwork init . --minimal"),
60
+ dim(" groundwork add data-layer"),
61
+ dim(" groundwork status"),
62
+ ].join("\n")
63
+ );
64
+ }
65
+
66
+ const [cmd, ...rest] = argv;
67
+ const { flags, pos } = parse(rest);
68
+
69
+ try {
70
+ switch (cmd) {
71
+ case "init":
72
+ init(pos[0], flags);
73
+ break;
74
+ case "update":
75
+ update(pos[0], flags);
76
+ break;
77
+ case "add":
78
+ add(pos[0], pos[1]);
79
+ break;
80
+ case "list":
81
+ list(pos[0], flags);
82
+ break;
83
+ case "status":
84
+ status(pos[0], flags);
85
+ break;
86
+ case "knowledge":
87
+ knowledge(pos[0], pos[1], flags);
88
+ break;
89
+ case "artifacts":
90
+ artifacts(pos[0]);
91
+ break;
92
+ case "doctor":
93
+ doctor(pos[0], flags);
94
+ break;
95
+ case "version":
96
+ case "--version":
97
+ case "-v":
98
+ version();
99
+ break;
100
+ case "help":
101
+ case "--help":
102
+ case "-h":
103
+ case undefined:
104
+ help();
105
+ break;
106
+ default:
107
+ log.err(`Unknown command: ${cmd}`);
108
+ help();
109
+ process.exitCode = 1;
110
+ }
111
+ } catch (err) {
112
+ log.err(err.message);
113
+ if (process.env.DEBUG) console.error(err);
114
+ process.exitCode = 1;
115
+ }
@@ -0,0 +1,39 @@
1
+ import path from "node:path";
2
+ import { PAYLOAD_SKILLS, TARGET } from "../lib/paths.mjs";
3
+ import { copyFileSafe, exists } from "../lib/fs.mjs";
4
+ import { loadSkills, mirrorFiles } from "../lib/skills.mjs";
5
+ import fs from "node:fs";
6
+ import { log, cyan } from "../lib/log.mjs";
7
+
8
+ /**
9
+ * Add a single optional skill (e.g. after a `--minimal` install, or to pull in
10
+ * `add-data-layer`). Copies the SKILL.md and regenerates that skill's mirrors.
11
+ */
12
+ export function add(skillName, targetDir) {
13
+ const root = path.resolve(targetDir || ".");
14
+ if (!skillName) {
15
+ log.err("Usage: groundwork add <skill-name> (see `groundwork list`)");
16
+ process.exitCode = 1;
17
+ return;
18
+ }
19
+ const src = path.join(PAYLOAD_SKILLS, skillName, "SKILL.md");
20
+ if (!exists(src)) {
21
+ log.err(`Unknown skill "${skillName}". Run \`groundwork list\`.`);
22
+ process.exitCode = 1;
23
+ return;
24
+ }
25
+
26
+ copyFileSafe(src, path.join(root, TARGET.skills, skillName, "SKILL.md"), {
27
+ force: true,
28
+ });
29
+ const [skill] = loadSkills([skillName]);
30
+ for (const f of mirrorFiles([skill], {
31
+ cursorDir: path.join(root, TARGET.cursor),
32
+ vscodeDir: path.join(root, TARGET.vscode),
33
+ })) {
34
+ fs.mkdirSync(path.dirname(f.rel), { recursive: true });
35
+ fs.writeFileSync(f.rel, f.content);
36
+ }
37
+
38
+ log.ok(`Added skill ${cyan("/" + skillName)} (+ Cursor/VS Code mirrors).`);
39
+ }
@@ -0,0 +1,24 @@
1
+ import path from "node:path";
2
+ import { TARGET } from "../lib/paths.mjs";
3
+ import { writeText, exists } from "../lib/fs.mjs";
4
+ import { renderArtifactsDoc } from "../lib/artifacts.mjs";
5
+ import { log, cyan } from "../lib/log.mjs";
6
+
7
+ /**
8
+ * Regenerate docs/ARTIFACTS.md in a target project from the single-source manifest.
9
+ * (init/update call writeArtifacts directly; this is the manual on-demand entry point.)
10
+ */
11
+ export function artifacts(targetDir) {
12
+ const root = path.resolve(targetDir || ".");
13
+ if (!exists(path.join(root, TARGET.docs))) {
14
+ log.warn("No docs/ here. Run `groundwork init` first.");
15
+ return;
16
+ }
17
+ writeArtifacts(root);
18
+ log.ok(`Regenerated ${cyan("docs/ARTIFACTS.md")} from the manifest.`);
19
+ }
20
+
21
+ /** Write docs/ARTIFACTS.md from the manifest. Shared by init/update. */
22
+ export function writeArtifacts(root) {
23
+ writeText(path.join(root, TARGET.docs, "ARTIFACTS.md"), renderArtifactsDoc());
24
+ }