cohorte 1.2.3 → 1.2.5
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 +26 -0
- package/bin/cli.js +21 -3
- package/core/commands/doctor.md +4 -2
- package/core/commands/update-pipeline.md +8 -1
- package/package.json +1 -1
- package/scripts/validate-core.mjs +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,32 @@
|
|
|
3
3
|
Entries are shown by `/update-pipeline` ("What's new") after a core refresh. Keep them short,
|
|
4
4
|
user-facing, most recent first. One `## <version> — <YYYY-MM-DD>` section per release.
|
|
5
5
|
|
|
6
|
+
## 1.2.5 — 2026-07-29
|
|
7
|
+
|
|
8
|
+
- **`.claude/pipeline.json`'s `core_version` never updated on global installs.** The installer
|
|
9
|
+
bumps it in bundled mode, but a global core is shared — it cannot know which repos point at
|
|
10
|
+
it, so nothing bumped the field and it drifted forever. Repos running a current core were
|
|
11
|
+
still claiming `1.0.0`. `/update-pipeline` now syncs the pointer in both modes.
|
|
12
|
+
- `/doctor` no longer reports that drift as a broken install: a global-mode pointer lagging the
|
|
13
|
+
VERSION file is ⚠️ with the one-command fix, not ❌. The core was never the problem.
|
|
14
|
+
|
|
15
|
+
## 1.2.4 — 2026-07-29
|
|
16
|
+
|
|
17
|
+
> **If you installed with `npx cohorte`, this is the release that makes 1.2.3 actually
|
|
18
|
+
> reach you.** Re-run `npx cohorte@latest update --global` (or `update` for a bundled core).
|
|
19
|
+
|
|
20
|
+
- **`npx cohorte install/update` shipped a core missing two scripts.** `bin/cli.js` — the
|
|
21
|
+
port of `install.sh` that `npx` actually runs — copied only `scripts/*.template`, never
|
|
22
|
+
`kanban-move.sh` or `telemetry-send.sh`. Since every caller chains them with `|| true`,
|
|
23
|
+
the result was silent on every npx-installed machine: no kanban card moves, no telemetry
|
|
24
|
+
pings, no error anywhere. The shell installers named both files explicitly and this port
|
|
25
|
+
drifted from them. It now copies by a rule that needs no list to keep in sync.
|
|
26
|
+
- The same port never copied `CHANGELOG.md` into the core either, so `/doctor` and
|
|
27
|
+
`/update-pipeline`'s "What's new" had nothing to read on npx installs. Fixed.
|
|
28
|
+
- CI now dry-runs `bin/cli.js` into a scratch dir and asserts the same postconditions as
|
|
29
|
+
the `install.sh` dry-run. 1.2.3's guard only grepped the two shell installers — it would
|
|
30
|
+
have passed this bug, because the port copies by rule rather than by name.
|
|
31
|
+
|
|
6
32
|
## 1.2.3 — 2026-07-29
|
|
7
33
|
|
|
8
34
|
- **Telemetry now covers the whole funnel.** Only `/build` was actually pinging; `/smoke`,
|
package/bin/cli.js
CHANGED
|
@@ -102,13 +102,31 @@ function copyCore() {
|
|
|
102
102
|
for (const f of ['PIPELINE.template.md', 'SCHEMA.md', 'cohorte.config.template.yaml']) {
|
|
103
103
|
fs.copyFileSync(path.join(src, 'profile', f), path.join(pipelineDir, f));
|
|
104
104
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
// Copy the *.template files AND the shipped executables (kanban-move.sh,
|
|
106
|
+
// telemetry-send.sh). Until 1.2.4 this loop took only `.template`, so every
|
|
107
|
+
// `npx cohorte install/update` produced a core missing both scripts — and since
|
|
108
|
+
// every caller chains them with `|| true`, the result was silent: no kanban card
|
|
109
|
+
// moves, no telemetry pings, no error. The shell installers named them explicitly
|
|
110
|
+
// and this port drifted. The rule below needs no list to keep in sync: a `<x>.sh`
|
|
111
|
+
// with an `<x>.sh.template` sibling is rendered per-project by /init-pipeline, so
|
|
112
|
+
// only the template ships; every other `.sh` is a shipped executable.
|
|
113
|
+
const scriptFiles = fs.readdirSync(path.join(src, 'scripts'));
|
|
114
|
+
for (const f of scriptFiles) {
|
|
115
|
+
const isTemplate = f.endsWith('.template');
|
|
116
|
+
const isShipped = f.endsWith('.sh') && !scriptFiles.includes(`${f}.template`);
|
|
117
|
+
if (!isTemplate && !isShipped) continue;
|
|
118
|
+
const target = path.join(pipelineDir, 'scripts', f);
|
|
119
|
+
fs.copyFileSync(path.join(src, 'scripts', f), target);
|
|
120
|
+
if (isShipped && process.platform !== 'win32') {
|
|
121
|
+
try { fs.chmodSync(target, 0o755); } catch { /* optional */ }
|
|
108
122
|
}
|
|
109
123
|
}
|
|
110
124
|
fs.copyFileSync(path.join(src, 'core', 'agents', 'implementer.template.md'),
|
|
111
125
|
path.join(pipelineDir, 'implementer.template.md'));
|
|
126
|
+
// /doctor reads this to tell the human what they're missing; the shell installers
|
|
127
|
+
// have always copied it, this port never did.
|
|
128
|
+
const changelog = path.join(src, 'CHANGELOG.md');
|
|
129
|
+
if (fs.existsSync(changelog)) fs.copyFileSync(changelog, path.join(pipelineDir, 'CHANGELOG.md'));
|
|
112
130
|
fs.writeFileSync(path.join(pipelineDir, 'VERSION'), VERSION + '\n');
|
|
113
131
|
if (process.platform !== 'win32') {
|
|
114
132
|
try { fs.chmodSync(path.join(dest, 'hooks', 'gate.py'), 0o755); } catch { /* optional */ }
|
package/core/commands/doctor.md
CHANGED
|
@@ -14,8 +14,10 @@ fix only with the human's go-ahead (or hand them the command).
|
|
|
14
14
|
|
|
15
15
|
1. **Core & pointer.** A core exists (`~/.claude/pipeline/VERSION` global, and/or
|
|
16
16
|
`.claude/pipeline/VERSION` bundled); `.claude/pipeline.json` names a mode + `core_version`
|
|
17
|
-
coherent with the VERSION file.
|
|
18
|
-
|
|
17
|
+
coherent with the VERSION file. A **global**-mode pointer lagging the VERSION file is ⚠️, not ❌:
|
|
18
|
+
nothing bumped that field before 1.2.5, so the core itself is fine and only the pointer is stale
|
|
19
|
+
⇒ fix by running `/update-pipeline` (§3 syncs it now), or by editing the one field. Compare
|
|
20
|
+
against `npm view cohorte version` — behind ⇒ suggest `/update-pipeline`. Read `pipeline/CHANGELOG.md` for what they're missing. The router
|
|
19
21
|
commands' step files are present — `templates/steps/init-pipeline/` non-empty (a router whose
|
|
20
22
|
`templates/steps/<cmd>/` dir is missing is a partial/stale install ⇒
|
|
21
23
|
re-run install/update). **Shipped scripts present and executable** in `<core>/pipeline/scripts/`:
|
|
@@ -51,7 +51,14 @@ the human's choices — so `/init-pipeline` never needs re-running for an upgrad
|
|
|
51
51
|
## 3. Report old → new
|
|
52
52
|
|
|
53
53
|
Re-read the VERSION file(s) and print `old → new`. If unchanged, say the core was already up to date.
|
|
54
|
-
|
|
54
|
+
|
|
55
|
+
**Sync the pointer — in BOTH modes.** If this repo has a `.claude/pipeline.json` whose `core_version`
|
|
56
|
+
differs from the core you just installed, rewrite that one field (leave every other field untouched)
|
|
57
|
+
and tell the human to commit it. In **bundled** mode the installer already did it; in **global** mode
|
|
58
|
+
**nothing does** — the installer refreshes one shared core and cannot know which repos point at it,
|
|
59
|
+
so before 1.2.5 the field simply drifted forever (a repo on a current core still claiming `1.0.0`).
|
|
60
|
+
`/doctor` check 1 requires the pointer to be coherent with the VERSION file, so a drifted field reads
|
|
61
|
+
as a broken install when nothing is broken.
|
|
55
62
|
|
|
56
63
|
Then print **What's new**: read the installed `<core>/pipeline/CHANGELOG.md` and show the entries
|
|
57
64
|
between the old and new versions (most recent first). File absent ⇒ the old core predates 0.1.14 —
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cohorte",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"description": "Portable, stack-agnostic multi-agent development pipeline for Claude Code — install the core, run /init-pipeline, and it adapts to your project's stack.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"cohorte": "bin/cli.js"
|
|
@@ -130,9 +130,13 @@ for (const f of readdirSync(join(root, "core/commands"))) {
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
// ── shipped scripts ─────────────────────────────────────────────────────────
|
|
133
|
-
// Every scripts/*.sh must be copied by BOTH installers. Callers chain these
|
|
134
|
-
// `|| true`, so one
|
|
133
|
+
// Every scripts/*.sh must be copied by BOTH shell installers. Callers chain these
|
|
134
|
+
// with `|| true`, so one an installer forgets is a silent no-op forever — no kanban
|
|
135
135
|
// card moves, no telemetry ping, no error. CI is the only place this is loud.
|
|
136
|
+
// The third installer, bin/cli.js (what `npx cohorte` runs), copies by rule rather
|
|
137
|
+
// than by name, so grepping for filenames can't see it — ci.yml dry-runs it into a
|
|
138
|
+
// scratch HOME and asserts the same postconditions instead. Both are needed: this
|
|
139
|
+
// check catches a forgotten name, that one catches a drifted rule.
|
|
136
140
|
// A `<name>.sh` with a `<name>.sh.template` sibling is a locally-rendered artifact
|
|
137
141
|
// (this repo dogfoods its own /init-pipeline), not a core asset — skip those.
|
|
138
142
|
const installers = { "install.sh": read("install.sh"), "install.ps1": read("install.ps1") };
|