cohorte 1.5.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 +169 -3
- package/README.md +65 -57
- package/bin/cli.js +31 -15
- package/core/agents/implementer.template.md +3 -3
- package/core/agents/release.md +1 -1
- package/core/agents/review.md +25 -2
- package/core/commands/{audit.md → cohorte-audit.md} +11 -3
- package/core/commands/{brainstorm.md → cohorte-brainstorm.md} +9 -3
- package/core/commands/{build.md → cohorte-build.md} +95 -10
- package/core/commands/{doctor.md → cohorte-doctor.md} +22 -9
- package/core/commands/{fix.md → cohorte-fix.md} +20 -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} +70 -20
- package/core/commands/{ship.md → cohorte-ship.md} +5 -5
- package/core/commands/{spec.md → cohorte-spec.md} +32 -12
- package/core/commands/{update-pipeline.md → cohorte-update-pipeline.md} +16 -6
- package/core/hooks/gate.py +101 -6
- package/core/templates/brainstorm-return.md +4 -4
- package/core/templates/decisions.template.md +42 -0
- package/core/templates/design-brief.md +1 -1
- package/core/templates/spec.template.md +8 -6
- 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 +62 -20
- package/dashboard/README.md +2 -2
- package/dashboard/dist/assets/{index-dkO8UUVl.css → index-BZ_LQlEj.css} +1 -1
- package/dashboard/dist/assets/{index-8owBnqyv.js → index-P1I1JGtj.js} +11 -11
- package/dashboard/dist/index.html +2 -2
- package/dashboard/server/doctor.js +75 -18
- package/dashboard/server/index.js +5 -5
- package/dashboard/server/metrics.js +1 -1
- package/install.ps1 +31 -14
- package/install.sh +31 -14
- package/package.json +2 -2
- package/profile/PIPELINE.template.md +17 -16
- package/profile/SCHEMA.md +199 -48
- package/profile/cohorte.config.template.yaml +8 -8
- package/scripts/loop-detach.sh +153 -0
- package/scripts/loop.sh +202 -25
- 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 +269 -0
- package/scripts/test-metrics.mjs +23 -11
- package/scripts/test-workflows.mjs +33 -5
- package/scripts/validate-core.mjs +46 -9
- package/core/commands/loop.md +0 -61
- /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,31 +207,158 @@ 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
|
+
|
|
220
|
+
## Spec status — the lifecycle state machine (and the loop's resume state)
|
|
221
|
+
|
|
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 `/cohorte-loop --resume` reads it
|
|
224
|
+
back to continue an interrupted autonomous run. Six states, and exactly one writer each:
|
|
225
|
+
|
|
226
|
+
| status | meaning | written by | who may build it |
|
|
227
|
+
| --- | --- | --- | --- |
|
|
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
|
+
| `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 | `/cohorte-ship` | no |
|
|
234
|
+
|
|
235
|
+
**The resume contract.** Before every phase, `loop.sh` stamps `status: in-progress` plus `loop_pass`
|
|
236
|
+
(the review pass it is on) and `loop_phase` (`build`/`review`/`fix`) into the spec — deterministically,
|
|
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. `/cohorte-loop <id> --resume` then continues
|
|
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
|
+
The build is still skipped or redone by the build stamp alone (`specs/reports/<id>.built`, written only
|
|
241
|
+
after a build that finished), so an interrupted *build* correctly rebuilds.
|
|
242
|
+
|
|
243
|
+
Corollaries worth knowing:
|
|
244
|
+
|
|
245
|
+
- A spec with no front-matter makes every stamp a **silent no-op** — the state is bookkeeping, and the
|
|
246
|
+
loop must never die over a status line.
|
|
247
|
+
- Child commands write `status` too (`/cohorte-fix` sets `in-review`); re-stamping before each phase is what
|
|
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. `/cohorte-build` accepts it, names it, and
|
|
250
|
+
routes by the spec's `## Remediation` (open items ⇒ `/cohorte-fix`).
|
|
251
|
+
|
|
252
|
+
## Dead agents — silence is not a green light
|
|
253
|
+
|
|
254
|
+
A subagent can die mid-run: a rate limit, a transport error that outlived its retries, its own context
|
|
255
|
+
exhausted on a big surface. When it does it returns **nothing** — and nothing is byte-identical to
|
|
256
|
+
"finished, nothing to report". Every phase that fans out therefore does a **roll call** before it
|
|
257
|
+
integrates anything, because the default reading of silence is the most dangerous one available:
|
|
258
|
+
|
|
259
|
+
| phase | what a dead agent looks like | what the phase must do |
|
|
260
|
+
| --- | --- | --- |
|
|
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
|
+
| workflows | `agent()` resolves to `null` | already enforced (`review.js` `unreviewedSurfaces`) — the doctrine started here |
|
|
265
|
+
|
|
266
|
+
Non-negotiables, in every phase:
|
|
267
|
+
|
|
268
|
+
- **Retry once, alone, byte-identical.** Most deaths are transient, and the other surfaces' work is
|
|
269
|
+
already on disk — so recovery costs one agent, never a rebuild. Never retry an agent that answered.
|
|
270
|
+
- **Never speak for a dead agent.** You did not see its work: report what the *tree* says (quiet
|
|
271
|
+
commands, redirected to a file, grepped), not what a handoff would have said.
|
|
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
|
+
aborts on either with **exit 2** *before* it reads `blocking`, since a dead reviewer makes
|
|
275
|
+
`blocking == 0` a statement about code nobody read.
|
|
276
|
+
- **`unreviewed` is separate from `blocking` on purpose.** Faking a count in `blocking` to force a
|
|
277
|
+
driver's hand would corrupt the one field the whole contract rests on; a driver reads them as two
|
|
278
|
+
different facts — "what was found" and "what was covered".
|
|
279
|
+
- **Write the metrics line anyway** (`"<key>":"dead"`). An incomplete batch is exactly the batch worth
|
|
280
|
+
recording; holding the append back "until it's complete" deletes the evidence that anything failed.
|
|
281
|
+
|
|
282
|
+
## Readiness — the gate between a frozen spec and N implementers
|
|
283
|
+
|
|
284
|
+
`/cohorte-build` §1.6 scores the frozen spec on **implementability** before authoring the contract and before
|
|
285
|
+
dispatching anything, and writes `specs/reports/<id>.readiness.json`
|
|
286
|
+
(`verdict`: `READY` · `RESERVATIONS` · `NOT-READY`, plus `gaps[]`). It costs **zero extra agents** — the
|
|
287
|
+
lead already holds the spec, the profile and the reconciled surface list — which is the whole economics
|
|
288
|
+
of the step: a spec that cannot be built does not get cheaper by being built on N surfaces in parallel.
|
|
289
|
+
|
|
290
|
+
- Five checks: contract completeness · surface coverage · dependencies exist · residual ambiguity ·
|
|
291
|
+
the design gate. Each maps to `NOT-READY` (a surface would have to invent the answer) or
|
|
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 `/cohorte-spec`.
|
|
294
|
+
`scripts/loop.sh` reads the same file and exits **4** (`not implementable`) — the one loop outcome
|
|
295
|
+
that more passes cannot fix.
|
|
296
|
+
- **`RESERVATIONS` never blocks.** Each gap is inlined verbatim into the dispatch of the surface it
|
|
297
|
+
affects, as an assumption the implementer must apply *and* flag in its handoff. A gate that stalled a
|
|
298
|
+
sound build on a missing error case would cost more human round-trips than it saves.
|
|
299
|
+
|
|
300
|
+
## Deferred findings — real, but not this feature's problem
|
|
301
|
+
|
|
302
|
+
`/cohorte-review` ends on "zero blocking findings", so everything non-blocking used to be discarded with the
|
|
303
|
+
report. A **deferred** finding is one the reviewer judges true and **out of this feature's scope**
|
|
304
|
+
(pre-existing code the staged diff never touched, adjacent debt the spec never claims to fix). The
|
|
305
|
+
review agent returns them in their own `## Deferred` section — never in `findings` — each carrying its
|
|
306
|
+
own out-of-scope reason.
|
|
307
|
+
|
|
308
|
+
- They count in **no** severity row, enter **no** verdict, and are **never** cross-checked: a deferred
|
|
309
|
+
item cannot cost a fix loop an iteration, and refuting one would spend an agent arguing about
|
|
310
|
+
something that cannot change the outcome.
|
|
311
|
+
- **Not deferrable, ever:** anything the diff touched or introduced, any spec violation, any security
|
|
312
|
+
issue on a path this feature adds, calls or modifies.
|
|
313
|
+
- `/cohorte-review` §3.5 routes them, **on every verdict**, into `specs/refactor-backlog.md` under the
|
|
314
|
+
`## <domain>` heading of the owning surface, tagged `deferred:<feature_id>` — the same grouping
|
|
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
|
+
is the one way they silently vanish.
|
|
319
|
+
- The verdict JSON carries `deferred: <n>` (informational, outside `blocking`), so `/cohorte-loop` can name
|
|
320
|
+
them in its closing line without reading a report.
|
|
321
|
+
|
|
322
|
+
## Decisions — the transverse decision journal
|
|
323
|
+
|
|
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 `/cohorte-spec` re-discovers or contradicts them.
|
|
326
|
+
`specs/_decisions.md` (from `core/templates/decisions.template.md`) is that place, deliberately small:
|
|
327
|
+
|
|
328
|
+
- **Append-only, one line per decision, ≤ ~160 chars:**
|
|
329
|
+
`- <YYYY-MM-DD> · <area> · <decision> — because <reason> · <feature_id>`. Reversal never edits a line:
|
|
330
|
+
append a superseding one (`· supersedes <date> <area>`) and move the old one to `## Superseded`. When
|
|
331
|
+
`## Live` passes ~100 lines, sweep the superseded ones down.
|
|
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
|
+
decisions are part of the rulebook it audits against).
|
|
337
|
+
- **Never read by implementers or reviewers.** They work from the frozen contract, which already tells
|
|
338
|
+
them what to do; shipping them the rationale would cost `surfaces × dispatches` tokens per feature
|
|
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: `/cohorte-doctor`, the dashboard spec scanner and the kanban backfill all skip
|
|
341
|
+
`specs/_*.md`, so the journal is never mistaken for a spec (no phantom card, no bogus stage).
|
|
219
342
|
|
|
220
343
|
## Preflight — the deterministic phase gate
|
|
221
344
|
|
|
222
|
-
`/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
|
|
223
346
|
agent) that executes the profile's mechanical checks in order (typecheck → lint → tests, quiet
|
|
224
347
|
variants) with all output redirected to `specs/reports/<id>.preflight.txt`:
|
|
225
348
|
|
|
226
349
|
- **Any check red** ⇒ the script prints the last 40 lines raw and exits 1. The command **aborts
|
|
227
350
|
there: zero agents are spawned.** A reviewer dispatched onto code that doesn't compile burns its
|
|
228
351
|
whole run rediscovering what `tsc` already printed for free — the failure goes straight to the
|
|
229
|
-
human (or `/fix`) instead.
|
|
230
|
-
- **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).
|
|
231
356
|
|
|
232
357
|
`hooks/gate.py` enforces the stamp as a **phase gate** (the `preflight` block of `gate-config.json`,
|
|
233
358
|
generated from `gate.preflight`): a Task dispatch of a listed `subagent_type` (default
|
|
234
|
-
`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
|
|
235
362
|
"ask", so a lead can't accidentally skip the gate but a human can consciously override it. The gate
|
|
236
363
|
hook fires for **every** agent in the session, including subagents spawned by the Workflow runtime
|
|
237
364
|
(they run in `acceptEdits` whatever the session mode — Write/Edit auto-approved — but Bash and Task
|
|
@@ -240,7 +367,7 @@ hard deny, because nobody is there to answer a prompt.
|
|
|
240
367
|
|
|
241
368
|
## Rendering / reconciling a surface agent (shared procedure)
|
|
242
369
|
|
|
243
|
-
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
|
|
244
371
|
this exact procedure so a surface is always defined the same way. To add surface `S`:
|
|
245
372
|
|
|
246
373
|
1. **Add the `surfaces[]` entry** to `PIPELINE.md`: `key`, `path` (the disjoint tree it exclusively
|
|
@@ -259,7 +386,7 @@ this exact procedure so a surface is always defined the same way. To add surface
|
|
|
259
386
|
**baked at render time**: `PIPELINE.md` §Conventions `### Shared` + this surface's
|
|
260
387
|
`### Surface: <key>` stanza + its §Testing lines, verbatim. At runtime the agent then reads only
|
|
261
388
|
the profile's machine block (the fenced `yaml pipeline-profile`) — never the prose sections. The
|
|
262
|
-
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
|
|
263
390
|
re-renders every agent (step 2 below); hand-edit the prose without re-rendering and the baked
|
|
264
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
|
|
265
392
|
stored `design_project` id — that goes stale on a DS rebuild):
|
|
@@ -287,7 +414,7 @@ conventions. Never leave an agent file with no matching `surfaces[]` entry (orph
|
|
|
287
414
|
|
|
288
415
|
## Reconcile — bringing generated files up to the current core
|
|
289
416
|
|
|
290
|
-
`/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
|
|
291
418
|
core upgrade never requires re-running init — new pipeline features flow into the repo's generated
|
|
292
419
|
files automatically. It works because every generated artifact is a **deterministic function of
|
|
293
420
|
(current template × the profile's data)**; nothing needs re-detecting or re-interviewing.
|
|
@@ -305,7 +432,7 @@ files automatically. It works because every generated artifact is a **determinis
|
|
|
305
432
|
init spec (missing `allow` entries, hooks per install mode) — add what's missing, never remove or
|
|
306
433
|
rewrite existing/custom keys.
|
|
307
434
|
4. **Capability wiring.** If a top-up added a capability needing external setup (e.g. a `retrieval`
|
|
308
|
-
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.
|
|
309
436
|
Even when nothing new was added, re-run the provider's health check (§Code retrieval) — wiring
|
|
310
437
|
rots (PATH changes, uninstalls, hand-edits) — and repair whatever fails.
|
|
311
438
|
5. **Global config seed.** If `~/.claude/cohorte.config.yaml` is absent, seed it from the template
|
|
@@ -313,21 +440,38 @@ files automatically. It works because every generated artifact is a **determinis
|
|
|
313
440
|
clobber an existing filled file; report what was seeded.
|
|
314
441
|
6. **Kanban sync.** Run the §Kanban reconcile: link/create the project's board if configured, verify
|
|
315
442
|
its columns, and backfill/sync cards from `specs/*.md`. See §Kanban.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
443
|
+
7. **Spec-template top-up.** `specs/_template.md` is seeded once at install and then **never**
|
|
444
|
+
refreshed, so a repo keeps whatever front-matter the core shipped the day it was installed (a
|
|
445
|
+
pre-1.6 copy has no `loop_pass`/`loop_phase`, and its `status` comment still lists four states).
|
|
446
|
+
Top it up the same way as the profile: add the **front-matter fields** the current
|
|
447
|
+
`templates/spec.template.md` has and the repo's copy lacks, with their documented defaults, and
|
|
448
|
+
refresh the `status:` comment. Never rewrite its body — the section list is the human's to shape,
|
|
449
|
+
and some repos have deliberately trimmed it. Nothing breaks without this (the fields are written on
|
|
450
|
+
demand when a driver needs them); it just keeps a new spec's front-matter honest about the states
|
|
451
|
+
the pipeline can put it in.
|
|
452
|
+
|
|
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).
|
|
319
463
|
|
|
320
464
|
## Workflows — deterministic multi-agent runs (opt-in)
|
|
321
465
|
|
|
322
466
|
Three phases have a **workflow variant** — a deterministic orchestration script the Claude Code
|
|
323
467
|
Workflow runtime executes instead of the lead reasoning out the fan-out turn by turn:
|
|
324
468
|
`<core>/workflows/review.js`, `audit.js`, `refactor.js` (installed to `.claude/workflows/` bundled or
|
|
325
|
-
`~/.claude/workflows/` global). The conversational commands (`/review`, `/audit`, `/refactor`)
|
|
469
|
+
`~/.claude/workflows/` global). The conversational commands (`/cohorte-review`, `/cohorte-audit`, `/cohorte-refactor`)
|
|
326
470
|
**remain the default path and the fallback** — a workflow runs only when the human explicitly asks
|
|
327
471
|
for it ("run the review workflow"), and requires Claude Code ≥ **2.1.154** with workflows
|
|
328
472
|
enabled.
|
|
329
|
-
`/doctor` reports which path a session will take. The interactive commands (`/init-pipeline`,
|
|
330
|
-
`/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
|
|
331
475
|
purpose: they're interviews or already a single parallel dispatch — a script adds nothing.
|
|
332
476
|
|
|
333
477
|
Shared design, all four scripts:
|
|
@@ -347,19 +491,22 @@ Shared design, all four scripts:
|
|
|
347
491
|
that never answered: `review.js` names them in `unreviewedSurfaces` and refuses to score
|
|
348
492
|
`SHIP`. `scripts/test-workflows.mjs`
|
|
349
493
|
pins this — it is the one invariant the structural checks in `validate-core.mjs` cannot see.
|
|
494
|
+
The conversational commands enforce the same rule by roll call (§Dead agents); it was the workflows
|
|
495
|
+
that had it first, and for three releases they had it **alone** — the same crash on the
|
|
496
|
+
conversational path went unreported.
|
|
350
497
|
- **`review.js`** — preflight gate (aborts red, zero agents), one `git diff --stat` staged per
|
|
351
498
|
touched surface, one reviewer per surface in parallel, then an **adversarial cross-check** phase
|
|
352
499
|
that tries to refute each CRITICAL/security finding before it can trigger a fix loop.
|
|
353
500
|
- **`audit.js`** — one auditor per domain (each surface + `shared`), concurrency capped by the
|
|
354
501
|
runtime (~16), merged into the prioritized `specs/refactor-backlog.md`.
|
|
355
502
|
- **`refactor.js`** — big domains only (it skips domains with a handful of open items — the
|
|
356
|
-
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'
|
|
357
504
|
implementers in parallel, each verified per-domain.
|
|
358
505
|
- **No input mid-run.** A workflow runs to completion without questions; anything interactive
|
|
359
506
|
(contract changes, human decisions) belongs to the conversational path. The gate hook still
|
|
360
507
|
fires on workflow subagents (see
|
|
361
508
|
§Preflight) — in unattended runs its asks become denies.
|
|
362
|
-
- **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`
|
|
363
510
|
`allow` list with what workflow agents need (the quiet commands, the shipped
|
|
364
511
|
`pipeline/scripts/*.sh`, read-only git incl. `git rev-parse`, and the retrieval provider's MCP
|
|
365
512
|
tools) so a run never stalls mid-workflow on a permission prompt nobody is watching.
|
|
@@ -382,11 +529,11 @@ present else `kanban.columns`. Not found ⇒ kanban off for this project.
|
|
|
382
529
|
**Card format.** A card is a Kanban list item under a `## <column>` heading:
|
|
383
530
|
`- [ ] <human title> #<feature_id>`. The `#<feature_id>` tag is the join key between a card and its
|
|
384
531
|
`specs/<feature_id>.md`; it is how every stage finds *its* card (Grep the board for `#<id>`). Free-text
|
|
385
|
-
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
|
|
386
533
|
the trailing `%% kanban:settings … %%` block or the `kanban-plugin: board` front-matter.
|
|
387
534
|
|
|
388
|
-
Once shipped, `/ship` appends the **PR number** to the card — `- [ ] <title> #<feature_id> — PR #<num>`.
|
|
389
|
-
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
|
|
390
537
|
writes it when a PR was actually created.
|
|
391
538
|
|
|
392
539
|
**Move a card (the core op).** Use the shipped script — it does the whole op outside the agent's
|
|
@@ -405,18 +552,22 @@ card created in the target column if missing.
|
|
|
405
552
|
| Pipeline moment | Column |
|
|
406
553
|
| --------------------------------------- | --------------- |
|
|
407
554
|
| human drops a raw idea (manual) | `ideas` |
|
|
408
|
-
| `/brainstorm` picks it up | `brainstorm` |
|
|
409
|
-
| `/spec` opens (draft) | `spec` |
|
|
410
|
-
| `/spec` freezes (`status: frozen`) | `ready` |
|
|
411
|
-
| `/build` | `building` |
|
|
412
|
-
| `/review` | `review` |
|
|
413
|
-
| `/fix` | `fix` |
|
|
414
|
-
| `/
|
|
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` |
|
|
415
564
|
| PR opened (`status: shipped`) | `shipped` (+ `PR #<num>` on the card) |
|
|
416
565
|
|
|
417
566
|
**Backfill / sync from specs (reconcile).** `specs/*.md` is the source of truth. For each spec, read its
|
|
418
567
|
`feature_id` (front-matter or filename) and `status`, map `status`→column — `frozen`→`ready`,
|
|
419
|
-
`in-
|
|
568
|
+
`in-progress`→the `loop_phase`'s column (`build`→`building`, `review`→`review`, `fix`→`fix`; unset ⇒
|
|
569
|
+
`building`), `in-review`→`review`, `blocked`→`fix`, `shipped`→`shipped`, anything else / a spec with no
|
|
570
|
+
status→`spec` — then **full
|
|
420
571
|
sync**: card absent ⇒ add it in that column; card present ⇒ **move it** to that column so the board
|
|
421
572
|
always reflects the specs (this repositions cards the human may have moved by hand). Report cards
|
|
422
573
|
added vs. moved vs. already-correct.
|
|
@@ -429,12 +580,12 @@ per configured column in pipeline order, and the closing `%% kanban:settings %%`
|
|
|
429
580
|
## Telemetry — anonymous usage stats, strictly opt-in (GDPR-first)
|
|
430
581
|
|
|
431
582
|
Cohorte can send the maintainers anonymous usage pings so the pipeline improves where it's actually
|
|
432
|
-
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
|
|
433
584
|
pre-telemetry installs) ask ONE question, once per machine, default **No**, and record the answer in
|
|
434
585
|
`~/.claude/cohorte.config.yaml` §`telemetry` (`enabled`, `install_id`, `consent_date`). The sender —
|
|
435
586
|
`pipeline/scripts/telemetry-send.sh` — is a silent no-op unless `enabled: true` AND `install_id` AND
|
|
436
587
|
`endpoint` are all set, times out at 2s, and never fails the pipeline. Callers chain it with
|
|
437
|
-
`|| 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/`
|
|
438
589
|
is fully populated.
|
|
439
590
|
|
|
440
591
|
**Which commands ping** — the six that make up the feature funnel, and only those. The point is to
|
|
@@ -454,8 +605,8 @@ see where features stall, so every stage of `idea → PR` reports and nothing el
|
|
|
454
605
|
> forms are valid — but read the `fix` column knowing which path produced it.
|
|
455
606
|
|
|
456
607
|
`seconds: 0` marks a phase whose duration is human thinking time, not pipeline wall-clock — the
|
|
457
|
-
funnel signal there is the event, not how long it took. `/doctor`, `/audit`, `/refactor`,
|
|
458
|
-
`/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
|
|
459
610
|
keeping them out is what holds the collected set to what the consent text describes.
|
|
460
611
|
|
|
461
612
|
**What one event contains** (strict allowlist, ~200 bytes):
|
|
@@ -475,7 +626,7 @@ work without revealing what is being built.
|
|
|
475
626
|
- **Consent** — opt-in only, recorded with a date; "No" is also recorded so nothing re-asks.
|
|
476
627
|
- **Withdrawal** — set `telemetry.enabled: false` in `~/.claude/cohorte.config.yaml`; effective on
|
|
477
628
|
the next phase, no restart.
|
|
478
|
-
- **Erasure** — `/doctor` prints your `install_id`; send
|
|
629
|
+
- **Erasure** — `/cohorte-doctor` prints your `install_id`; send
|
|
479
630
|
`curl -X DELETE <endpoint-origin>/v1/install/<install_id>` and the collector drops every event
|
|
480
631
|
for that id (the deployed collector implements this and stores no IPs).
|
|
481
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"
|