@keighleykodric/weeve 0.1.0 → 0.1.2

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 (98) hide show
  1. package/README.md +75 -19
  2. package/bin/weeve.js +467 -2
  3. package/examples/core/CODEOWNERS.template +9 -0
  4. package/examples/core/README.md +63 -0
  5. package/examples/core/demo/README.md +38 -0
  6. package/examples/core/demo/weeve/ally/ally-intake.md +16 -0
  7. package/examples/core/demo/weeve/compass/compass-intake.md +15 -0
  8. package/examples/core/demo/weeve/layers-plus/figma-notes.md +31 -0
  9. package/examples/core/demo/weeve/layers-plus/layers-plus-intake.md +13 -0
  10. package/examples/core/demo/weeve/rubric/component-inventory.md +42 -0
  11. package/examples/core/demo/weeve/rubric/rubric-intake.md +14 -0
  12. package/examples/core/demo/weeve/shared/competitive.md +28 -0
  13. package/examples/core/demo/weeve/shared/roadmap.md +26 -0
  14. package/examples/core/demo/weeve/shared/weeve-guardrails.md +28 -0
  15. package/examples/core/demo/weeve/shared/weeve-intake.md +18 -0
  16. package/examples/core/demo/weeve/shared/weeve-project.md +33 -0
  17. package/examples/core/demo/weeve.yaml +15 -0
  18. package/examples/core/weeve.yaml +14 -0
  19. package/examples/engineering/CODEOWNERS.template +9 -0
  20. package/examples/engineering/README.md +61 -0
  21. package/examples/engineering/demo/README.md +20 -0
  22. package/examples/engineering/demo/weeve/forge/architecture.md +39 -0
  23. package/examples/engineering/demo/weeve/forge/ci-metrics.md +47 -0
  24. package/examples/engineering/demo/weeve/forge/forge-intake.md +41 -0
  25. package/examples/engineering/demo/weeve/guard/guard-intake.md +17 -0
  26. package/examples/engineering/demo/weeve/helm/helm-intake.md +16 -0
  27. package/examples/engineering/demo/weeve/helm/incidents.md +40 -0
  28. package/examples/engineering/demo/weeve/helm/on-call-runbook.md +33 -0
  29. package/examples/engineering/demo/weeve/shared/roadmap.md +25 -0
  30. package/examples/engineering/demo/weeve/shared/team.md +33 -0
  31. package/examples/engineering/demo/weeve/shared/weeve-guardrails.md +27 -0
  32. package/examples/engineering/demo/weeve/shared/weeve-intake.md +18 -0
  33. package/examples/engineering/demo/weeve/shared/weeve-project.md +29 -0
  34. package/examples/engineering/demo/weeve/verify/coverage-report.md +49 -0
  35. package/examples/engineering/demo/weeve/verify/verify-intake.md +16 -0
  36. package/examples/engineering/demo/weeve.yaml +15 -0
  37. package/examples/engineering/weeve.yaml +14 -0
  38. package/examples/gtm/CODEOWNERS.template +8 -0
  39. package/examples/gtm/README.md +59 -0
  40. package/examples/gtm/demo/README.md +19 -0
  41. package/examples/gtm/demo/weeve/compass/compass-intake.md +15 -0
  42. package/examples/gtm/demo/weeve/maven/maven-intake.md +35 -0
  43. package/examples/gtm/demo/weeve/maven/website-notes.md +33 -0
  44. package/examples/gtm/demo/weeve/pitch/pitch-intake.md +54 -0
  45. package/examples/gtm/demo/weeve/pitch/sales-deck-notes.md +28 -0
  46. package/examples/gtm/demo/weeve/pitch/win-loss-notes.md +40 -0
  47. package/examples/gtm/demo/weeve/shared/competitive.md +30 -0
  48. package/examples/gtm/demo/weeve/shared/roadmap.md +19 -0
  49. package/examples/gtm/demo/weeve/shared/weeve-guardrails.md +24 -0
  50. package/examples/gtm/demo/weeve/shared/weeve-intake.md +18 -0
  51. package/examples/gtm/demo/weeve/shared/weeve-project.md +25 -0
  52. package/examples/gtm/demo/weeve.yaml +22 -0
  53. package/examples/gtm/weeve.yaml +14 -0
  54. package/examples/product/CODEOWNERS.template +10 -0
  55. package/examples/product/README.md +67 -0
  56. package/examples/product/demo/README.md +21 -0
  57. package/examples/product/demo/weeve/ally/ally-intake.md +16 -0
  58. package/examples/product/demo/weeve/compass/compass-intake.md +15 -0
  59. package/examples/product/demo/weeve/felt/felt-intake.md +37 -0
  60. package/examples/product/demo/weeve/felt/user-research.md +68 -0
  61. package/examples/product/demo/weeve/layers-plus/layers-plus-intake.md +14 -0
  62. package/examples/product/demo/weeve/rubric/component-inventory.md +42 -0
  63. package/examples/product/demo/weeve/rubric/rubric-intake.md +14 -0
  64. package/examples/product/demo/weeve/shared/competitive.md +28 -0
  65. package/examples/product/demo/weeve/shared/roadmap.md +32 -0
  66. package/examples/product/demo/weeve/shared/weeve-guardrails.md +27 -0
  67. package/examples/product/demo/weeve/shared/weeve-intake.md +18 -0
  68. package/examples/product/demo/weeve/shared/weeve-project.md +29 -0
  69. package/examples/product/demo/weeve.yaml +21 -0
  70. package/examples/product/weeve.yaml +14 -0
  71. package/examples/strategy/CODEOWNERS.template +8 -0
  72. package/examples/strategy/README.md +59 -0
  73. package/examples/strategy/demo/README.md +19 -0
  74. package/examples/strategy/demo/weeve/compass/compass-intake.md +34 -0
  75. package/examples/strategy/demo/weeve/compass/customer-segments.md +34 -0
  76. package/examples/strategy/demo/weeve/layers-plus/layers-plus-intake.md +15 -0
  77. package/examples/strategy/demo/weeve/maven/maven-intake.md +33 -0
  78. package/examples/strategy/demo/weeve/shared/competitive.md +40 -0
  79. package/examples/strategy/demo/weeve/shared/roadmap.md +29 -0
  80. package/examples/strategy/demo/weeve/shared/weeve-guardrails.md +22 -0
  81. package/examples/strategy/demo/weeve/shared/weeve-intake.md +17 -0
  82. package/examples/strategy/demo/weeve/shared/weeve-project.md +25 -0
  83. package/examples/strategy/demo/weeve.yaml +15 -0
  84. package/examples/strategy/weeve.yaml +14 -0
  85. package/package.json +14 -3
  86. package/spec/contributing-template.md +109 -0
  87. package/spec/readme-template.md +55 -0
  88. package/{docs/shared/SHIP-GATE.md → spec/ship-gate.md} +7 -7
  89. package/spec/signals-schema.md +685 -0
  90. package/spec/weeve-yaml.md +274 -0
  91. package/.github/SECURITY.md +0 -22
  92. package/GOVERNANCE.md +0 -173
  93. package/WORKFLOW.md +0 -354
  94. package/docs/shared/engineering-pack-contract.md +0 -94
  95. package/docs/shared/id-prefix-reference.md +0 -235
  96. package/docs/shared/idea-intake-pattern.md +0 -99
  97. package/docs/shared/lane-conventions.md +0 -207
  98. package/docs/shared/recommendations-schema.md +0 -363
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
- # Weeve
1
+ # 🧵 Weeve
2
2
 
3
- Cross-functional alignment system. 14+ lanes that audit strategy, product, design, engineering, QA, security, marketing, sales, and UX then synthesize into one prioritized roadmap.
3
+ Cross-functional contract framework. Each domain writes findings in the same versioned schema shape — Pilot reads them all and surfaces what conflicts, what blocks the ship, and what to do first. Observability for AI-orchestrated execution.
4
4
 
5
- Markdown-in-git. BYO everything. Each lane writes a `<lane>-recommendations.md` file in the same shape. Pilot reads them all and produces a single roadmap. The alignment property: findings from different domains compose, rather than sit in separate files nobody reads.
5
+ Markdown-in-git. BYO everything. The contract shape is the durable asset: a versioned schema that every lane writes to and Pilot synthesizes from. Findings from different domains compose because they share a common structure not because a platform forces alignment.
6
6
 
7
7
  ---
8
8
 
@@ -10,9 +10,9 @@ Markdown-in-git. BYO everything. Each lane writes a `<lane>-recommendations.md`
10
10
 
11
11
  1. Install the lanes you need
12
12
  2. Run each lane against your product (`/<lane>-intro` to start)
13
- 3. Each lane writes findings to `docs/<lane>/<lane>-recommendations.md`
14
- 4. Run `/pilot-roadmap` — Pilot reads all lane outputs and synthesizes a prioritized roadmap
15
- 5. Run `/pilot-ship` — autonomous worker picks tasks from the roadmap and ships them
13
+ 3. Each lane writes findings to `docs/<lane>/<lane>-signals.md`
14
+ 4. Run `/pilot-priorities` — Pilot reads all lane outputs and synthesizes a prioritized backlog
15
+ 5. Run `/pilot-ship` — autonomous worker picks tasks from the priorities file and ships them
16
16
 
17
17
  ---
18
18
 
@@ -66,9 +66,13 @@ Markdown-in-git. BYO everything. Each lane writes a `<lane>-recommendations.md`
66
66
 
67
67
  ---
68
68
 
69
+ > **Trust model:** Skills execute with your OS permissions — only install from trusted sources.
70
+
71
+ ---
72
+
69
73
  ## You don't need every lane
70
74
 
71
- Install only the lanes that match your team. If marketing doesn't use Maven, that's fine — Maven won't appear in the Pilot roadmap, and nothing breaks.
75
+ Install only the lanes that match your team. If marketing doesn't use Maven, that's fine — Maven won't appear in the Pilot priorities file, and nothing breaks.
72
76
 
73
77
  Departments without a lane can still contribute. Any team member can feed context into another lane's intake skill — paste a doc, a ticket link, or a screenshot into `/compass-intake` or `/layers-plus-intake` and it gets scoped and routed. You don't need a lane installed to provide input; you just won't get lane-specific findings back.
74
78
 
@@ -77,12 +81,12 @@ Departments without a lane can still contribute. Any team member can feed contex
77
81
  Not sure which lanes to install? Pick a preset that matches your role:
78
82
 
79
83
  ```
80
- npx weeve add core # Designer/strategist starting point
81
- npx weeve add product # Product manager — strategy + design + research
82
- npx weeve add engineering # Engineering lead — delivery + security + QA
83
- npx weeve add strategy # Founder/leadership — strategy + marketing
84
- npx weeve add gtm # Go-to-market — strategy + marketing + sales
85
- npx weeve add all # Everything
84
+ npx @keighleykodric/weeve add core # Designer/strategist starting point
85
+ npx @keighleykodric/weeve add product # Product manager — strategy + design + research
86
+ npx @keighleykodric/weeve add engineering # Engineering lead — delivery + security + QA
87
+ npx @keighleykodric/weeve add strategy # Founder/leadership — strategy + marketing
88
+ npx @keighleykodric/weeve add gtm # Go-to-market — strategy + marketing + sales
89
+ npx @keighleykodric/weeve add all # Everything
86
90
  ```
87
91
 
88
92
  | Preset | Lanes included |
@@ -96,6 +100,16 @@ npx weeve add all # Everything
96
100
 
97
101
  Every preset includes Pilot — it's the synthesis layer that makes the lanes compose.
98
102
 
103
+ ### Version pinning
104
+
105
+ Pin to a tagged release for reproducible installs:
106
+
107
+ ```
108
+ npx skills add keighleykodric/weeve-compass@v0.1.0
109
+ ```
110
+
111
+ See [Releases](https://github.com/keighleykodric/weeve/releases) for available versions.
112
+
99
113
  ---
100
114
 
101
115
  ## First-run order
@@ -106,22 +120,64 @@ See [WORKFLOW.md](WORKFLOW.md) for the full cadence, within-lane sequences, and
106
120
 
107
121
  ---
108
122
 
109
- ## The alignment property
123
+ ## The contract shape
110
124
 
111
- Each lane writes findings independently. Pilot reads them all and surfaces:
125
+ Each lane writes findings independently, in the same schema. Pilot reads them all and surfaces:
112
126
  - Cross-lane conflicts (strategy says X, design says Y)
113
127
  - Ship gates (Guard or Verify can block `/pilot-ship`)
114
128
  - Priority synthesis (what to do first, across all domains)
115
129
 
116
- The claim: running all lanes against the same product produces coherent, composable outputnot just a bigger folder of tools.
130
+ The schema is what makes the lanes composable. A finding from Guard and a finding from Compass use the same severity vocabulary, status field, and ID prefix so Pilot can synthesize them without translation. The contract is the moat, not the lane count.
117
131
 
118
132
  ---
119
133
 
120
134
  ## Schema
121
135
 
122
- All lane recommendations files follow a versioned schema: [recommendations-schema.md](docs/shared/recommendations-schema.md) (v0.3).
136
+ All lane signals files follow a versioned schema: [signals-schema.md](spec/schema.md) (v0.4).
137
+
138
+ The schema is the contract. Severity uses `🔴 High / 🟡 Medium / 🟢 Low`. Lane files never use Now/Next/Watch — that vocabulary belongs to Pilot's priorities output. The manifest hierarchy (`weeve.yaml` → `road.yaml` → `lane.yaml`) governs multi-lane configuration.
139
+
140
+ ---
141
+
142
+ ## Alternative installation (git clone)
143
+
144
+ If you prefer not to use the npm installer, you can clone lanes directly and verify integrity:
145
+
146
+ ```bash
147
+ # Clone a specific tagged release
148
+ git clone --branch v0.1.0 --depth 1 https://github.com/keighleykodric/weeve-compass.git
149
+
150
+ # Verify the commit SHA matches the published release
151
+ cd weeve-compass
152
+ git rev-parse HEAD
153
+ # Compare against the SHA listed on https://github.com/keighleykodric/weeve-compass/releases/tag/v0.1.0
154
+
155
+ # Verify skills-lock.json integrity (if present)
156
+ # skills-lock.json contains SHA-256 hashes of all SKILL.md files
157
+ cat skills-lock.json
158
+ # Manually verify: shasum -a 256 skills/<skill-dir>/SKILL.md
159
+ ```
160
+
161
+ Then symlink or copy the skills directory into `~/.claude/skills/`:
162
+
163
+ ```bash
164
+ cp -r skills/* ~/.claude/skills/
165
+ ```
166
+
167
+ This bypasses the npm registry entirely. You can audit all code before installation and verify that file contents match the published hashes in `skills-lock.json`.
168
+
169
+ ---
170
+
171
+ ## Terminology
172
+
173
+ Two terms in Weave overlap with common engineering vocabulary:
174
+
175
+ | Term | In Weave | In engineering contexts |
176
+ |---|---|---|
177
+ | **Operator** | The practitioner running the lanes — a cross-functional lead, designer, or strategist using Claude Code | Infrastructure operator, DevOps engineer, Kubernetes operator |
178
+ | **Schema** | The governance spec that defines how lanes write findings (`spec/schema.md`) | Database schema, OpenAPI spec, JSON Schema |
123
179
 
124
- The schema is the durable asset. Severity uses `🔴 High / 🟡 Medium / 🟢 Low`. Lane files never use Now/Next/Watch that vocabulary belongs to Pilot's roadmap output.
180
+ If you come from an infrastructure or data engineering background: Weave's "Operator" is closer to "practitioner" or "user," and Weave's "Schema" is closer to "contract format" or "output spec."
125
181
 
126
182
  ---
127
183
 
@@ -129,7 +185,7 @@ The schema is the durable asset. Severity uses `🔴 High / 🟡 Medium / 🟢 L
129
185
 
130
186
  Each lane is its own repo. To contribute to a lane, open an issue or PR on that lane's repo.
131
187
 
132
- To build a community lane, see [GOVERNANCE.md](GOVERNANCE.md) for the pack.yaml spec, CODEOWNERS model, and the ship interface contract.
188
+ To build a community lane, see [GOVERNANCE.md](GOVERNANCE.md) for the lane.yaml spec, CODEOWNERS model, and the ship interface contract.
133
189
 
134
190
  ---
135
191
 
package/bin/weeve.js CHANGED
@@ -1,6 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const { execSync } = require("child_process");
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+ const os = require("os");
4
7
 
5
8
  const ORG = "keighleykodric";
6
9
 
@@ -37,6 +40,27 @@ const PRESETS = {
37
40
  gtm: ["compass", "maven", "pitch", "pilot"],
38
41
  };
39
42
 
43
+ // CODEOWNERS lines per lane
44
+ const LANE_OWNERS = {
45
+ compass: "weeve/compass/ @leadership",
46
+ "layers-plus": "weeve/layers-plus/ @product",
47
+ felt: "weeve/felt/ @product",
48
+ ally: "weeve/ally/ @design",
49
+ rubric: "weeve/rubric/ @design",
50
+ forge: "weeve/forge/ @engineering",
51
+ helm: "weeve/helm/ @engineering",
52
+ verify: "weeve/verify/ @engineering",
53
+ guard: "weeve/guard/ @security",
54
+ maven: "weeve/maven/ @marketing",
55
+ pitch: "weeve/pitch/ @revenue",
56
+ pilot: "weeve/pilot/ @leadership",
57
+ };
58
+
59
+ const FIRST_STEP_ORDER = [
60
+ "compass", "layers-plus", "felt", "ally", "rubric",
61
+ "forge", "helm", "verify", "guard", "maven", "pitch", "pilot",
62
+ ];
63
+
40
64
  const cmd = process.argv[2];
41
65
  const args = process.argv.slice(3);
42
66
 
@@ -62,7 +86,16 @@ function installLanes(lanes) {
62
86
  console.log(` + ${lane} — ${LANES[lane]}`);
63
87
  run(`npx skills add ${repo}`);
64
88
  }
65
- console.log(`\nDone. Run /pilot-intro to get started.\n`);
89
+ // Always install framework skills from the weeve repo itself
90
+ run(`npx skills add ${ORG}/weeve`);
91
+ // Show the right first step based on what was installed
92
+ const firstLane = FIRST_STEP_ORDER.find((l) => lanes.includes(l));
93
+ if (firstLane && firstLane !== "pilot") {
94
+ console.log(`\nDone. Run /${firstLane}-intro to get started.`);
95
+ console.log(`Then work through your lanes. Run /pilot-intro last — it reads all lane outputs.\n`);
96
+ } else {
97
+ console.log(`\nDone. Run /pilot-intro to get started.\n`);
98
+ }
66
99
  }
67
100
 
68
101
  switch (cmd) {
@@ -87,6 +120,421 @@ switch (cmd) {
87
120
  break;
88
121
  }
89
122
 
123
+ case "init": {
124
+ const presetArg = args[0];
125
+
126
+ // Resolve lanes to scaffold
127
+ let lanes;
128
+ if (!presetArg) {
129
+ lanes = Object.keys(LANES);
130
+ } else if (PRESETS[presetArg]) {
131
+ lanes = PRESETS[presetArg];
132
+ } else if (LANES[presetArg]) {
133
+ lanes = [presetArg];
134
+ } else {
135
+ console.error(`Unknown preset or lane: ${presetArg}`);
136
+ console.error(`Run 'weeve presets' to see available presets.`);
137
+ process.exit(1);
138
+ }
139
+
140
+ const cwd = process.cwd();
141
+ const yamlPath = path.join(cwd, "weeve.yaml");
142
+
143
+ // Bail if weeve.yaml already exists
144
+ if (fs.existsSync(yamlPath)) {
145
+ console.error(`Warning: weeve.yaml already exists in ${cwd}. Exiting without changes.`);
146
+ process.exit(1);
147
+ }
148
+
149
+ // 1. Create weeve/<lane>/ output folders
150
+ for (const lane of lanes) {
151
+ const laneDir = path.join(cwd, "weeve", lane);
152
+ fs.mkdirSync(laneDir, { recursive: true });
153
+ fs.writeFileSync(path.join(laneDir, ".gitkeep"), "");
154
+ }
155
+
156
+ // 1b. Create loom/ content-type folders based on installed lanes, plus shared/ and archive/
157
+ // Loom is organised by content type, not lane — multiple lanes share the same folder.
158
+ const loomFolders = new Set(["shared"]);
159
+ const LOOM_MAP = {
160
+ strategy: ["compass"],
161
+ business: ["compass", "guard"],
162
+ design: ["ally", "layers-plus", "rubric"],
163
+ engineering: ["forge", "helm", "verify", "guard", "layers-plus"],
164
+ research: ["felt"],
165
+ marketing: ["maven", "rubric"],
166
+ sales: ["pitch"],
167
+ };
168
+ for (const [folder, owners] of Object.entries(LOOM_MAP)) {
169
+ if (owners.some((l) => lanes.includes(l))) loomFolders.add(folder);
170
+ }
171
+ for (const folder of loomFolders) {
172
+ const dir = path.join(cwd, "loom", folder);
173
+ fs.mkdirSync(dir, { recursive: true });
174
+ fs.writeFileSync(path.join(dir, ".gitkeep"), "");
175
+ }
176
+ fs.mkdirSync(path.join(cwd, "archive"), { recursive: true });
177
+
178
+ // 2. Write weeve.yaml
179
+ const projName = path.basename(cwd);
180
+ const projTag = projName.replace(/[^a-zA-Z0-9]/g, "").slice(0, 6).toUpperCase() || "MYP";
181
+ const yaml = [
182
+ `# weeve.yaml — generated by weeve init`,
183
+ `schema_version: "0.4"`,
184
+ ``,
185
+ `project:`,
186
+ ` name: ${projName}`,
187
+ ` tag: ${projTag}`,
188
+ ` # docs_root: ./weeve # Uncomment to write skill outputs here instead of vault`,
189
+ ` # loom_root: ./loom # Uncomment to read raw input from here instead of vault`,
190
+ ` # repos: # Multi-repo: list other repos that share this tag`,
191
+ ` # - name: api`,
192
+ ` # path: ../my-api`,
193
+ ` # depends_on: # Other weeve projects this project reads context from`,
194
+ ` # - tag: API`,
195
+ ` # name: Core API`,
196
+ ` # relationship: api-contract`,
197
+ ``,
198
+ `roads:`,
199
+ ` - name: startup`,
200
+ ` path: roads/startup`,
201
+ ``,
202
+ `# Installed lanes: ${lanes.join(", ")}`,
203
+ `# Run 'weeve status' to see installed skills`,
204
+ ``,
205
+ ].join("\n");
206
+ fs.writeFileSync(yamlPath, yaml);
207
+
208
+ // 3a. Scaffold weeve/shared/ for skill-managed shared docs
209
+ const sharedDir = path.join(cwd, "weeve", "shared");
210
+ fs.mkdirSync(sharedDir, { recursive: true });
211
+
212
+ fs.writeFileSync(path.join(sharedDir, "weeve-project.md"), [
213
+ `# ${projName} — project brief`,
214
+ ``,
215
+ `<!-- What are you building, who is it for, what stage are you at? -->`,
216
+ `<!-- Include: product surface, current state, team size, open questions -->`,
217
+ ``,
218
+ `**What it is:**`,
219
+ ``,
220
+ `**Stage:**`,
221
+ ``,
222
+ `**Core surface:**`,
223
+ ``,
224
+ `**Current state:**`,
225
+ ``,
226
+ `**Team:**`,
227
+ ``,
228
+ `**Open questions:**`,
229
+ ``,
230
+ ].join("\n"));
231
+
232
+ fs.writeFileSync(path.join(sharedDir, "weeve-decisions.md"), [
233
+ `# ${projName} — key decisions`,
234
+ ``,
235
+ `<!-- Architectural, product, and strategic decisions that are settled.`,
236
+ ` Lanes use this to avoid re-opening closed questions. -->`,
237
+ `<!-- Format: - [DATE] Decision. Reason. -->`,
238
+ ``,
239
+ ].join("\n"));
240
+
241
+ fs.writeFileSync(path.join(sharedDir, "weeve-guardrails.md"), [
242
+ `# ${projName} — constraints`,
243
+ ``,
244
+ `<!-- Hard limits and non-negotiables. Lanes treat these as guardrails. -->`,
245
+ `<!-- Pilot and all lanes read this before picking or executing tasks. -->`,
246
+ `<!-- Examples: no external SaaS without security review, must pass WCAG AA, -->`,
247
+ `<!-- no breaking API changes without deprecation period -->`,
248
+ ``,
249
+ ].join("\n"));
250
+
251
+ fs.writeFileSync(path.join(sharedDir, "weeve-sources.md"), [
252
+ `# ${projName} — context sources`,
253
+ ``,
254
+ `<!-- Links to external docs lanes should be aware of. -->`,
255
+ `<!-- Org strategy, brand guidelines, API contracts, compliance docs, etc. -->`,
256
+ `<!-- Format: - **Label:** [Title](url) — one-line description -->`,
257
+ ``,
258
+ ].join("\n"));
259
+
260
+ // 3. Write or append CODEOWNERS
261
+ const codeownersPath = path.join(cwd, "CODEOWNERS");
262
+ const ownerLines = lanes
263
+ .filter((l) => LANE_OWNERS[l])
264
+ .map((l) => LANE_OWNERS[l]);
265
+ const codeownersBlock = [
266
+ `# Weeve lane ownership — edit to match your team structure`,
267
+ ...ownerLines,
268
+ ``,
269
+ ].join("\n");
270
+
271
+ if (fs.existsSync(codeownersPath)) {
272
+ fs.appendFileSync(codeownersPath, "\n" + codeownersBlock);
273
+ } else {
274
+ fs.writeFileSync(codeownersPath, codeownersBlock);
275
+ }
276
+
277
+ // 4. Summary
278
+ const firstLane = FIRST_STEP_ORDER.find((l) => lanes.includes(l));
279
+ const nextCmd = firstLane && firstLane !== "pilot"
280
+ ? `/${firstLane}-intro`
281
+ : `/pilot-intro`;
282
+
283
+ console.log(`\nWeeve initialized${presetArg ? ` (${presetArg} preset)` : ""}:\n`);
284
+ console.log(` Created weeve.yaml`);
285
+ console.log(` Created CODEOWNERS${fs.existsSync(codeownersPath) ? " (appended)" : ""}`);
286
+ console.log(` Created weeve/shared/weeve-project.md`);
287
+ console.log(` Created weeve/shared/weeve-decisions.md`);
288
+ console.log(` Created weeve/shared/weeve-guardrails.md`);
289
+ console.log(` Created weeve/shared/weeve-sources.md`);
290
+ console.log(` Created archive/`);
291
+ for (const lane of lanes) {
292
+ console.log(` Created weeve/${lane}/`);
293
+ }
294
+ const loomList = [...loomFolders].filter((f) => f !== "shared").sort().join("/ loom/");
295
+ console.log(` Created loom/${loomList}/ loom/shared/`);
296
+ console.log(`\n weeve/ — skill outputs (written by skills)`);
297
+ console.log(` loom/ — your input: drop notes, research, briefs here (organised by content type)`);
298
+ console.log(` archive/ — historical snapshots\n`);
299
+ console.log(`\nNext: run 'weeve add ${presetArg || "all"}' to install skills, then run ${nextCmd}\n`);
300
+ break;
301
+ }
302
+
303
+ case "status": {
304
+ const lockPath = path.join(os.homedir(), ".claude", "skills-lock.json");
305
+
306
+ if (!fs.existsSync(lockPath)) {
307
+ console.log("No weeve lanes installed. Run 'weeve add <lane>' to get started.");
308
+ break;
309
+ }
310
+
311
+ let lock;
312
+ try {
313
+ lock = JSON.parse(fs.readFileSync(lockPath, "utf8"));
314
+ } catch {
315
+ console.error(`Could not parse ${lockPath}`);
316
+ process.exit(1);
317
+ }
318
+
319
+ const skills = lock.skills || {};
320
+
321
+ // Group skills by weeve lane (source matches keighleykodric/weeve-<lane>)
322
+ const laneMap = {};
323
+ for (const [skillName, skillData] of Object.entries(skills)) {
324
+ const source = skillData.source || "";
325
+ const match = source.match(/^keighleykodric\/weeve-(.+)$/);
326
+ if (match) {
327
+ const lane = match[1];
328
+ if (!laneMap[lane]) {
329
+ laneMap[lane] = { count: 0, source };
330
+ }
331
+ laneMap[lane].count++;
332
+ }
333
+ }
334
+
335
+ if (Object.keys(laneMap).length === 0) {
336
+ console.log("No weeve lanes installed. Run 'weeve add <lane>' to get started.");
337
+ break;
338
+ }
339
+
340
+ console.log("\nInstalled lanes:\n");
341
+ const laneNames = Object.keys(laneMap);
342
+ const maxLane = Math.max(...laneNames.map((l) => l.length));
343
+ for (const lane of laneNames) {
344
+ const { count, source } = laneMap[lane];
345
+ console.log(
346
+ ` ${lane.padEnd(maxLane + 2)}${String(count).padStart(2)} skills ${source}`
347
+ );
348
+ }
349
+
350
+ const firstInstalled = FIRST_STEP_ORDER.find((l) => laneMap[l]);
351
+ const nextCmd = firstInstalled && firstInstalled !== "pilot"
352
+ ? `/${firstInstalled}-intro`
353
+ : `/pilot-intro`;
354
+
355
+ console.log(`\n${laneNames.length} lane${laneNames.length !== 1 ? "s" : ""} installed. Run ${nextCmd} to get started.\n`);
356
+ break;
357
+ }
358
+
359
+ case "remove":
360
+ case "uninstall": {
361
+ if (!args.length) {
362
+ console.error("Usage: weeve remove <lane|preset> [lane2...]");
363
+ process.exit(1);
364
+ }
365
+
366
+ // Expand preset or validate individual lanes
367
+ let lanes;
368
+ if (args.length === 1 && PRESETS[args[0]]) {
369
+ const preset = args[0];
370
+ console.log(`Removing preset: ${preset} (${PRESETS[preset].join(", ")})`);
371
+ lanes = PRESETS[preset];
372
+ } else {
373
+ const invalid = args.filter((l) => !LANES[l]);
374
+ if (invalid.length) {
375
+ console.error(`Unknown lane(s): ${invalid.join(", ")}`);
376
+ console.error(`Run 'weeve list' to see available lanes.`);
377
+ process.exit(1);
378
+ }
379
+ lanes = args;
380
+ }
381
+
382
+ console.log(`\nRemoving ${lanes.length} lane(s)...\n`);
383
+ for (const lane of lanes) {
384
+ const repo = `${ORG}/weeve-${lane}`;
385
+ console.log(` - ${lane}`);
386
+ run(`npx skills remove ${repo}`);
387
+ }
388
+ console.log(`\nDone. Removed: ${lanes.join(", ")}\n`);
389
+ break;
390
+ }
391
+
392
+ case "demo": {
393
+ const presetArg = args[0];
394
+
395
+ if (!presetArg) {
396
+ console.log("\nAvailable demos:\n");
397
+ const demoPreviews = {
398
+ core: "Prism — design token management SaaS (compass, layers-plus, ally, rubric, pilot)",
399
+ engineering: "Volta — internal developer platform (forge, helm, verify, guard, pilot)",
400
+ product: "Canvas — no-code form builder (compass, layers-plus, ally, rubric, felt, pilot)",
401
+ strategy: "Beacon — B2B analytics at a strategic inflection point (compass, layers-plus, maven, pilot)",
402
+ gtm: "Relay — outbound sales automation SaaS (compass, maven, pitch, pilot)",
403
+ };
404
+ const maxName = Math.max(...Object.keys(demoPreviews).map((k) => k.length));
405
+ for (const [name, desc] of Object.entries(demoPreviews)) {
406
+ console.log(` ${name.padEnd(maxName + 2)}${desc}`);
407
+ }
408
+ console.log("\nUsage: weeve demo <preset>\n");
409
+ break;
410
+ }
411
+
412
+ if (!PRESETS[presetArg]) {
413
+ console.error(`Unknown preset: ${presetArg}`);
414
+ console.error("Run 'weeve demo' to see available demos.");
415
+ process.exit(1);
416
+ }
417
+
418
+ const demoSrc = path.join(__dirname, "..", "examples", presetArg, "demo");
419
+
420
+ if (!fs.existsSync(demoSrc)) {
421
+ console.error(`No demo found for preset: ${presetArg}`);
422
+ process.exit(1);
423
+ }
424
+
425
+ const cwd = process.cwd();
426
+ const weeveYaml = path.join(cwd, "weeve.yaml");
427
+
428
+ if (fs.existsSync(weeveYaml)) {
429
+ console.error(`weeve.yaml already exists in ${cwd}. Remove it first or run in an empty directory.`);
430
+ process.exit(1);
431
+ }
432
+
433
+ // Recursively copy demo folder to cwd
434
+ function copyDir(src, dest) {
435
+ fs.mkdirSync(dest, { recursive: true });
436
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
437
+ const srcPath = path.join(src, entry.name);
438
+ const destPath = path.join(dest, entry.name);
439
+ if (entry.isDirectory()) {
440
+ copyDir(srcPath, destPath);
441
+ } else {
442
+ fs.copyFileSync(srcPath, destPath);
443
+ }
444
+ }
445
+ }
446
+
447
+ copyDir(demoSrc, cwd);
448
+
449
+ const demoNames = { core: "Prism", engineering: "Volta", product: "Canvas", strategy: "Beacon", gtm: "Relay" };
450
+ const demoName = demoNames[presetArg];
451
+ const firstLane = FIRST_STEP_ORDER.find((l) => PRESETS[presetArg].includes(l));
452
+ const firstCmd = firstLane && firstLane !== "pilot" ? `/${firstLane}-intro` : `/pilot-intro`;
453
+
454
+ console.log(`\nDemo ready: ${demoName} (${presetArg} preset)\n`);
455
+ console.log(` weeve.yaml project config (docs_root: ./docs)`);
456
+ console.log(` docs/shared/ weeve-project.md, weeve-guardrails.md, weeve-intake.md\n`);
457
+ console.log(`Next steps:`);
458
+ console.log(` 1. weeve add ${presetArg} — install the lanes`);
459
+ console.log(` 2. ${firstCmd} — start the first lane\n`);
460
+ break;
461
+ }
462
+
463
+ case "project": {
464
+ const subcmd = args[0];
465
+
466
+ if (!subcmd || subcmd === "show") {
467
+ // Walk up from cwd to find weeve.yaml
468
+ let dir = process.cwd();
469
+ let found = null;
470
+ for (let i = 0; i < 4; i++) {
471
+ const candidate = path.join(dir, "weeve.yaml");
472
+ if (fs.existsSync(candidate)) {
473
+ found = candidate;
474
+ break;
475
+ }
476
+ const parent = path.dirname(dir);
477
+ if (parent === dir) break;
478
+ dir = parent;
479
+ }
480
+
481
+ if (!found) {
482
+ console.log("\nNo weeve.yaml found in this directory or its parents.");
483
+ console.log("Run 'weeve init [preset]' to create one.\n");
484
+ break;
485
+ }
486
+
487
+ const raw = fs.readFileSync(found, "utf8");
488
+ console.log(`\nProject config: ${found}\n`);
489
+
490
+ // Parse and display key fields
491
+ const nameMatch = raw.match(/^\s{2}name:\s*(.+)$/m);
492
+ const tagMatch = raw.match(/^\s{2}tag:\s*(.+)$/m);
493
+ const docsMatch = raw.match(/^\s{2}docs_root:\s*(.+)$/m);
494
+ const schemaMatch = raw.match(/^schema_version:\s*(.+)$/m);
495
+
496
+ const name = nameMatch ? nameMatch[1].trim() : "(not set)";
497
+ const tag = tagMatch ? tagMatch[1].trim() : "(not set)";
498
+ const docsRoot = docsMatch ? docsMatch[1].trim() : `<vault>/Projects/${tag}/docs (via Claudette)`;
499
+ const schema = schemaMatch ? schemaMatch[1].trim() : "(not set)";
500
+
501
+ const maxLabel = 14;
502
+ console.log(` ${"name".padEnd(maxLabel)}${name}`);
503
+ console.log(` ${"tag".padEnd(maxLabel)}${tag}`);
504
+ console.log(` ${"docs_root".padEnd(maxLabel)}${docsRoot}`);
505
+ console.log(` ${"schema_version".padEnd(maxLabel)}${schema}`);
506
+
507
+ // Check for repos
508
+ const reposBlock = raw.match(/^\s{2}repos:\n((?:\s{4}.+\n?)*)/m);
509
+ if (reposBlock) {
510
+ console.log(` ${"repos".padEnd(maxLabel)}${reposBlock[1].trim().split("\n").length} registered`);
511
+ }
512
+
513
+ // Check for depends_on
514
+ const depsBlock = raw.match(/^\s{2}depends_on:\n((?:\s{4}.+\n?)*)/m);
515
+ if (depsBlock) {
516
+ const depTags = [...depsBlock[1].matchAll(/tag:\s*(\S+)/g)].map((m) => m[1]);
517
+ const depNames = [...depsBlock[1].matchAll(/name:\s*(.+)/g)].map((m) => m[1].trim());
518
+ const depList = depTags.map((tag, i) => depNames[i] ? `${depNames[i]} (${tag})` : tag).join(", ");
519
+ console.log(` ${"depends_on".padEnd(maxLabel)}${depList}`);
520
+ }
521
+
522
+ // Check for shared docs
523
+ const sharedDir = path.join(path.dirname(found), "docs", "shared");
524
+ if (fs.existsSync(sharedDir)) {
525
+ const sharedFiles = fs.readdirSync(sharedDir).filter((f) => f.endsWith(".md"));
526
+ console.log(` ${"shared/".padEnd(maxLabel)}${sharedFiles.join(", ")}`);
527
+ }
528
+
529
+ console.log();
530
+ break;
531
+ }
532
+
533
+ console.error(`Unknown project subcommand: ${subcmd}`);
534
+ console.error("Usage: weeve project show");
535
+ process.exit(1);
536
+ }
537
+
90
538
  case "list":
91
539
  case "lanes": {
92
540
  console.log("\nAvailable lanes:\n");
@@ -112,11 +560,24 @@ switch (cmd) {
112
560
  case "--help":
113
561
  case "-h": {
114
562
  console.log(`
115
- weeve — Cross-functional alignment system
563
+ ██╗ ██╗███████╗███████╗██╗ ██╗███████╗
564
+ ██║ ██║██╔════╝██╔════╝██║ ██║██╔════╝
565
+ ██║ █╗ ██║█████╗ █████╗ ██║ ██║█████╗
566
+ ██║███╗██║██╔══╝ ██╔══╝ ╚██╗ ██╔╝██╔══╝
567
+ ╚███╔███╔╝███████╗███████╗ ╚████╔╝ ███████╗
568
+ ╚══╝╚══╝ ╚══════╝╚══════╝ ╚═══╝ ╚══════╝
569
+
570
+ Cross-functional contract framework
116
571
 
117
572
  Commands:
118
573
  weeve add <lane> [lane2...] Install one or more lanes
119
574
  weeve add <preset> Install a preset group of lanes
575
+ weeve remove <lane> [lane2…] Remove one or more lanes
576
+ weeve remove <preset> Remove a preset group of lanes
577
+ weeve init [preset] Scaffold weeve structure in current directory
578
+ weeve demo [preset] Copy a pre-built demo project to current directory
579
+ weeve project show Show current project config (weeve.yaml)
580
+ weeve status Show installed lanes and skill counts
120
581
  weeve list Show all available lanes
121
582
  weeve presets Show preset groups
122
583
 
@@ -124,6 +585,10 @@ Examples:
124
585
  weeve add compass ally pilot Install three lanes
125
586
  weeve add core Install core preset (compass, layers-plus, ally, rubric, pilot)
126
587
  weeve add all Install everything
588
+ weeve init core Scaffold folder structure for the core preset
589
+ weeve demo core Copy the Prism demo project (ready to run immediately)
590
+ weeve status See which lanes are installed
591
+ weeve remove ally Remove a single lane
127
592
 
128
593
  Presets:
129
594
  all Every lane
@@ -0,0 +1,9 @@
1
+ # Weeve lane ownership
2
+ # Copy to .github/CODEOWNERS and replace team handles with your org's teams
3
+ # Requires GitHub branch protection with "Require review from Code Owners" enabled
4
+
5
+ weeve/compass/ @leadership
6
+ weeve/layers-plus/ @product
7
+ weeve/ally/ @design
8
+ weeve/rubric/ @design
9
+ weeve/pilot/ @leadership