cohorte 1.6.0 → 2.0.0
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.
- package/CHANGELOG.md +84 -2
- package/README.md +57 -57
- package/bin/cli.js +23 -15
- package/core/agents/implementer.template.md +3 -3
- package/core/agents/release.md +1 -1
- package/core/agents/review.md +3 -3
- package/core/commands/{audit.md → cohorte-audit.md} +3 -3
- package/core/commands/{brainstorm.md → cohorte-brainstorm.md} +4 -4
- package/core/commands/{build.md → cohorte-build.md} +15 -15
- package/core/commands/{doctor.md → cohorte-doctor.md} +17 -9
- package/core/commands/{fix.md → cohorte-fix.md} +15 -13
- package/core/commands/{init-pipeline.md → cohorte-init-pipeline.md} +1 -1
- package/core/commands/cohorte-loop.md +110 -0
- package/core/commands/{refactor.md → cohorte-refactor.md} +3 -3
- package/core/commands/{review.md → cohorte-review.md} +20 -19
- package/core/commands/{ship.md → cohorte-ship.md} +5 -5
- package/core/commands/{spec.md → cohorte-spec.md} +13 -13
- package/core/commands/{update-pipeline.md → cohorte-update-pipeline.md} +11 -6
- package/core/hooks/gate.py +101 -6
- package/core/templates/brainstorm-return.md +4 -4
- package/core/templates/decisions.template.md +1 -1
- package/core/templates/design-brief.md +1 -1
- package/core/templates/spec.template.md +7 -7
- package/core/templates/steps/init-pipeline/01-detect-stack.md +1 -1
- package/core/templates/steps/init-pipeline/02-interview-gaps.md +6 -6
- package/core/templates/steps/init-pipeline/03-draft-profile.md +1 -1
- package/core/templates/steps/init-pipeline/04-write-render.md +16 -12
- package/core/templates/steps/init-pipeline/05-report.md +5 -5
- package/core/workflows/audit.js +6 -6
- package/core/workflows/refactor.js +14 -14
- package/core/workflows/review.js +22 -22
- package/dashboard/README.md +2 -2
- package/dashboard/dist/assets/{index-DYyn4p93.js → index-P1I1JGtj.js} +2 -2
- package/dashboard/dist/index.html +1 -1
- package/dashboard/server/doctor.js +69 -19
- package/dashboard/server/index.js +5 -5
- package/dashboard/server/metrics.js +1 -1
- package/install.ps1 +23 -14
- package/install.sh +24 -14
- package/package.json +2 -2
- package/profile/PIPELINE.template.md +17 -16
- package/profile/SCHEMA.md +89 -77
- package/profile/cohorte.config.template.yaml +8 -8
- package/scripts/loop-detach.sh +153 -0
- package/scripts/loop.sh +75 -27
- package/scripts/metrics/collect.mjs +17 -8
- package/scripts/new-feature.sh.template +3 -3
- package/scripts/preflight.sh +40 -4
- package/scripts/remove-feature.sh.template +2 -2
- package/scripts/test-dashboard.mjs +34 -7
- package/scripts/test-gate.mjs +58 -0
- package/scripts/test-loop.mjs +49 -7
- package/scripts/test-metrics.mjs +23 -11
- package/scripts/test-workflows.mjs +7 -7
- package/scripts/validate-core.mjs +45 -23
- package/core/commands/drive.md +0 -80
- /package/core/commands/{align-ds.md → cohorte-align-ds.md} +0 -0
package/profile/SCHEMA.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# PIPELINE.md profile — field reference
|
|
2
2
|
|
|
3
|
-
`/init-pipeline` fills the `yaml pipeline-profile` block in `PIPELINE.md` (from
|
|
3
|
+
`/cohorte-init-pipeline` fills the `yaml pipeline-profile` block in `PIPELINE.md` (from
|
|
4
4
|
`PIPELINE.template.md`) plus the prose sections. This documents every field and how the
|
|
5
5
|
generic pipeline uses it, so a stateless agent can read/regenerate the profile correctly.
|
|
6
6
|
|
|
@@ -29,12 +29,12 @@ generic pipeline uses it, so a stateless agent can read/regenerate the profile c
|
|
|
29
29
|
| `surfaces[].*_cmd` | string | implementer | test/lint/format/typecheck/build commands. |
|
|
30
30
|
| `surfaces[].test_quiet_cmd` `.lint_quiet_cmd` | string | implementer, preflight, workflows | Bridled variants agents actually run (dot reporter / `--quiet` / failures-only). `""` ⇒ `<cmd> 2>&1 \| tail -40`. See §Output discipline. |
|
|
31
31
|
| `surfaces[].uses_design` | bool | build, frontend | Whether this surface consumes designs. |
|
|
32
|
-
| `contract.enabled` | bool | build | `false` ⇒ skip contract authoring (§2 of /build). |
|
|
32
|
+
| `contract.enabled` | bool | build | `false` ⇒ skip contract authoring (§2 of /cohorte-build). |
|
|
33
33
|
| `contract.mechanism` | enum | build, lead | `shared-types-zod`/`openapi`/`protobuf`/`json-schema`/`none`. |
|
|
34
34
|
| `contract.path` `.ext` `.index` | string | build | Where `<feature_id>` contract is authored + barrel. |
|
|
35
35
|
| `contract.authored_by` | const `lead` | build | Implementers import it read-only, never edit. |
|
|
36
36
|
| `commands.*` | string | all | Repo-wide install/dev/lint/format/typecheck/test + migrate. |
|
|
37
|
-
| `commands.test_quiet` `.lint_quiet` | string | review, audit, workflows | Repo-wide bridled variants — what the `/review` pre-flight runs. Same fallback as the per-surface ones. |
|
|
37
|
+
| `commands.test_quiet` `.lint_quiet` | string | review, audit, workflows | Repo-wide bridled variants — what the `/cohorte-review` pre-flight runs. Same fallback as the per-surface ones. |
|
|
38
38
|
| `rbac.enabled` | bool | brainstorm, review | Toggle RBAC personas + authz audit. |
|
|
39
39
|
| `rbac.hierarchy` | list | review | Highest→lowest role list. |
|
|
40
40
|
| `design.enabled` | bool | build, frontend, align-ds | `false` ⇒ design steps are no-ops. |
|
|
@@ -60,14 +60,14 @@ generic pipeline uses it, so a stateless agent can read/regenerate the profile c
|
|
|
60
60
|
|
|
61
61
|
- **Conventions** — per-surface rules the implementer follows and review audits.
|
|
62
62
|
- **Testing** — the TDD contract per surface (what a test must cover, DB isolation).
|
|
63
|
-
- **Design brief note** — feeds `/spec` §8 and the Claude Design step.
|
|
64
|
-
- **Personas** — the `/brainstorm` panel; include one per RBAC role when `rbac.enabled`.
|
|
63
|
+
- **Design brief note** — feeds `/cohorte-spec` §8 and the Claude Design step.
|
|
64
|
+
- **Personas** — the `/cohorte-brainstorm` panel; include one per RBAC role when `rbac.enabled`.
|
|
65
65
|
|
|
66
66
|
## How the pieces reference this file
|
|
67
67
|
|
|
68
68
|
- **Agents** (`implementer`, `review`, `release`) are told at dispatch: _read `PIPELINE.md`
|
|
69
69
|
§Commands / §Conventions / §Surfaces first._ They have `Read`, so they load it live.
|
|
70
|
-
- **Commands** (`/build`, `/review`, …) parse the `yaml pipeline-profile` block to know how
|
|
70
|
+
- **Commands** (`/cohorte-build`, `/cohorte-review`, …) parse the `yaml pipeline-profile` block to know how
|
|
71
71
|
many surfaces to dispatch, the contract mechanism, the commands, and the capability flags.
|
|
72
72
|
- **Hook** (`gate.py`) reads `gate.deny`/`gate.ask`/`gate.ask_on_default_branch`/`gate.default_branch`
|
|
73
73
|
from a generated `.claude/gate-config.json`. The last two make git + docker free on feature branches
|
|
@@ -87,7 +87,7 @@ follow is provider-agnostic: _"prefer the retrieval MCP tools over Grep/Glob + w
|
|
|
87
87
|
| `graphify` | persistent tree-sitter knowledge graph over code + docs | as fresh as the last rescan | index step + re-index discipline |
|
|
88
88
|
| `none` | agents fall back to Grep/Glob/Read | — | — |
|
|
89
89
|
|
|
90
|
-
**Wiring (done by `/init-pipeline`, or `/update-pipeline` retroactively):**
|
|
90
|
+
**Wiring (done by `/cohorte-init-pipeline`, or `/cohorte-update-pipeline` retroactively):**
|
|
91
91
|
|
|
92
92
|
- `serena` — requires the `serena` CLI (`uv tool install -p 3.13 serena-agent`). For day-to-day CLI
|
|
93
93
|
use it should also be on PATH (`uv tool update-shell`; uv installs to `~/.local/bin`). Register at
|
|
@@ -113,7 +113,7 @@ follow is provider-agnostic: _"prefer the retrieval MCP tools over Grep/Glob + w
|
|
|
113
113
|
- Rendered agents get the provider's MCP tools appended to their `tools:` list (e.g. `mcp__serena`
|
|
114
114
|
grants the whole server); `none` ⇒ nothing appended.
|
|
115
115
|
|
|
116
|
-
**Serena health check** — run after wiring in `/init-pipeline` AND on every `/update-pipeline`
|
|
116
|
+
**Serena health check** — run after wiring in `/cohorte-init-pipeline` AND on every `/cohorte-update-pipeline`
|
|
117
117
|
reconcile (wiring that worked once can rot: PATH changes, tool uninstalled, entry hand-edited):
|
|
118
118
|
|
|
119
119
|
1. **CLI resolves:** `command -v serena`. Fails but `~/.local/bin/serena` exists ⇒ PATH repair
|
|
@@ -135,7 +135,7 @@ Grep/Read; the health check above is the diagnostic.
|
|
|
135
135
|
|
|
136
136
|
## Specialization — when to split one surface into more agents
|
|
137
137
|
|
|
138
|
-
`/build` dispatches ONE agent per surface, in parallel, so build wall-clock ≈ the **slowest single
|
|
138
|
+
`/cohorte-build` dispatches ONE agent per surface, in parallel, so build wall-clock ≈ the **slowest single
|
|
139
139
|
surface**. More agents only build faster when they let the *slowest* surface's work run concurrently —
|
|
140
140
|
and only if the split is safe. The invariant that keeps parallelism safe is **one owner per tree, and
|
|
141
141
|
the frozen contract as the only cross-surface channel**. So specialization means carving a surface into
|
|
@@ -161,8 +161,8 @@ the frozen contract as the only cross-surface channel**. So specialization means
|
|
|
161
161
|
Coarse first, specialize on evidence: start with one `frontend` / `backend` surface each; split only a
|
|
162
162
|
surface that's proven slow and cleanly separable. The evidence lives in
|
|
163
163
|
the **main checkout's** `.claude/pipeline-metrics.jsonl` (gitignored) — one JSONL line per phase batch
|
|
164
|
-
(`ts`/`feature`/`phase`/`seconds`/`surfaces:{key: result}`), appended by `/build`, `/review`
|
|
165
|
-
and `/fix`.
|
|
164
|
+
(`ts`/`feature`/`phase`/`seconds`/`surfaces:{key: result}`), appended by `/cohorte-build`, `/cohorte-review`
|
|
165
|
+
and `/cohorte-fix`.
|
|
166
166
|
**`surfaces` keys are surface keys, nothing else** — run-level facts go in their own top-level
|
|
167
167
|
fields. Anything put inside `surfaces` is read
|
|
168
168
|
as a surface: the dashboard renders it as a row in the per-surface table and scores a non-`ok`
|
|
@@ -178,8 +178,8 @@ what's SLOW. It deliberately does NOT record tokens: the lead can't reliably rea
|
|
|
178
178
|
to log it. For what's EXPENSIVE, use Claude Code's own accounting:
|
|
179
179
|
|
|
180
180
|
- **`/cost`** (built-in, zero setup) — reports per-**subagent** and per-**slash-command** share of your usage
|
|
181
|
-
over the last 24 h / 7 d (e.g. _"Top subagents: frontend 7 %, backend 4 % · Top skills: /build 1 %,
|
|
182
|
-
/review 1 %"_). That IS the per-phase ledger — approximate (share-of-total, machine-local, not exact
|
|
181
|
+
over the last 24 h / 7 d (e.g. _"Top subagents: frontend 7 %, backend 4 % · Top skills: /cohorte-build 1 %,
|
|
182
|
+
/cohorte-review 1 %"_). That IS the per-phase ledger — approximate (share-of-total, machine-local, not exact
|
|
183
183
|
tokens). Read it to see which surface/command actually dominates the bill before you tune a `model` tier.
|
|
184
184
|
- **OpenTelemetry** (exact numbers + dashboards) — add an `env` block to `~/.claude/settings.json`:
|
|
185
185
|
`{"env":{"CLAUDE_CODE_ENABLE_TELEMETRY":"1","OTEL_METRICS_EXPORTER":"otlp","OTEL_EXPORTER_OTLP_PROTOCOL":"http/protobuf","OTEL_EXPORTER_OTLP_ENDPOINT":"http://localhost:4318"}}`
|
|
@@ -207,35 +207,35 @@ context. The profile therefore stores **two forms of each noisy command**:
|
|
|
207
207
|
(`--reporter=dot`, `--quiet`, `-q`, `--silent`, framework equivalent) so a green run costs lines,
|
|
208
208
|
not pages, and a red run prints only the failures.
|
|
209
209
|
|
|
210
|
-
Rules for every consumer (implementers, preflight, `/audit` gates, workflow agents):
|
|
210
|
+
Rules for every consumer (implementers, preflight, `/cohorte-audit` gates, workflow agents):
|
|
211
211
|
|
|
212
212
|
1. Run the quiet variant when set.
|
|
213
213
|
2. Quiet variant empty/absent (older profile) ⇒ run `<full cmd> 2>&1 | tail -40` — never the bare
|
|
214
214
|
command into your context.
|
|
215
215
|
3. Need the full log? Redirect it to a file and grep it; never print it.
|
|
216
216
|
|
|
217
|
-
`/init-pipeline` **asks** for these variants (detected defaults offered first) instead of silently
|
|
218
|
-
storing a bare `pnpm test` as the thing agents execute; `/update-pipeline` tops up older profiles.
|
|
217
|
+
`/cohorte-init-pipeline` **asks** for these variants (detected defaults offered first) instead of silently
|
|
218
|
+
storing a bare `pnpm test` as the thing agents execute; `/cohorte-update-pipeline` tops up older profiles.
|
|
219
219
|
|
|
220
220
|
## Spec status — the lifecycle state machine (and the loop's resume state)
|
|
221
221
|
|
|
222
222
|
A spec's front-matter `status` is not a label, it is the pipeline's **state**: every command routes on
|
|
223
|
-
it, the dashboard boards on it, the kanban backfill maps it to a column, and `/
|
|
223
|
+
it, the dashboard boards on it, the kanban backfill maps it to a column, and `/cohorte-loop --resume` reads it
|
|
224
224
|
back to continue an interrupted autonomous run. Six states, and exactly one writer each:
|
|
225
225
|
|
|
226
226
|
| status | meaning | written by | who may build it |
|
|
227
227
|
| --- | --- | --- | --- |
|
|
228
|
-
| `draft` | the interview is open, nothing is frozen | `/spec` Mode A | no |
|
|
229
|
-
| `frozen` | the contract is frozen — the handoff to `/build` | `/spec` Mode A freeze | yes |
|
|
230
|
-
| `in-progress` | a `/
|
|
231
|
-
| `in-review` | reviewed / awaiting the next round or `/ship` | `/spec` Mode B, `/fix`, `loop.sh` on a clean exit | yes |
|
|
228
|
+
| `draft` | the interview is open, nothing is frozen | `/cohorte-spec` Mode A | no |
|
|
229
|
+
| `frozen` | the contract is frozen — the handoff to `/cohorte-build` | `/cohorte-spec` Mode A freeze | yes |
|
|
230
|
+
| `in-progress` | a `/cohorte-loop` is driving this spec right now (or died doing it) | `scripts/loop.sh`, before each phase | yes |
|
|
231
|
+
| `in-review` | reviewed / awaiting the next round or `/cohorte-ship` | `/cohorte-spec` Mode B, `/cohorte-fix`, `loop.sh` on a clean exit | yes |
|
|
232
232
|
| `blocked` | a loop gave up here (ceiling, non-convergent, no verdict, not implementable) | `loop.sh` on any non-zero exit | yes, with the reason named |
|
|
233
|
-
| `shipped` | the PR is open; the status flip is part of the release commit | `/ship` | no |
|
|
233
|
+
| `shipped` | the PR is open; the status flip is part of the release commit | `/cohorte-ship` | no |
|
|
234
234
|
|
|
235
235
|
**The resume contract.** Before every phase, `loop.sh` stamps `status: in-progress` plus `loop_pass`
|
|
236
236
|
(the review pass it is on) and `loop_phase` (`build`/`review`/`fix`) into the spec — deterministically,
|
|
237
237
|
with `awk`, spending **no tokens** on state it will need later. On exit it stamps a terminal status:
|
|
238
|
-
`in-review` + `loop_phase: done` when clean, `blocked` otherwise. `/
|
|
238
|
+
`in-review` + `loop_phase: done` when clean, `blocked` otherwise. `/cohorte-loop <id> --resume` then continues
|
|
239
239
|
at the recorded pass instead of pass 1, so a session killed at pass 3 of 5 does not re-pay passes 1–2.
|
|
240
240
|
The build is still skipped or redone by the build stamp alone (`specs/reports/<id>.built`, written only
|
|
241
241
|
after a build that finished), so an interrupted *build* correctly rebuilds.
|
|
@@ -244,10 +244,10 @@ Corollaries worth knowing:
|
|
|
244
244
|
|
|
245
245
|
- A spec with no front-matter makes every stamp a **silent no-op** — the state is bookkeeping, and the
|
|
246
246
|
loop must never die over a status line.
|
|
247
|
-
- Child commands write `status` too (`/fix` sets `in-review`); re-stamping before each phase is what
|
|
247
|
+
- Child commands write `status` too (`/cohorte-fix` sets `in-review`); re-stamping before each phase is what
|
|
248
248
|
keeps `in-progress` true for the duration of the run rather than for its first phase.
|
|
249
|
-
- `blocked` is not a failure to hide: it is the resumable state. `/build` accepts it, names it, and
|
|
250
|
-
routes by the spec's `## Remediation` (open items ⇒ `/fix`).
|
|
249
|
+
- `blocked` is not a failure to hide: it is the resumable state. `/cohorte-build` accepts it, names it, and
|
|
250
|
+
routes by the spec's `## Remediation` (open items ⇒ `/cohorte-fix`).
|
|
251
251
|
|
|
252
252
|
## Dead agents — silence is not a green light
|
|
253
253
|
|
|
@@ -258,9 +258,9 @@ integrates anything, because the default reading of silence is the most dangerou
|
|
|
258
258
|
|
|
259
259
|
| phase | what a dead agent looks like | what the phase must do |
|
|
260
260
|
| --- | --- | --- |
|
|
261
|
-
| `/build` | a surface with no handoff | retry it **once** alone (byte-identical prompt), then mark it `dead`, verify the tree with that surface's own quiet commands, never call the batch ok |
|
|
262
|
-
| `/review` | a reviewer with no report ⇒ **zero findings** | retry once, then list the surface in `unreviewed` and refuse to score `SHIP` |
|
|
263
|
-
| `/fix` | a re-dispatched agent with no handoff | retry once, then leave **every** one of its items `- [ ]` — a dead agent never ticks a box |
|
|
261
|
+
| `/cohorte-build` | a surface with no handoff | retry it **once** alone (byte-identical prompt), then mark it `dead`, verify the tree with that surface's own quiet commands, never call the batch ok |
|
|
262
|
+
| `/cohorte-review` | a reviewer with no report ⇒ **zero findings** | retry once, then list the surface in `unreviewed` and refuse to score `SHIP` |
|
|
263
|
+
| `/cohorte-fix` | a re-dispatched agent with no handoff | retry once, then leave **every** one of its items `- [ ]` — a dead agent never ticks a box |
|
|
264
264
|
| workflows | `agent()` resolves to `null` | already enforced (`review.js` `unreviewedSurfaces`) — the doctrine started here |
|
|
265
265
|
|
|
266
266
|
Non-negotiables, in every phase:
|
|
@@ -269,8 +269,8 @@ Non-negotiables, in every phase:
|
|
|
269
269
|
already on disk — so recovery costs one agent, never a rebuild. Never retry an agent that answered.
|
|
270
270
|
- **Never speak for a dead agent.** You did not see its work: report what the *tree* says (quiet
|
|
271
271
|
commands, redirected to a file, grepped), not what a handoff would have said.
|
|
272
|
-
- **Never let it reach a driver as clean.** `/build` writes `dead[]` into
|
|
273
|
-
`specs/reports/<id>.build.json`, `/review` writes `unreviewed[]` into the verdict; `scripts/loop.sh`
|
|
272
|
+
- **Never let it reach a driver as clean.** `/cohorte-build` writes `dead[]` into
|
|
273
|
+
`specs/reports/<id>.build.json`, `/cohorte-review` writes `unreviewed[]` into the verdict; `scripts/loop.sh`
|
|
274
274
|
aborts on either with **exit 2** *before* it reads `blocking`, since a dead reviewer makes
|
|
275
275
|
`blocking == 0` a statement about code nobody read.
|
|
276
276
|
- **`unreviewed` is separate from `blocking` on purpose.** Faking a count in `blocking` to force a
|
|
@@ -281,7 +281,7 @@ Non-negotiables, in every phase:
|
|
|
281
281
|
|
|
282
282
|
## Readiness — the gate between a frozen spec and N implementers
|
|
283
283
|
|
|
284
|
-
`/build` §1.6 scores the frozen spec on **implementability** before authoring the contract and before
|
|
284
|
+
`/cohorte-build` §1.6 scores the frozen spec on **implementability** before authoring the contract and before
|
|
285
285
|
dispatching anything, and writes `specs/reports/<id>.readiness.json`
|
|
286
286
|
(`verdict`: `READY` · `RESERVATIONS` · `NOT-READY`, plus `gaps[]`). It costs **zero extra agents** — the
|
|
287
287
|
lead already holds the spec, the profile and the reconciled surface list — which is the whole economics
|
|
@@ -290,7 +290,7 @@ of the step: a spec that cannot be built does not get cheaper by being built on
|
|
|
290
290
|
- Five checks: contract completeness · surface coverage · dependencies exist · residual ambiguity ·
|
|
291
291
|
the design gate. Each maps to `NOT-READY` (a surface would have to invent the answer) or
|
|
292
292
|
`RESERVATIONS` (a surface can proceed on a stated assumption).
|
|
293
|
-
- **`NOT-READY` aborts the build with no agent spawned** and sends the human to `/spec`.
|
|
293
|
+
- **`NOT-READY` aborts the build with no agent spawned** and sends the human to `/cohorte-spec`.
|
|
294
294
|
`scripts/loop.sh` reads the same file and exits **4** (`not implementable`) — the one loop outcome
|
|
295
295
|
that more passes cannot fix.
|
|
296
296
|
- **`RESERVATIONS` never blocks.** Each gap is inlined verbatim into the dispatch of the surface it
|
|
@@ -299,7 +299,7 @@ of the step: a spec that cannot be built does not get cheaper by being built on
|
|
|
299
299
|
|
|
300
300
|
## Deferred findings — real, but not this feature's problem
|
|
301
301
|
|
|
302
|
-
`/review` ends on "zero blocking findings", so everything non-blocking used to be discarded with the
|
|
302
|
+
`/cohorte-review` ends on "zero blocking findings", so everything non-blocking used to be discarded with the
|
|
303
303
|
report. A **deferred** finding is one the reviewer judges true and **out of this feature's scope**
|
|
304
304
|
(pre-existing code the staged diff never touched, adjacent debt the spec never claims to fix). The
|
|
305
305
|
review agent returns them in their own `## Deferred` section — never in `findings` — each carrying its
|
|
@@ -310,51 +310,55 @@ own out-of-scope reason.
|
|
|
310
310
|
something that cannot change the outcome.
|
|
311
311
|
- **Not deferrable, ever:** anything the diff touched or introduced, any spec violation, any security
|
|
312
312
|
issue on a path this feature adds, calls or modifies.
|
|
313
|
-
- `/review` §3.5 routes them, **on every verdict**, into `specs/refactor-backlog.md` under the
|
|
313
|
+
- `/cohorte-review` §3.5 routes them, **on every verdict**, into `specs/refactor-backlog.md` under the
|
|
314
314
|
`## <domain>` heading of the owning surface, tagged `deferred:<feature_id>` — the same grouping
|
|
315
|
-
`/audit` writes, so `/refactor <domain>` picks them up with no extra plumbing. Never into the spec's
|
|
316
|
-
`## Remediation`, which is what `/fix` re-dispatches.
|
|
317
|
-
- `/audit` **carries open `deferred:` items over** when it rewrites the backlog; overwriting them away
|
|
315
|
+
`/cohorte-audit` writes, so `/cohorte-refactor <domain>` picks them up with no extra plumbing. Never into the spec's
|
|
316
|
+
`## Remediation`, which is what `/cohorte-fix` re-dispatches.
|
|
317
|
+
- `/cohorte-audit` **carries open `deferred:` items over** when it rewrites the backlog; overwriting them away
|
|
318
318
|
is the one way they silently vanish.
|
|
319
|
-
- The verdict JSON carries `deferred: <n>` (informational, outside `blocking`), so `/
|
|
319
|
+
- The verdict JSON carries `deferred: <n>` (informational, outside `blocking`), so `/cohorte-loop` can name
|
|
320
320
|
them in its closing line without reading a report.
|
|
321
321
|
|
|
322
322
|
## Decisions — the transverse decision journal
|
|
323
323
|
|
|
324
324
|
`PIPELINE.md` is a **stack profile** (surfaces, commands, conventions); it says nothing about what this
|
|
325
|
-
project has *decided*. Without somewhere for those, every `/spec` re-discovers or contradicts them.
|
|
325
|
+
project has *decided*. Without somewhere for those, every `/cohorte-spec` re-discovers or contradicts them.
|
|
326
326
|
`specs/_decisions.md` (from `core/templates/decisions.template.md`) is that place, deliberately small:
|
|
327
327
|
|
|
328
328
|
- **Append-only, one line per decision, ≤ ~160 chars:**
|
|
329
329
|
`- <YYYY-MM-DD> · <area> · <decision> — because <reason> · <feature_id>`. Reversal never edits a line:
|
|
330
330
|
append a superseding one (`· supersedes <date> <area>`) and move the old one to `## Superseded`. When
|
|
331
331
|
`## Live` passes ~100 lines, sweep the superseded ones down.
|
|
332
|
-
- **Written by** `/spec` at freeze (the decisions that outlive the feature — typically 0–3 lines, and
|
|
333
|
-
zero is a normal outcome) and `/build` §1.5 when it adds or splits a surface.
|
|
334
|
-
- **Read by the deciding stages only** — `/brainstorm` (so the panel argues about the idea, not about
|
|
335
|
-
settled ground), `/spec` (so a new spec does not silently un-decide something), `/audit` (standing
|
|
332
|
+
- **Written by** `/cohorte-spec` at freeze (the decisions that outlive the feature — typically 0–3 lines, and
|
|
333
|
+
zero is a normal outcome) and `/cohorte-build` §1.5 when it adds or splits a surface.
|
|
334
|
+
- **Read by the deciding stages only** — `/cohorte-brainstorm` (so the panel argues about the idea, not about
|
|
335
|
+
settled ground), `/cohorte-spec` (so a new spec does not silently un-decide something), `/cohorte-audit` (standing
|
|
336
336
|
decisions are part of the rulebook it audits against).
|
|
337
337
|
- **Never read by implementers or reviewers.** They work from the frozen contract, which already tells
|
|
338
338
|
them what to do; shipping them the rationale would cost `surfaces × dispatches` tokens per feature
|
|
339
339
|
for a fact they cannot act on. This is what keeps the journal cheap enough to be worth having.
|
|
340
|
-
- The `_` prefix is load-bearing: `/doctor`, the dashboard spec scanner and the kanban backfill all skip
|
|
340
|
+
- The `_` prefix is load-bearing: `/cohorte-doctor`, the dashboard spec scanner and the kanban backfill all skip
|
|
341
341
|
`specs/_*.md`, so the journal is never mistaken for a spec (no phantom card, no bogus stage).
|
|
342
342
|
|
|
343
343
|
## Preflight — the deterministic phase gate
|
|
344
344
|
|
|
345
|
-
`/review` starts by running `pipeline/scripts/preflight.sh` — a plain shell script (no
|
|
345
|
+
`/cohorte-review` starts by running `pipeline/scripts/preflight.sh` — a plain shell script (no
|
|
346
346
|
agent) that executes the profile's mechanical checks in order (typecheck → lint → tests, quiet
|
|
347
347
|
variants) with all output redirected to `specs/reports/<id>.preflight.txt`:
|
|
348
348
|
|
|
349
349
|
- **Any check red** ⇒ the script prints the last 40 lines raw and exits 1. The command **aborts
|
|
350
350
|
there: zero agents are spawned.** A reviewer dispatched onto code that doesn't compile burns its
|
|
351
351
|
whole run rediscovering what `tsc` already printed for free — the failure goes straight to the
|
|
352
|
-
human (or `/fix`) instead.
|
|
353
|
-
- **All green** ⇒ the script stamps `.claude/preflight.ok` (`<epoch> <HEAD sha>`
|
|
352
|
+
human (or `/cohorte-fix`) instead.
|
|
353
|
+
- **All green** ⇒ the script stamps `.claude/preflight.ok` (`<epoch> <HEAD sha> <tree digest>` —
|
|
354
|
+
local and **gitignored**; a versioned stamp describes the tree *before* its own commit and rides
|
|
355
|
+
into every clone and worktree, which breaks the gate both ways).
|
|
354
356
|
|
|
355
357
|
`hooks/gate.py` enforces the stamp as a **phase gate** (the `preflight` block of `gate-config.json`,
|
|
356
358
|
generated from `gate.preflight`): a Task dispatch of a listed `subagent_type` (default
|
|
357
|
-
`review`) with a missing/stale stamp — older than `max_age_minutes`, or
|
|
359
|
+
`review`) with a missing/stale stamp — older than `max_age_minutes`, or the digest no longer
|
|
360
|
+
matches the working tree (`.claude` and `specs` excluded, so the pipeline's own writes and a
|
|
361
|
+
commit of already-verified code do not invalidate it) — gets an
|
|
358
362
|
"ask", so a lead can't accidentally skip the gate but a human can consciously override it. The gate
|
|
359
363
|
hook fires for **every** agent in the session, including subagents spawned by the Workflow runtime
|
|
360
364
|
(they run in `acceptEdits` whatever the session mode — Write/Edit auto-approved — but Bash and Task
|
|
@@ -363,7 +367,7 @@ hard deny, because nobody is there to answer a prompt.
|
|
|
363
367
|
|
|
364
368
|
## Rendering / reconciling a surface agent (shared procedure)
|
|
365
369
|
|
|
366
|
-
Both `/init-pipeline` (initial render) and `/build` (auto-reconcile when a spec needs a new agent) use
|
|
370
|
+
Both `/cohorte-init-pipeline` (initial render) and `/cohorte-build` (auto-reconcile when a spec needs a new agent) use
|
|
367
371
|
this exact procedure so a surface is always defined the same way. To add surface `S`:
|
|
368
372
|
|
|
369
373
|
1. **Add the `surfaces[]` entry** to `PIPELINE.md`: `key`, `path` (the disjoint tree it exclusively
|
|
@@ -382,7 +386,7 @@ this exact procedure so a surface is always defined the same way. To add surface
|
|
|
382
386
|
**baked at render time**: `PIPELINE.md` §Conventions `### Shared` + this surface's
|
|
383
387
|
`### Surface: <key>` stanza + its §Testing lines, verbatim. At runtime the agent then reads only
|
|
384
388
|
the profile's machine block (the fenced `yaml pipeline-profile`) — never the prose sections. The
|
|
385
|
-
bake stays honest because §Conventions edits go through `/update-pipeline`, whose reconcile
|
|
389
|
+
bake stays honest because §Conventions edits go through `/cohorte-update-pipeline`, whose reconcile
|
|
386
390
|
re-renders every agent (step 2 below); hand-edit the prose without re-rendering and the baked
|
|
387
391
|
slice goes stale — that's the trade for not re-reading the prose on every dispatch. For a `uses_design` surface, fill them **link-based** (never with a
|
|
388
392
|
stored `design_project` id — that goes stale on a DS rebuild):
|
|
@@ -410,7 +414,7 @@ conventions. Never leave an agent file with no matching `surfaces[]` entry (orph
|
|
|
410
414
|
|
|
411
415
|
## Reconcile — bringing generated files up to the current core
|
|
412
416
|
|
|
413
|
-
`/init-pipeline` is **one-time per project**. Afterwards, `/update-pipeline` runs this procedure so a
|
|
417
|
+
`/cohorte-init-pipeline` is **one-time per project**. Afterwards, `/cohorte-update-pipeline` runs this procedure so a
|
|
414
418
|
core upgrade never requires re-running init — new pipeline features flow into the repo's generated
|
|
415
419
|
files automatically. It works because every generated artifact is a **deterministic function of
|
|
416
420
|
(current template × the profile's data)**; nothing needs re-detecting or re-interviewing.
|
|
@@ -428,7 +432,7 @@ files automatically. It works because every generated artifact is a **determinis
|
|
|
428
432
|
init spec (missing `allow` entries, hooks per install mode) — add what's missing, never remove or
|
|
429
433
|
rewrite existing/custom keys.
|
|
430
434
|
4. **Capability wiring.** If a top-up added a capability needing external setup (e.g. a `retrieval`
|
|
431
|
-
provider whose MCP server isn't registered yet), run its wiring step from `/init-pipeline` Phase 4.
|
|
435
|
+
provider whose MCP server isn't registered yet), run its wiring step from `/cohorte-init-pipeline` Phase 4.
|
|
432
436
|
Even when nothing new was added, re-run the provider's health check (§Code retrieval) — wiring
|
|
433
437
|
rots (PATH changes, uninstalls, hand-edits) — and repair whatever fails.
|
|
434
438
|
5. **Global config seed.** If `~/.claude/cohorte.config.yaml` is absent, seed it from the template
|
|
@@ -446,20 +450,28 @@ files automatically. It works because every generated artifact is a **determinis
|
|
|
446
450
|
demand when a driver needs them); it just keeps a new spec's front-matter honest about the states
|
|
447
451
|
the pipeline can put it in.
|
|
448
452
|
|
|
449
|
-
|
|
450
|
-
|
|
453
|
+
8. **Local-artifact hygiene.** The pipeline's own runtime files must stay out of git:
|
|
454
|
+
`.claude/preflight.ok`, `.claude/pipeline-metrics.jsonl`, `specs/reports/`. Add any missing entry to
|
|
455
|
+
`.gitignore`, and **untrack** what a pre-2.0.0 install let slip in —
|
|
456
|
+
`git rm --cached --ignore-unmatch .claude/preflight.ok` (repeat per stray path). The stamp is the
|
|
457
|
+
one that actively breaks: it records the tree it verified, the commit carrying it moves HEAD past
|
|
458
|
+
that tree, and the committed copy lands in every clone and worktree — so the phase gate ends up
|
|
459
|
+
blocking clean trees and greening unchecked ones. Report what was untracked; the human commits it.
|
|
460
|
+
|
|
461
|
+
Re-running `/cohorte-init-pipeline` remains possible (it reconciles too) but is only *needed* when the stack
|
|
462
|
+
itself changes in ways `/cohorte-build` §1.5 can't auto-grow (e.g. package manager or contract mechanism swap).
|
|
451
463
|
|
|
452
464
|
## Workflows — deterministic multi-agent runs (opt-in)
|
|
453
465
|
|
|
454
466
|
Three phases have a **workflow variant** — a deterministic orchestration script the Claude Code
|
|
455
467
|
Workflow runtime executes instead of the lead reasoning out the fan-out turn by turn:
|
|
456
468
|
`<core>/workflows/review.js`, `audit.js`, `refactor.js` (installed to `.claude/workflows/` bundled or
|
|
457
|
-
`~/.claude/workflows/` global). The conversational commands (`/review`, `/audit`, `/refactor`)
|
|
469
|
+
`~/.claude/workflows/` global). The conversational commands (`/cohorte-review`, `/cohorte-audit`, `/cohorte-refactor`)
|
|
458
470
|
**remain the default path and the fallback** — a workflow runs only when the human explicitly asks
|
|
459
471
|
for it ("run the review workflow"), and requires Claude Code ≥ **2.1.154** with workflows
|
|
460
472
|
enabled.
|
|
461
|
-
`/doctor` reports which path a session will take. The interactive commands (`/init-pipeline`,
|
|
462
|
-
`/brainstorm`, `/spec`) and the dispatch-only ones (`/build`, `/ship`) have **no** workflow variant on
|
|
473
|
+
`/cohorte-doctor` reports which path a session will take. The interactive commands (`/cohorte-init-pipeline`,
|
|
474
|
+
`/cohorte-brainstorm`, `/cohorte-spec`) and the dispatch-only ones (`/cohorte-build`, `/cohorte-ship`) have **no** workflow variant on
|
|
463
475
|
purpose: they're interviews or already a single parallel dispatch — a script adds nothing.
|
|
464
476
|
|
|
465
477
|
Shared design, all four scripts:
|
|
@@ -488,13 +500,13 @@ Shared design, all four scripts:
|
|
|
488
500
|
- **`audit.js`** — one auditor per domain (each surface + `shared`), concurrency capped by the
|
|
489
501
|
runtime (~16), merged into the prioritized `specs/refactor-backlog.md`.
|
|
490
502
|
- **`refactor.js`** — big domains only (it skips domains with a handful of open items — the
|
|
491
|
-
conversational `/refactor` is cheaper there): `shared` first and alone, then the other domains'
|
|
503
|
+
conversational `/cohorte-refactor` is cheaper there): `shared` first and alone, then the other domains'
|
|
492
504
|
implementers in parallel, each verified per-domain.
|
|
493
505
|
- **No input mid-run.** A workflow runs to completion without questions; anything interactive
|
|
494
506
|
(contract changes, human decisions) belongs to the conversational path. The gate hook still
|
|
495
507
|
fires on workflow subagents (see
|
|
496
508
|
§Preflight) — in unattended runs its asks become denies.
|
|
497
|
-
- **Permissions:** `/init-pipeline` and `/update-pipeline` extend the generated `settings.json`
|
|
509
|
+
- **Permissions:** `/cohorte-init-pipeline` and `/cohorte-update-pipeline` extend the generated `settings.json`
|
|
498
510
|
`allow` list with what workflow agents need (the quiet commands, the shipped
|
|
499
511
|
`pipeline/scripts/*.sh`, read-only git incl. `git rev-parse`, and the retrieval provider's MCP
|
|
500
512
|
tools) so a run never stalls mid-workflow on a permission prompt nobody is watching.
|
|
@@ -517,11 +529,11 @@ present else `kanban.columns`. Not found ⇒ kanban off for this project.
|
|
|
517
529
|
**Card format.** A card is a Kanban list item under a `## <column>` heading:
|
|
518
530
|
`- [ ] <human title> #<feature_id>`. The `#<feature_id>` tag is the join key between a card and its
|
|
519
531
|
`specs/<feature_id>.md`; it is how every stage finds *its* card (Grep the board for `#<id>`). Free-text
|
|
520
|
-
notes a human writes as sub-bullets under an Ideas card are seed context for `/brainstorm`. Never touch
|
|
532
|
+
notes a human writes as sub-bullets under an Ideas card are seed context for `/cohorte-brainstorm`. Never touch
|
|
521
533
|
the trailing `%% kanban:settings … %%` block or the `kanban-plugin: board` front-matter.
|
|
522
534
|
|
|
523
|
-
Once shipped, `/ship` appends the **PR number** to the card — `- [ ] <title> #<feature_id> — PR #<num>`.
|
|
524
|
-
The bare `#<num>` is what the dashboard renders as a clickable link to the GitHub PR, so `/ship` always
|
|
535
|
+
Once shipped, `/cohorte-ship` appends the **PR number** to the card — `- [ ] <title> #<feature_id> — PR #<num>`.
|
|
536
|
+
The bare `#<num>` is what the dashboard renders as a clickable link to the GitHub PR, so `/cohorte-ship` always
|
|
525
537
|
writes it when a PR was actually created.
|
|
526
538
|
|
|
527
539
|
**Move a card (the core op).** Use the shipped script — it does the whole op outside the agent's
|
|
@@ -540,15 +552,15 @@ card created in the target column if missing.
|
|
|
540
552
|
| Pipeline moment | Column |
|
|
541
553
|
| --------------------------------------- | --------------- |
|
|
542
554
|
| human drops a raw idea (manual) | `ideas` |
|
|
543
|
-
| `/brainstorm` picks it up | `brainstorm` |
|
|
544
|
-
| `/spec` opens (draft) | `spec` |
|
|
545
|
-
| `/spec` freezes (`status: frozen`) | `ready` |
|
|
546
|
-
| `/build` | `building` |
|
|
547
|
-
| `/review` | `review` |
|
|
548
|
-
| `/fix` | `fix` |
|
|
549
|
-
| a `/
|
|
550
|
-
| a `/
|
|
551
|
-
| `/ship` starts | `ship` |
|
|
555
|
+
| `/cohorte-brainstorm` picks it up | `brainstorm` |
|
|
556
|
+
| `/cohorte-spec` opens (draft) | `spec` |
|
|
557
|
+
| `/cohorte-spec` freezes (`status: frozen`) | `ready` |
|
|
558
|
+
| `/cohorte-build` | `building` |
|
|
559
|
+
| `/cohorte-review` | `review` |
|
|
560
|
+
| `/cohorte-fix` | `fix` |
|
|
561
|
+
| a `/cohorte-loop` is driving it (`in-progress`) | the current phase's column |
|
|
562
|
+
| a `/cohorte-loop` gave up (`blocked`) | `fix` |
|
|
563
|
+
| `/cohorte-ship` starts | `ship` |
|
|
552
564
|
| PR opened (`status: shipped`) | `shipped` (+ `PR #<num>` on the card) |
|
|
553
565
|
|
|
554
566
|
**Backfill / sync from specs (reconcile).** `specs/*.md` is the source of truth. For each spec, read its
|
|
@@ -568,12 +580,12 @@ per configured column in pipeline order, and the closing `%% kanban:settings %%`
|
|
|
568
580
|
## Telemetry — anonymous usage stats, strictly opt-in (GDPR-first)
|
|
569
581
|
|
|
570
582
|
Cohorte can send the maintainers anonymous usage pings so the pipeline improves where it's actually
|
|
571
|
-
slow. **Nothing is ever sent without explicit consent**: `/init-pipeline` (and `/update-pipeline` on
|
|
583
|
+
slow. **Nothing is ever sent without explicit consent**: `/cohorte-init-pipeline` (and `/cohorte-update-pipeline` on
|
|
572
584
|
pre-telemetry installs) ask ONE question, once per machine, default **No**, and record the answer in
|
|
573
585
|
`~/.claude/cohorte.config.yaml` §`telemetry` (`enabled`, `install_id`, `consent_date`). The sender —
|
|
574
586
|
`pipeline/scripts/telemetry-send.sh` — is a silent no-op unless `enabled: true` AND `install_id` AND
|
|
575
587
|
`endpoint` are all set, times out at 2s, and never fails the pipeline. Callers chain it with
|
|
576
|
-
`|| true`, so a **missing** script is equally silent: `/doctor` check 1 verifies `pipeline/scripts/`
|
|
588
|
+
`|| true`, so a **missing** script is equally silent: `/cohorte-doctor` check 1 verifies `pipeline/scripts/`
|
|
577
589
|
is fully populated.
|
|
578
590
|
|
|
579
591
|
**Which commands ping** — the six that make up the feature funnel, and only those. The point is to
|
|
@@ -593,8 +605,8 @@ see where features stall, so every stage of `idea → PR` reports and nothing el
|
|
|
593
605
|
> forms are valid — but read the `fix` column knowing which path produced it.
|
|
594
606
|
|
|
595
607
|
`seconds: 0` marks a phase whose duration is human thinking time, not pipeline wall-clock — the
|
|
596
|
-
funnel signal there is the event, not how long it took. `/doctor`, `/audit`, `/refactor`,
|
|
597
|
-
`/align-ds`, `/init-pipeline` and `/update-pipeline` **never** ping: they sit outside the funnel, and
|
|
608
|
+
funnel signal there is the event, not how long it took. `/cohorte-doctor`, `/cohorte-audit`, `/cohorte-refactor`,
|
|
609
|
+
`/cohorte-align-ds`, `/cohorte-init-pipeline` and `/cohorte-update-pipeline` **never** ping: they sit outside the funnel, and
|
|
598
610
|
keeping them out is what holds the collected set to what the consent text describes.
|
|
599
611
|
|
|
600
612
|
**What one event contains** (strict allowlist, ~200 bytes):
|
|
@@ -614,7 +626,7 @@ work without revealing what is being built.
|
|
|
614
626
|
- **Consent** — opt-in only, recorded with a date; "No" is also recorded so nothing re-asks.
|
|
615
627
|
- **Withdrawal** — set `telemetry.enabled: false` in `~/.claude/cohorte.config.yaml`; effective on
|
|
616
628
|
the next phase, no restart.
|
|
617
|
-
- **Erasure** — `/doctor` prints your `install_id`; send
|
|
629
|
+
- **Erasure** — `/cohorte-doctor` prints your `install_id`; send
|
|
618
630
|
`curl -X DELETE <endpoint-origin>/v1/install/<install_id>` and the collector drops every event
|
|
619
631
|
for that id (the deployed collector implements this and stores no IPs).
|
|
620
632
|
- **Access/portability** — events are keyed by your `install_id`; ask the operator for an export.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# pipeline capabilities. One machine, every project. NOT tied to any project's PIPELINE.md.
|
|
3
3
|
#
|
|
4
4
|
# Seeded once by the installer (npx cohorte install) and never clobbered on update. Wired
|
|
5
|
-
# interactively by /init-pipeline (new project) and /update-pipeline (existing project) —
|
|
5
|
+
# interactively by /cohorte-init-pipeline (new project) and /cohorte-update-pipeline (existing project) —
|
|
6
6
|
# you should never need to hand-edit it.
|
|
7
7
|
#
|
|
8
8
|
# The `# cfg:<key>` markers below are anchors the installer's interactive prompts write to;
|
|
@@ -12,12 +12,12 @@ enabled: true # cfg:enabled — master switch; false disables ev
|
|
|
12
12
|
|
|
13
13
|
# ── telemetry (anonymous usage stats — OPT-IN, GDPR-first) ──────────────────
|
|
14
14
|
# Strictly opt-in: nothing is ever sent unless YOU said yes to the consent question
|
|
15
|
-
# (/init-pipeline or /update-pipeline ask once per machine; they record your answer here).
|
|
15
|
+
# (/cohorte-init-pipeline or /cohorte-update-pipeline ask once per machine; they record your answer here).
|
|
16
16
|
# What is sent when enabled: core version, OS, phase name, wall-clock seconds, per-surface
|
|
17
17
|
# result counts, and a SHA-256 HASH of the feature id — never repo names, paths, code, spec
|
|
18
|
-
# content, emails, or IPs. One ping per pipeline phase, /brainstorm through /ship; setup and
|
|
19
|
-
# maintenance commands (/doctor, /init-pipeline, /update-pipeline, /audit, /refactor,
|
|
20
|
-
# /align-ds) never ping. Sent fire-and-forget (2s timeout, silent on failure) by
|
|
18
|
+
# content, emails, or IPs. One ping per pipeline phase, /cohorte-brainstorm through /cohorte-ship; setup and
|
|
19
|
+
# maintenance commands (/cohorte-doctor, /cohorte-init-pipeline, /cohorte-update-pipeline, /cohorte-audit, /cohorte-refactor,
|
|
20
|
+
# /cohorte-align-ds) never ping. Sent fire-and-forget (2s timeout, silent on failure) by
|
|
21
21
|
# pipeline/scripts/telemetry-send.sh. Withdraw anytime: set enabled: false. Erase your history:
|
|
22
22
|
# see SCHEMA.md §Telemetry (DELETE by install_id).
|
|
23
23
|
telemetry:
|
|
@@ -33,9 +33,9 @@ obsidian:
|
|
|
33
33
|
vault_path: "" # cfg:vault_path
|
|
34
34
|
|
|
35
35
|
# ── kanban (dev pipeline mirror) ─────────────────────────────────────────────
|
|
36
|
-
# Mirrors /brainstorm…/ship onto an Obsidian Kanban board — one board per project. The
|
|
36
|
+
# Mirrors /cohorte-brainstorm…/cohorte-ship onto an Obsidian Kanban board — one board per project. The
|
|
37
37
|
# board path points at your PERSONAL vault, so it is machine-specific and lives here (never
|
|
38
|
-
# committed in a repo's PIPELINE.md). /init-pipeline + /update-pipeline write `boards` for you.
|
|
38
|
+
# committed in a repo's PIPELINE.md). /cohorte-init-pipeline + /cohorte-update-pipeline write `boards` for you.
|
|
39
39
|
# See SCHEMA.md §Kanban.
|
|
40
40
|
kanban:
|
|
41
41
|
enabled: false # cfg:kanban_enabled — master switch for the kanban mirror
|
|
@@ -52,7 +52,7 @@ kanban:
|
|
|
52
52
|
ship: "Ship"
|
|
53
53
|
shipped: "Shipped"
|
|
54
54
|
# One entry per project, keyed by the project's PIPELINE.md `name` (e.g. SAMO). `board` is a
|
|
55
|
-
# path RELATIVE to obsidian.vault_path. Written by /init-pipeline + /update-pipeline.
|
|
55
|
+
# path RELATIVE to obsidian.vault_path. Written by /cohorte-init-pipeline + /cohorte-update-pipeline.
|
|
56
56
|
boards: {}
|
|
57
57
|
# SAMO:
|
|
58
58
|
# board: "Samo/Tasks.md"
|