cohorte 2.1.0 → 2.3.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 +173 -0
- package/README.md +49 -41
- package/bin/cli.js +324 -28
- package/core/adapter/render.js +389 -0
- package/core/agents/implementer.template.md +3 -3
- package/core/agents/release.md +7 -6
- package/core/agents/review.md +17 -2
- package/core/commands/cohorte-audit.md +2 -0
- package/core/commands/cohorte-brainstorm.md +3 -11
- package/core/commands/cohorte-build.md +37 -23
- package/core/commands/cohorte-doctor.md +61 -36
- package/core/commands/cohorte-fix.md +3 -5
- package/core/commands/cohorte-init-pipeline.md +7 -8
- package/core/commands/cohorte-patch.md +113 -0
- package/core/commands/cohorte-refactor.md +5 -2
- package/core/commands/cohorte-review.md +20 -18
- package/core/commands/cohorte-ship.md +13 -14
- package/core/commands/cohorte-spec.md +4 -13
- package/core/commands/cohorte-update-pipeline.md +13 -12
- package/core/hooks/gate.py +203 -16
- package/core/runtimes/claude.json +73 -0
- package/core/runtimes/codex.json +82 -0
- package/core/runtimes/cursor.json +75 -0
- package/core/runtimes/gemini.json +75 -0
- package/core/runtimes/opencode.json +72 -0
- package/core/templates/patch.template.md +86 -0
- package/core/templates/spec.template.md +1 -3
- package/core/templates/steps/init-pipeline/01-detect-stack.md +1 -1
- package/core/templates/steps/init-pipeline/02-interview-gaps.md +1 -11
- package/core/templates/steps/init-pipeline/04-write-render.md +23 -17
- package/core/templates/steps/init-pipeline/05-report.md +1 -1
- package/core/workflows/review.js +1 -3
- package/dashboard/dist/assets/{index-P1I1JGtj.js → index-D1rsbLat.js} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/dashboard/server/doctor.js +156 -69
- package/dashboard/server/index.js +12 -2
- package/dashboard/server/metrics.js +13 -6
- package/dashboard/server/runtime.js +115 -0
- package/dashboard/server/versions.js +12 -1
- package/install.ps1 +26 -3
- package/install.sh +28 -6
- package/package.json +6 -2
- package/profile/PIPELINE.template.md +8 -6
- package/profile/SCHEMA.md +70 -108
- package/profile/cohorte.config.template.yaml +0 -16
- package/scripts/kanban-move.sh +11 -1
- package/scripts/metrics/collect.mjs +5 -3
- package/scripts/preflight.sh +27 -8
- package/scripts/test-adapter.mjs +368 -0
- package/scripts/test-dashboard.mjs +70 -0
- package/scripts/test-gate.mjs +62 -0
- package/scripts/validate-core.mjs +26 -24
- package/core/commands/cohorte-loop.md +0 -110
- package/scripts/loop-detach.sh +0 -153
- package/scripts/loop.sh +0 -399
- package/scripts/telemetry-send.sh +0 -77
- package/scripts/test-loop.mjs +0 -330
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "cursor",
|
|
3
|
+
"label": "Cursor",
|
|
4
|
+
"docs": "https://cursor.com/docs/cli/overview",
|
|
5
|
+
"detect": [
|
|
6
|
+
"~/.cursor"
|
|
7
|
+
],
|
|
8
|
+
"notes": [
|
|
9
|
+
"Cursor commands are plain markdown with NO placeholder substitution: whatever the human",
|
|
10
|
+
"types after the command name is appended to the prompt. The adapter therefore explains the",
|
|
11
|
+
"argument placeholder in the preamble rather than rewriting it to a token.",
|
|
12
|
+
"Subagents are markdown + frontmatter, and `readonly: true` is a real tool restriction \u2014",
|
|
13
|
+
"the review agent gets it. Cursor also reads .claude/agents and .codex/agents.",
|
|
14
|
+
"Hooks use Cursor's own envelope ({\"permission\": \u2026}), not Claude's.",
|
|
15
|
+
"Model pins are NOT carried across: the profile names Anthropic aliases (sonnet/haiku), which are meaningless here and would either error or be silently ignored. Agents and commands inherit this runtime's own model selection instead."
|
|
16
|
+
],
|
|
17
|
+
"scopes": {
|
|
18
|
+
"global": {
|
|
19
|
+
"root": "~/.cursor",
|
|
20
|
+
"core": "~/.cohorte/cursor",
|
|
21
|
+
"commands": "~/.cursor/commands",
|
|
22
|
+
"agents": "~/.cursor/agents",
|
|
23
|
+
"hooks": "~/.cohorte/cursor/hooks",
|
|
24
|
+
"hooks_config": "~/.cursor/hooks.json",
|
|
25
|
+
"workflows": null,
|
|
26
|
+
"settings": null
|
|
27
|
+
},
|
|
28
|
+
"project": {
|
|
29
|
+
"root": ".cursor",
|
|
30
|
+
"core": ".cohorte/cursor",
|
|
31
|
+
"commands": ".cursor/commands",
|
|
32
|
+
"agents": ".cursor/agents",
|
|
33
|
+
"hooks": ".cohorte/cursor/hooks",
|
|
34
|
+
"hooks_config": ".cursor/hooks.json",
|
|
35
|
+
"workflows": null,
|
|
36
|
+
"settings": null
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"exclude_commands": [],
|
|
40
|
+
"command": {
|
|
41
|
+
"format": "md",
|
|
42
|
+
"ext": ".md",
|
|
43
|
+
"frontmatter": [],
|
|
44
|
+
"args": null,
|
|
45
|
+
"args_note": "the text you typed after the command name",
|
|
46
|
+
"invoke": "/<name>"
|
|
47
|
+
},
|
|
48
|
+
"agent": {
|
|
49
|
+
"format": "md",
|
|
50
|
+
"ext": ".md",
|
|
51
|
+
"frontmatter": [
|
|
52
|
+
"name",
|
|
53
|
+
"description"
|
|
54
|
+
],
|
|
55
|
+
"readonly_key": "readonly",
|
|
56
|
+
"readonly_value": "true",
|
|
57
|
+
"dispatch": "invoke it as /<name> <brief>, or name it in the prompt; several run in parallel",
|
|
58
|
+
"address": "/<name>"
|
|
59
|
+
},
|
|
60
|
+
"hook": {
|
|
61
|
+
"format": "cursor",
|
|
62
|
+
"event": "beforeShellExecution",
|
|
63
|
+
"supports_ask": true,
|
|
64
|
+
"config_shape": "json"
|
|
65
|
+
},
|
|
66
|
+
"capabilities": {
|
|
67
|
+
"subagents": true,
|
|
68
|
+
"hooks": true,
|
|
69
|
+
"workflows": false,
|
|
70
|
+
"mcp": true,
|
|
71
|
+
"tool_restriction": true
|
|
72
|
+
},
|
|
73
|
+
"memory": "AGENTS.md",
|
|
74
|
+
"headless": "cursor-agent -p"
|
|
75
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "gemini",
|
|
3
|
+
"label": "Gemini CLI",
|
|
4
|
+
"docs": "https://geminicli.com/docs/",
|
|
5
|
+
"detect": [
|
|
6
|
+
"~/.gemini"
|
|
7
|
+
],
|
|
8
|
+
"notes": [
|
|
9
|
+
"Commands are TOML, not markdown: the whole prompt body becomes the `prompt` key, and the",
|
|
10
|
+
"argument placeholder is {{args}}. Sub-directories namespace with ':'.",
|
|
11
|
+
"Subagents ARE markdown + frontmatter (.gemini/agents), and are exposed to the main agent as",
|
|
12
|
+
"a tool of the same name; @agent-name forces one. They cannot call other subagents.",
|
|
13
|
+
"Hooks live in settings.json under `hooks`, event `BeforeTool`, matched on the tool name",
|
|
14
|
+
"(run_shell_command). The envelope is {\"decision\": \"deny\", \"reason\": \u2026} with no ask tier.",
|
|
15
|
+
"Model pins are NOT carried across: the profile names Anthropic aliases (sonnet/haiku), which are meaningless here and would either error or be silently ignored. Agents and commands inherit this runtime's own model selection instead."
|
|
16
|
+
],
|
|
17
|
+
"scopes": {
|
|
18
|
+
"global": {
|
|
19
|
+
"root": "~/.gemini",
|
|
20
|
+
"core": "~/.cohorte/gemini",
|
|
21
|
+
"commands": "~/.gemini/commands",
|
|
22
|
+
"agents": "~/.gemini/agents",
|
|
23
|
+
"hooks": "~/.cohorte/gemini/hooks",
|
|
24
|
+
"hooks_config": "~/.gemini/settings.json",
|
|
25
|
+
"workflows": null,
|
|
26
|
+
"settings": "~/.gemini/settings.json"
|
|
27
|
+
},
|
|
28
|
+
"project": {
|
|
29
|
+
"root": ".gemini",
|
|
30
|
+
"core": ".cohorte/gemini",
|
|
31
|
+
"commands": ".gemini/commands",
|
|
32
|
+
"agents": ".gemini/agents",
|
|
33
|
+
"hooks": ".cohorte/gemini/hooks",
|
|
34
|
+
"hooks_config": ".gemini/settings.json",
|
|
35
|
+
"workflows": null,
|
|
36
|
+
"settings": ".gemini/settings.json"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"exclude_commands": [],
|
|
40
|
+
"command": {
|
|
41
|
+
"format": "toml",
|
|
42
|
+
"ext": ".toml",
|
|
43
|
+
"frontmatter": [
|
|
44
|
+
"description"
|
|
45
|
+
],
|
|
46
|
+
"args": "{{args}}",
|
|
47
|
+
"invoke": "/<name>"
|
|
48
|
+
},
|
|
49
|
+
"agent": {
|
|
50
|
+
"format": "md",
|
|
51
|
+
"ext": ".md",
|
|
52
|
+
"frontmatter": [
|
|
53
|
+
"name",
|
|
54
|
+
"description"
|
|
55
|
+
],
|
|
56
|
+
"dispatch": "the subagent is exposed as a tool of the same name; @<name> forces it",
|
|
57
|
+
"address": "@<name>"
|
|
58
|
+
},
|
|
59
|
+
"hook": {
|
|
60
|
+
"format": "gemini",
|
|
61
|
+
"event": "BeforeTool",
|
|
62
|
+
"matcher": "run_shell_command",
|
|
63
|
+
"supports_ask": false,
|
|
64
|
+
"config_shape": "settings"
|
|
65
|
+
},
|
|
66
|
+
"capabilities": {
|
|
67
|
+
"subagents": true,
|
|
68
|
+
"hooks": true,
|
|
69
|
+
"workflows": false,
|
|
70
|
+
"mcp": true,
|
|
71
|
+
"tool_restriction": false
|
|
72
|
+
},
|
|
73
|
+
"memory": "GEMINI.md",
|
|
74
|
+
"headless": "gemini -p"
|
|
75
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "opencode",
|
|
3
|
+
"label": "OpenCode",
|
|
4
|
+
"docs": "https://opencode.ai/docs/cli/",
|
|
5
|
+
"detect": [
|
|
6
|
+
"~/.config/opencode",
|
|
7
|
+
"~/.opencode"
|
|
8
|
+
],
|
|
9
|
+
"notes": [
|
|
10
|
+
"Markdown agents in agents/ with `mode: subagent`, addressed with @<name>.",
|
|
11
|
+
"The one runtime here with NO hook mechanism \u2014 extension is via plugins (.opencode/plugin/*.js),",
|
|
12
|
+
"which is a different contract from a blocking PreToolUse hook. The gate therefore runs in",
|
|
13
|
+
"explicit --check mode, which is advisory by construction.",
|
|
14
|
+
"`opencode run` is the headless primitive; --agent selects an agent.",
|
|
15
|
+
"Model pins are NOT carried across: the profile names Anthropic aliases (sonnet/haiku), which are meaningless here and would either error or be silently ignored. Agents and commands inherit this runtime's own model selection instead."
|
|
16
|
+
],
|
|
17
|
+
"scopes": {
|
|
18
|
+
"global": {
|
|
19
|
+
"root": "~/.config/opencode",
|
|
20
|
+
"core": "~/.cohorte/opencode",
|
|
21
|
+
"commands": "~/.config/opencode/commands",
|
|
22
|
+
"agents": "~/.config/opencode/agents",
|
|
23
|
+
"hooks": null,
|
|
24
|
+
"workflows": null,
|
|
25
|
+
"settings": null
|
|
26
|
+
},
|
|
27
|
+
"project": {
|
|
28
|
+
"root": ".opencode",
|
|
29
|
+
"core": ".cohorte/opencode",
|
|
30
|
+
"commands": ".opencode/commands",
|
|
31
|
+
"agents": ".opencode/agents",
|
|
32
|
+
"hooks": null,
|
|
33
|
+
"workflows": null,
|
|
34
|
+
"settings": null
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"exclude_commands": [],
|
|
38
|
+
"command": {
|
|
39
|
+
"format": "md",
|
|
40
|
+
"ext": ".md",
|
|
41
|
+
"frontmatter": [
|
|
42
|
+
"description",
|
|
43
|
+
"agent",
|
|
44
|
+
"subtask"
|
|
45
|
+
],
|
|
46
|
+
"args": "$ARGUMENTS",
|
|
47
|
+
"invoke": "/<name>"
|
|
48
|
+
},
|
|
49
|
+
"agent": {
|
|
50
|
+
"format": "md",
|
|
51
|
+
"frontmatter": [
|
|
52
|
+
"description",
|
|
53
|
+
"mode"
|
|
54
|
+
],
|
|
55
|
+
"defaults": {
|
|
56
|
+
"mode": "subagent"
|
|
57
|
+
},
|
|
58
|
+
"dispatch": "address the subagent with @<name> and give it the full brief in one message",
|
|
59
|
+
"address": "@<name>",
|
|
60
|
+
"ext": ".md"
|
|
61
|
+
},
|
|
62
|
+
"capabilities": {
|
|
63
|
+
"subagents": true,
|
|
64
|
+
"hooks": false,
|
|
65
|
+
"workflows": false,
|
|
66
|
+
"mcp": true,
|
|
67
|
+
"tool_restriction": false
|
|
68
|
+
},
|
|
69
|
+
"memory": "AGENTS.md",
|
|
70
|
+
"headless": "opencode run",
|
|
71
|
+
"hook": null
|
|
72
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
feature_id: patch-<slug>
|
|
3
|
+
kind: patch # a bug fix, not a feature — /cohorte-build skips contract authoring, /cohorte-ship commits `fix(…)`
|
|
4
|
+
title: <one line: the bug, from the user's side>
|
|
5
|
+
status: draft # draft → frozen → in-progress → in-review → shipped · blocked (see SCHEMA.md §Spec status)
|
|
6
|
+
severity: <critical | major | minor> # drives nothing mechanical; it is what the human triages on
|
|
7
|
+
branch: <patch_branch_prefix><feature_id>
|
|
8
|
+
created: <YYYY-MM-DD>
|
|
9
|
+
reviewed_base: # merge-base sha at the last SHIP verdict — freshness-gate anchor (written by /cohorte-review)
|
|
10
|
+
reviewed_digest: # sha256 (16 hex) of the reviewed source diff vs reviewed_base, specs excluded — /cohorte-ship re-checks
|
|
11
|
+
design_files: [] # omit unless the fix is itself visual
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# <one line: the bug, from the user's side>
|
|
15
|
+
|
|
16
|
+
## 1. Symptom & repro
|
|
17
|
+
|
|
18
|
+
> What the user sees, and the shortest deterministic path to see it. A repro nobody can run is a
|
|
19
|
+
> hypothesis, not a bug — say so here rather than pretending otherwise.
|
|
20
|
+
|
|
21
|
+
- **Observed:** …
|
|
22
|
+
- **Expected:** …
|
|
23
|
+
- **Repro:** 1. … 2. … 3. …
|
|
24
|
+
- **Since / trigger:** <version, commit, or "unknown">
|
|
25
|
+
|
|
26
|
+
## 2. Impact
|
|
27
|
+
|
|
28
|
+
> Who is affected, how often, and whether there is a workaround. This is what justifies the patch
|
|
29
|
+
> jumping the feature queue — one or two lines.
|
|
30
|
+
|
|
31
|
+
## 3. Cause
|
|
32
|
+
|
|
33
|
+
> Confirmed or hypothesis — label which. Name the `file:line` if you have it. If the cause is
|
|
34
|
+
> unknown at freeze, say so: the implementer's first job is then to find it, and the review will
|
|
35
|
+
> check that the stated cause matches the diff.
|
|
36
|
+
|
|
37
|
+
## 4. Regression test (red first)
|
|
38
|
+
|
|
39
|
+
> The heart of a patch spec — it replaces §5 CONTRACT as the thing the diff is checked against.
|
|
40
|
+
> Name the test file and what it asserts. It must fail on the current code and pass after the fix.
|
|
41
|
+
|
|
42
|
+
- **Test:** `<path/to/test>` · asserts: …
|
|
43
|
+
- **Fails today because:** …
|
|
44
|
+
|
|
45
|
+
## 5. Contract delta
|
|
46
|
+
|
|
47
|
+
> Usually `none`. A fix that *changes* an existing contract entry describes the change here and
|
|
48
|
+
> `/cohorte-build` propagates it to every surface that names it. A fix that needs **new** contract
|
|
49
|
+
> surface area is not a patch — stop and run `/cohorte-spec` instead.
|
|
50
|
+
|
|
51
|
+
`none`
|
|
52
|
+
|
|
53
|
+
## 6. Surface tasks
|
|
54
|
+
|
|
55
|
+
> One `###` subsection per surface the fix touches — a patch may legitimately span several (an
|
|
56
|
+
> unvalidated field on the API *and* the form that sends it). Each TDD: the §4 test first.
|
|
57
|
+
|
|
58
|
+
### <surface.key>
|
|
59
|
+
|
|
60
|
+
- …
|
|
61
|
+
|
|
62
|
+
## 7. Out of scope
|
|
63
|
+
|
|
64
|
+
> The adjacent things this patch deliberately does NOT fix. This is the section that keeps a bug fix
|
|
65
|
+
> from turning into a refactor — the reviewer reads it before flagging what you left alone. Real but
|
|
66
|
+
> out-of-scope findings belong in `specs/refactor-backlog.md`, not in this diff.
|
|
67
|
+
|
|
68
|
+
- …
|
|
69
|
+
|
|
70
|
+
## 9. Acceptance criteria / DoD
|
|
71
|
+
|
|
72
|
+
> §9, not §8 — the number is load-bearing, so don't renumber it. `review.md` and
|
|
73
|
+
> `implementer.template.md` both name "contract §5, acceptance §9" verbatim, so a patch spec pins
|
|
74
|
+
> those two sections to the feature spec's numbers and just has no §8 (the feature spec has no §7 —
|
|
75
|
+
> a gap in the sequence is normal here).
|
|
76
|
+
|
|
77
|
+
- [ ] The §4 regression test exists, and failed before the fix
|
|
78
|
+
- [ ] Each touched surface's tests (TDD) green
|
|
79
|
+
- [ ] `PIPELINE.md` commands.lint · typecheck · test green
|
|
80
|
+
- [ ] The repro in §1 no longer reproduces
|
|
81
|
+
- [ ] Nothing outside §6's surfaces changed
|
|
82
|
+
|
|
83
|
+
## Remediation
|
|
84
|
+
|
|
85
|
+
> Filled by `/cohorte-fix` from a REVIEW REPORT; empty otherwise. Each item:
|
|
86
|
+
> `[ ] <SEVERITY> · <file:line> · <spec-violation|quality|security> · <concrete fix>`
|
|
@@ -4,8 +4,6 @@ title: <Feature title>
|
|
|
4
4
|
status: draft # draft → frozen → in-progress → in-review → shipped · blocked (see SCHEMA.md §Spec status)
|
|
5
5
|
branch: <feature_branch_prefix><slug>
|
|
6
6
|
created: <YYYY-MM-DD>
|
|
7
|
-
loop_pass: 0 # /cohorte-loop bookkeeping — the review pass it is on; 0 = no loop running. Written by the driver, not by hand
|
|
8
|
-
loop_phase: # /cohorte-loop bookkeeping — build | review | fix | done. With loop_pass, this is what `--resume` reads back
|
|
9
7
|
reviewed_base: # merge-base sha at the last SHIP verdict — freshness-gate anchor (written by /cohorte-review)
|
|
10
8
|
reviewed_digest: # sha256 (16 hex) of the reviewed source diff vs reviewed_base, specs excluded — /cohorte-ship re-checks
|
|
11
9
|
design_files: [] # design page links — full URLs of the form https://claude.ai/design/p/<projectId>?file=<file> (each carries its own project + page); blank until designed; omit if no UI
|
|
@@ -64,7 +62,7 @@ design_files: [] # design page links — full URLs of the form https://claude.ai
|
|
|
64
62
|
|
|
65
63
|
## 8. Design brief (the "spec return")
|
|
66
64
|
|
|
67
|
-
> Only if the project has UI. Standalone; mirrors
|
|
65
|
+
> Only if the project has UI. Standalone; mirrors `<core>/templates/design-brief.md`.
|
|
68
66
|
|
|
69
67
|
- **Screens / views:** …
|
|
70
68
|
- **Flows:** …
|
|
@@ -37,7 +37,7 @@ Gather evidence, then summarize what you found. Look for:
|
|
|
37
37
|
`graphify`? Is either already registered in this repo's `.mcp.json` or `claude mcp list`? (Feeds
|
|
38
38
|
the retrieval question + Phase 4 wiring — default provider is `serena`.)
|
|
39
39
|
- **VCS:** `git remote -v` → host + `owner/repo`; the default branch (`git symbolic-ref refs/remotes/origin/HEAD` or `git branch`).
|
|
40
|
-
- **Existing
|
|
40
|
+
- **Existing `<memory>`** — read it; it may already state stack/conventions to fold in. **Existing
|
|
41
41
|
`PIPELINE.md`** — if present, this is a re-run: load it as the starting draft and only reconcile deltas.
|
|
42
42
|
|
|
43
43
|
Print a compact **Detection Report**: layout, surfaces (with framework + commands), contract, release
|
|
@@ -47,19 +47,9 @@ Prefer sensible defaults from Phase 1 as the first (Recommended) option in each
|
|
|
47
47
|
|
|
48
48
|
- **Kanban** (optional) — mirror this project's pipeline (`/cohorte-brainstorm`…`/cohorte-ship`) onto an Obsidian
|
|
49
49
|
Kanban board? If the human says yes: confirm the shared vault path (`obsidian.vault_path` in
|
|
50
|
-
|
|
50
|
+
`<config>`; ask if empty) and the board's location inside it (default
|
|
51
51
|
`<ProjectName>/Tasks.md`). Phase 4 creates the board and records the link. Default: no.
|
|
52
52
|
|
|
53
53
|
> The **kanban** link is user-scoped (it points at a personal vault, so it never goes in the committed
|
|
54
54
|
> `PIPELINE.md`), but IS wired here because it is per-project — see Phase 4.
|
|
55
55
|
|
|
56
|
-
- **Telemetry** (optional, machine-scoped — SKIP entirely if `~/.claude/cohorte.config.yaml` already
|
|
57
|
-
has a `telemetry:` block with a `consent_date`, i.e. the human already answered on this machine).
|
|
58
|
-
Ask ONE opt-in question, stating exactly: _"Share anonymous usage stats with the cohorte project?
|
|
59
|
-
One ping per pipeline phase, `/cohorte-brainstorm` through `/cohorte-ship`: core version, OS, phase name, duration,
|
|
60
|
-
per-surface result counts, and a hash of the feature id — never repo names, paths, code, or IPs.
|
|
61
|
-
Setup and maintenance commands never ping. Off by default; withdraw anytime
|
|
62
|
-
(`telemetry.enabled: false`); erase your history anytime (SCHEMA.md §Telemetry). Default: No."_
|
|
63
|
-
On **yes**: in the global config set `telemetry.enabled: true`, mint `install_id` (`uuidgen`,
|
|
64
|
-
lowercase), set `consent_date` (ISO date). On **no**: set `enabled: false` + `consent_date` (so
|
|
65
|
-
no future command re-asks). Never touch `endpoint` — it ships with the template.
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
### Phase 4 — Write & render (after go-ahead)
|
|
4
4
|
|
|
5
5
|
1. **Write `PIPELINE.md`** at the repo root (source: the installer's `pipeline/PIPELINE.template.md`).
|
|
6
|
-
2. **Wire it into
|
|
6
|
+
2. **Wire it into `<memory>`:** if `<memory>` exists, ensure it references the profile (add a line
|
|
7
7
|
near the top: `> Project profile & pipeline facts: **@PIPELINE.md**`). If not, create a minimal
|
|
8
|
-
|
|
8
|
+
`<memory>` with that reference + a one-paragraph project intro.
|
|
9
9
|
3. **Render one agent per surface** — for each surface, follow SCHEMA.md §"Rendering / reconciling a
|
|
10
|
-
surface agent" (steps 2–3): render
|
|
10
|
+
surface agent" (steps 2–3): render `<agents>/<agent>.md` from the installer's
|
|
11
11
|
`pipeline/implementer.template.md`, substituting `<SURFACE_AGENT>`, `<SURFACE_LABEL>`, `<SURFACE_PATH>`,
|
|
12
12
|
`<SURFACE_TOOLS>`, `<SURFACE_MODEL>`, `<PROJECT_NAME>`, `<SURFACE_CONVENTIONS>` (the surface's
|
|
13
13
|
baked convention slice — §Shared + its `### Surface:` stanza + its §Testing lines from the
|
|
@@ -16,26 +16,24 @@
|
|
|
16
16
|
only when `uses_design`).
|
|
17
17
|
Leave the fixed agents as-is (generic, shipped by the installer): `review.md`, `release.md`,
|
|
18
18
|
`profile-reader.md`.
|
|
19
|
-
4. **Generate
|
|
19
|
+
4. **Generate `<state>/gate-config.json`** from the `gate` block — copy all five keys verbatim:
|
|
20
20
|
`{"deny": [...], "ask": [...], "ask_on_default_branch": [...], "default_branch": "<vcs.default_branch>",
|
|
21
21
|
"preflight": {"enabled": <gate.preflight.enabled>, "agents": [...], "max_age_minutes": <n>}}`
|
|
22
22
|
(profile has no `preflight` block ⇒ omit the key — the hook then skips the phase gate).
|
|
23
|
+
<!-- cohorte:if hooks -->
|
|
23
24
|
5. **Write `.claude/settings.json`** permissions (`ask`/`deny` lists mirroring the gate, **plus an
|
|
24
25
|
`allow` list of the project's read-only / verification commands** so agents don't stall on
|
|
25
26
|
permission prompts — including mid-workflow, where nobody is watching a prompt: the detected
|
|
26
27
|
per-surface `test_cmd`/`lint_cmd`/`typecheck_cmd`/`build_cmd` **and their `*_quiet_cmd`
|
|
27
28
|
variants** and repo-wide `commands.*` equivalents as `Bash(<cmd>:*)` rules, plus read-only git —
|
|
28
29
|
`Bash(git status:*)`, `Bash(git diff:*)`, `Bash(git log:*)`, `Bash(git rev-parse:*)` — plus the
|
|
29
|
-
shipped pipeline scripts
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
and `Bash(bash ~/.claude/pipeline/scripts/loop.sh:*)`) — those prefix rules match a command
|
|
33
|
-
*starting* with the path, so `bash <path>` needs its own entry or `/cohorte-loop` stalls on a permission
|
|
34
|
-
prompt at every launch, and the
|
|
30
|
+
shipped pipeline scripts (`Bash(<core>/pipeline/scripts/:*)` — preflight, kanban-move;
|
|
31
|
+
a prefix rule matches a command *starting* with that path, so a `bash <path>`
|
|
32
|
+
invocation would need its own entry), and the
|
|
35
33
|
retrieval provider's MCP tools when wired (e.g. `mcp__serena`). Never allowlist anything matching
|
|
36
34
|
a `gate.ask`/`gate.deny` pattern. Mention the human can widen it later with
|
|
37
35
|
`/fewer-permission-prompts`) + the hooks, **conditioned on the install mode:**
|
|
38
|
-
- **bundled:** register the PreToolUse hook
|
|
36
|
+
- **bundled:** register the PreToolUse hook `<core>/hooks/gate.py` with matcher `Bash|Task`
|
|
39
37
|
(Task is required — the preflight phase gate keys off Task dispatches; a `Bash`-only matcher
|
|
40
38
|
leaves it dead) and the PostToolUse formatter (detected formatter). Before adding, drop any
|
|
41
39
|
existing PreToolUse entry whose command ends in `gate.py` (here AND in `~/.claude/settings.json`
|
|
@@ -47,6 +45,14 @@
|
|
|
47
45
|
registration serves every repo; you only supply this repo's `gate-config.json`. Still write the
|
|
48
46
|
PostToolUse formatter hook + the permissions.
|
|
49
47
|
Preserve any existing custom keys.
|
|
48
|
+
<!-- cohorte:else -->
|
|
49
|
+
5. **No permissions or hook file to write.** This runtime has neither a PreToolUse hook nor a
|
|
50
|
+
settings.json permission model the pipeline can generate, so the gate is enforced by the
|
|
51
|
+
commands calling `<core>/hooks/gate.py --check` at the points the profile marks gated. That
|
|
52
|
+
means `<state>/gate-config.json` (step 4) is not decoration here — it is the ONLY place the
|
|
53
|
+
deny/ask patterns live, so fill it from the profile exactly and do not skip it. If this repo is
|
|
54
|
+
also driven from Claude Code, that install's hook reads the same file; nothing to duplicate.
|
|
55
|
+
<!-- cohorte:endif -->
|
|
50
56
|
6. **Wire the retrieval provider** (skip if `retrieval.provider: none`):
|
|
51
57
|
- **serena:** if the `serena` CLI is missing, have the human install it (`uv tool install -p 3.13
|
|
52
58
|
serena-agent`) — or set the provider to `none` if they decline, and say `/cohorte-update-pipeline` can wire
|
|
@@ -74,14 +80,14 @@
|
|
|
74
80
|
slug, DB pattern, port bases, compose file, branch prefix, install/dev/migrate commands, per-surface
|
|
75
81
|
env stanzas). `chmod +x` them. If isolation is disabled, skip and note features build in the main checkout.
|
|
76
82
|
8. **Ensure `specs/_template.md`** exists (copy from the installer's `templates/spec.template.md` if missing).
|
|
77
|
-
9. **Write the pointer**
|
|
83
|
+
9. **Write the pointer** `<state>/pipeline.json` (committed — this is how a teammate who clones the repo
|
|
78
84
|
knows which core to install):
|
|
79
85
|
`{ "pipeline": "cohorte", "mode": "<bundled|global>", "core_version": "<contents of the
|
|
80
86
|
installer's pipeline/VERSION>", "install": "<per mode: bundled ⇒ \"npx cohorte install\"
|
|
81
87
|
note that the core is committed under .claude/; global ⇒ \"npx cohorte install --global\"
|
|
82
88
|
(or, without npm: curl -fsSL https://raw.githubusercontent.com/TheBidouilleAgency/cohorte/main/install.sh | sh -s -- --global;
|
|
83
89
|
Windows: install.ps1 -Global from the same repo)> " }`.
|
|
84
|
-
In **global** mode also add, near the top of
|
|
90
|
+
In **global** mode also add, near the top of `<memory>`, a one-liner:
|
|
85
91
|
`> Pipeline: global core — run the installer above if /cohorte-brainstorm etc. are missing.`
|
|
86
92
|
10. **CI workflow** (if `vcs.host: github` and no existing workflow already runs the profile's
|
|
87
93
|
checks): with the human's go-ahead, generate `.github/workflows/pipeline-ci.yml` — on
|
|
@@ -89,18 +95,18 @@
|
|
|
89
95
|
`commands.install`, then `commands.lint` · `commands.typecheck` · `commands.test` (+ per-surface
|
|
90
96
|
`build_cmd`s that are non-empty). Derive the setup steps from the detected stack — mirror what a
|
|
91
97
|
sibling workflow does if one exists. `/cohorte-ship` watches these checks before the merge.
|
|
92
|
-
11. **Metrics sink, report buffer & preflight stamp:** add
|
|
98
|
+
11. **Metrics sink, report buffer & preflight stamp:** add `<state>/pipeline-metrics.jsonl` to
|
|
93
99
|
`.gitignore` — `/cohorte-build`, `/cohorte-review` and `/cohorte-fix` append per-dispatch evidence
|
|
94
100
|
there (SCHEMA §Specialization reads it).
|
|
95
101
|
Also add `specs/reports/` — `/cohorte-review` stages its last report there so a `/cohorte-fix` (or
|
|
96
102
|
`/cohorte-spec` Mode B) survives a `/clear`; it's a derived buffer, not a versioned artifact.
|
|
97
|
-
And
|
|
103
|
+
And `<state>/preflight.ok` — a local, per-checkout freshness stamp. Versioning it breaks the phase
|
|
98
104
|
gate for good (a committed stamp describes the tree *before* its own commit, and it rides into every
|
|
99
|
-
new worktree as a green nobody earned). If it is already tracked: `git rm --cached
|
|
105
|
+
new worktree as a green nobody earned). If it is already tracked: `git rm --cached <state>/preflight.ok`.
|
|
100
106
|
12. **Design system:** if `design.enabled` with a snapshot dir, note that `/cohorte-align-ds` is active; else the
|
|
101
107
|
`/cohorte-align-ds` command will no-op with a clear message.
|
|
102
108
|
13. **Kanban** (only if the human opted in at Phase 2): wire it per SCHEMA.md §Kanban, writing into the
|
|
103
|
-
**global**
|
|
109
|
+
**global** `<config>` (never into this repo — the board points at a
|
|
104
110
|
personal vault). Create the file from `pipeline/cohorte.config.template.yaml` if absent; set
|
|
105
111
|
`kanban.enabled: true` and `obsidian.vault_path` if it was empty. Add a `kanban.boards[<PIPELINE
|
|
106
112
|
name>]` entry with `board: <folder>/Tasks.md`. Then **create the board file**
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
### Phase 5 — Report
|
|
4
4
|
|
|
5
5
|
Print: the install mode (bundled core under `.claude/` vs global core in `~/.claude/` + the committed
|
|
6
|
-
|
|
6
|
+
`<state>/pipeline.json` pointer), the files written/rendered, the surface→agent mapping, and the
|
|
7
7
|
tailored workflow line, e.g.
|
|
8
8
|
`/cohorte-brainstorm → /cohorte-spec → (design) → /cohorte-build <id> → test → /cohorte-review → /cohorte-ship`. Tell the human to sanity-check
|
|
9
9
|
`PIPELINE.md`, commit it, and run `/cohorte-brainstorm` to start a feature. Note that this was the one-time
|
package/core/workflows/review.js
CHANGED
|
@@ -323,12 +323,10 @@ const staging = await agent(
|
|
|
323
323
|
`1. Write EXACTLY this content to specs/reports/${feature}.md (overwrite):\n<<<REPORT\n${reportBody}\nREPORT\n` +
|
|
324
324
|
`2. Append one line to $(dirname "$(git rev-parse --git-common-dir)")/.claude/pipeline-metrics.jsonl: ` +
|
|
325
325
|
`{"ts":"<ISO now>","feature":"${feature}","phase":"review","seconds":0,"surfaces":{${results.map(r => `"${r.key}":"${verdict}:${r.kept.length}"`).join(',')}}}\n` +
|
|
326
|
-
`3. Chain the opt-in usage ping: <core>/pipeline/scripts/telemetry-send.sh review "${feature}" 0 "${verdict}:${kept.length}" || true ` +
|
|
327
|
-
'(<core> = .claude if .claude/pipeline/scripts/telemetry-send.sh exists, else ~/.claude; script on neither ⇒ skip the ping).\n' +
|
|
328
326
|
// Deferred findings must land in the backlog on EVERY verdict — parked only on a
|
|
329
327
|
// SHIP is parked nowhere the rest of the time, which is the leak this closes.
|
|
330
328
|
(deferredAll.length
|
|
331
|
-
? `
|
|
329
|
+
? `3. Route the deferred findings to specs/refactor-backlog.md (create it if absent): for each line below, ` +
|
|
332
330
|
`append it under the \`## <domain>\` heading named in its prefix (create that heading if absent) — with \`>>\`, ` +
|
|
333
331
|
`never by rewriting the file, and skip any whose file path + first words already appear there (grep -F first, ` +
|
|
334
332
|
`they may be left from a prior round or an /cohorte-audit):\n` +
|