@esneiderbravo/speclaw 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -4
- package/dist/cli/commands/init.js +2 -1
- package/dist/cli/commands/update.js +52 -56
- package/dist/cli/index.js +2 -2
- package/dist/cli/lib/update-check.js +8 -5
- package/dist/modules/lawbook/assets/agents/planner.md +3 -0
- package/dist/modules/lawbook/assets/skills/cortex/steps/02-dispatch-loop.md +3 -0
- package/dist/modules/lawbook/assets/skills/draft/steps/02-understand.md +12 -9
- package/dist/modules/lawbook/assets/skills/explore/steps/02-summarize.md +11 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -332,14 +332,19 @@ review from Code Owners* when you declare `team.owners`.
|
|
|
332
332
|
## <img src="https://raw.githubusercontent.com/esneiderbravo/speclaw/main/brand/diamond.png" height="20" alt="◆" align="absmiddle"> Staying up to date
|
|
333
333
|
|
|
334
334
|
speclaw checks for new releases in the background (at most once a day) and nudges
|
|
335
|
-
you when one lands. To
|
|
335
|
+
you when one lands. To bring a project up to date (migrations only — never runs
|
|
336
|
+
`npm install -g`):
|
|
336
337
|
|
|
337
338
|
```bash
|
|
338
339
|
speclaw update
|
|
339
340
|
```
|
|
340
341
|
|
|
341
|
-
|
|
342
|
-
|
|
342
|
+
If a newer binary is on npm, `update` prints an advisory (`current → latest`) and
|
|
343
|
+
how to upgrade the binary separately (`npm i -g @esneiderbravo/speclaw@latest`, or
|
|
344
|
+
prefer `npx @esneiderbravo/speclaw@latest update`), then still migrates the project.
|
|
345
|
+
|
|
346
|
+
`update` brings the current project up to date without a re-init, splitting files
|
|
347
|
+
by who owns them:
|
|
343
348
|
|
|
344
349
|
- **Managed files** (skills/commands/rules under `ai-specs/`) are **refreshed**.
|
|
345
350
|
Pass `--backup` to keep a `<file>.bak` before overwrite.
|
|
@@ -348,7 +353,8 @@ without a re-init, splitting files by who owns them:
|
|
|
348
353
|
prints a prompt for the agent you're using.
|
|
349
354
|
- **`speclaw.lock`** and the CODEOWNERS owners block are refreshed when configured.
|
|
350
355
|
|
|
351
|
-
- `speclaw update --check` — report
|
|
356
|
+
- `speclaw update --check` — report version status only; do not migrate.
|
|
357
|
+
- `speclaw update --migrate-only` — silent no-op alias of the default (compat).
|
|
352
358
|
- `NO_UPDATE_NOTIFIER=1` — silence the reminder.
|
|
353
359
|
|
|
354
360
|
<br/>
|
|
@@ -45,7 +45,8 @@ export async function runInit(flags) {
|
|
|
45
45
|
const upd = await checkForUpdates();
|
|
46
46
|
if (upd.updateAvailable && upd.latest) {
|
|
47
47
|
ui.warn(`You're on ${c.muted(upd.current)} — latest is ${c.bold(c.cyan(upd.latest))}.`);
|
|
48
|
-
ui.info(`Recommended:
|
|
48
|
+
ui.info(`Recommended: refresh the binary with ${ui.code("npx @esneiderbravo/speclaw@latest init")} ` +
|
|
49
|
+
`(or ${ui.code("npm i -g @esneiderbravo/speclaw@latest")}), then run ${ui.code("speclaw init")} again.`);
|
|
49
50
|
ui.plain();
|
|
50
51
|
}
|
|
51
52
|
if (interactive) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { spawnSync } from "node:child_process";
|
|
2
1
|
import fs from "node:fs";
|
|
3
2
|
import path from "node:path";
|
|
4
3
|
import { ui, c } from "../lib/ui.js";
|
|
@@ -11,6 +10,17 @@ import { readManifest } from "../../shared/manifest.js";
|
|
|
11
10
|
import { loadPacks } from "../../modules/tools/packs.js";
|
|
12
11
|
import { detectProjectName } from "./init.js";
|
|
13
12
|
import { reportTrackedLocalContent } from "../lib/untrack.js";
|
|
13
|
+
/**
|
|
14
|
+
* How to upgrade the installed binary without this command spawning `npm install -g`.
|
|
15
|
+
*
|
|
16
|
+
* @param name - Package name on npm (usually `pkgName()`).
|
|
17
|
+
* @returns One-line advisory for the terminal.
|
|
18
|
+
*/
|
|
19
|
+
export function binaryUpgradeHint(name) {
|
|
20
|
+
return (`Upgrade the binary separately with ${ui.code(`npm i -g ${name}@latest`)} ` +
|
|
21
|
+
`(or prefer ${ui.code(`npx ${name}@latest update`)}). ` +
|
|
22
|
+
`This command only migrates the project.`);
|
|
23
|
+
}
|
|
14
24
|
// The first migration must be tagged at the version that introduces this
|
|
15
25
|
// mechanism (0.1.12): `isNewer` is strict, so an entry tagged at an already-
|
|
16
26
|
// shipped version (e.g. 0.1.11) would never fire for projects already on it.
|
|
@@ -196,70 +206,56 @@ const MIGRATIONS = [
|
|
|
196
206
|
"`esneiderbravo/speclaw@v2`. See `docs/cortex.md`.\n" +
|
|
197
207
|
"- Preserve all project-specific wording; only apply these speclaw-authored changes.",
|
|
198
208
|
},
|
|
209
|
+
{
|
|
210
|
+
version: "2.0.1",
|
|
211
|
+
describe: "speclaw update no longer upgrades the global npm package",
|
|
212
|
+
agentPrompt: "- `speclaw update` applies **project** migrations only — it does **not** run " +
|
|
213
|
+
"`npm install -g`. If a newer binary exists on npm it prints an advisory; " +
|
|
214
|
+
"upgrade the CLI separately (`npm i -g @esneiderbravo/speclaw@latest` or " +
|
|
215
|
+
"`npx @esneiderbravo/speclaw@latest update`). Prefer `npx @…@latest` when the " +
|
|
216
|
+
"installed binary is stale so migrations match the latest package.\n" +
|
|
217
|
+
"- Preserve all project-specific wording; only apply these speclaw-authored changes.",
|
|
218
|
+
},
|
|
199
219
|
];
|
|
200
220
|
/**
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
* commands, and feature steps this
|
|
221
|
+
* Bring the current project up to date without a full re-init: check whether a
|
|
222
|
+
* newer binary exists on npm (advisory only — never runs `npm install -g`), then
|
|
223
|
+
* additively apply any new standards, skills, commands, and feature steps this
|
|
224
|
+
* project is missing (existing files untouched).
|
|
204
225
|
*
|
|
205
|
-
* @param flags - `--check` reports
|
|
206
|
-
*
|
|
207
|
-
*
|
|
226
|
+
* @param flags - `--check` reports version status only (no migrate);
|
|
227
|
+
* `--migrate-only` is a silent no-op alias of the default (compat).
|
|
228
|
+
* @param hooks - Optional test seams for the version check and migrate path.
|
|
208
229
|
*/
|
|
209
|
-
export async function runUpdate(flags) {
|
|
230
|
+
export async function runUpdate(flags, hooks = {}) {
|
|
210
231
|
const cwd = process.cwd();
|
|
211
|
-
|
|
232
|
+
// `--migrate-only` is accepted for compat but is a no-op alias of default
|
|
233
|
+
// (version check + project migrations). It no longer skips the version check.
|
|
212
234
|
const checkOnly = Boolean(flags.check);
|
|
213
235
|
const backup = Boolean(flags.backup);
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
ui.step(`Updating ${pkgName()} globally`);
|
|
228
|
-
const install = spawnSync("npm", ["install", "-g", `${pkgName()}@latest`], {
|
|
229
|
-
stdio: "inherit",
|
|
230
|
-
shell: winShell,
|
|
231
|
-
});
|
|
232
|
-
if (install.status !== 0) {
|
|
233
|
-
ui.err("Global update failed. Try again with elevated permissions (e.g. sudo), or check your npm setup.");
|
|
234
|
-
process.exit(1);
|
|
235
|
-
}
|
|
236
|
-
ui.ok(`Updated to ${latest}`);
|
|
237
|
-
// Re-exec the NEWLY installed binary so migrations run with the new assets
|
|
238
|
-
// and any new feature steps — not this (now-stale) process. Carry --backup
|
|
239
|
-
// through so the refresh honors it after the upgrade.
|
|
240
|
-
const reArgs = [
|
|
241
|
-
"update",
|
|
242
|
-
"--migrate-only",
|
|
243
|
-
...(backup ? ["--backup"] : []),
|
|
244
|
-
...(flags.minimal ? ["--minimal"] : []),
|
|
245
|
-
];
|
|
246
|
-
const re = spawnSync("speclaw", reArgs, {
|
|
247
|
-
stdio: "inherit",
|
|
248
|
-
shell: winShell,
|
|
249
|
-
});
|
|
250
|
-
if (re.error) {
|
|
251
|
-
ui.warn(`Upgraded — now run ${ui.code("speclaw update --migrate-only")} to apply project changes.`);
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
process.exit(re.status ?? 0);
|
|
255
|
-
}
|
|
256
|
-
else {
|
|
257
|
-
ui.ok(`Already on the latest version (${current}).`);
|
|
258
|
-
if (checkOnly)
|
|
259
|
-
return;
|
|
236
|
+
const check = hooks.checkForUpdates ?? checkForUpdates;
|
|
237
|
+
const migrate = hooks.applyProjectMigrations ?? applyProjectMigrations;
|
|
238
|
+
ui.step("Checking for updates");
|
|
239
|
+
const { current, latest, updateAvailable } = await check({ force: true });
|
|
240
|
+
if (!latest) {
|
|
241
|
+
ui.warn("Could not reach the npm registry — skipping the version check.");
|
|
242
|
+
}
|
|
243
|
+
else if (updateAvailable) {
|
|
244
|
+
ui.info(`${c.muted(current)} ${c.muted("→")} ${c.cyan(latest)}`);
|
|
245
|
+
ui.info(binaryUpgradeHint(pkgName()));
|
|
246
|
+
if (checkOnly) {
|
|
247
|
+
ui.info(`Run ${ui.code("speclaw update")} to apply project migrations with the binary you have.`);
|
|
248
|
+
return;
|
|
260
249
|
}
|
|
261
250
|
}
|
|
262
|
-
|
|
251
|
+
else {
|
|
252
|
+
ui.ok(`Already on the latest version (${current}).`);
|
|
253
|
+
if (checkOnly)
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
if (checkOnly)
|
|
257
|
+
return;
|
|
258
|
+
migrate(cwd, backup, flags.minimal ? true : undefined);
|
|
263
259
|
}
|
|
264
260
|
/**
|
|
265
261
|
* Additively apply the current version's content and feature steps to a project.
|
package/dist/cli/index.js
CHANGED
|
@@ -12,8 +12,8 @@ Install globally so the command is always available:
|
|
|
12
12
|
Setup
|
|
13
13
|
init Interactive setup: pick agents, scaffold, index, get the prompt
|
|
14
14
|
(--minimal omits setup/lifecycle MCP tools)
|
|
15
|
-
update
|
|
16
|
-
(--
|
|
15
|
+
update Apply project migrations (advisory if a newer binary exists)
|
|
16
|
+
(--check reports version only; --minimal persists minimal exposure)
|
|
17
17
|
agent list Show which agents are configured
|
|
18
18
|
agent add <id> Configure another agent later (symlinks + MCP)
|
|
19
19
|
|
|
@@ -102,15 +102,16 @@ export function npmPackageUrl(name) {
|
|
|
102
102
|
/**
|
|
103
103
|
* Build the two-line "update available" notice. The latest version is rendered
|
|
104
104
|
* as a clickable link to the package's npm page, so a capable terminal lets the
|
|
105
|
-
* user open the release with a single click
|
|
106
|
-
*
|
|
105
|
+
* user open the release with a single click. Project migrations stay
|
|
106
|
+
* `speclaw update`; the binary is upgraded separately (prefer npx).
|
|
107
107
|
*
|
|
108
108
|
* @param current - The installed version.
|
|
109
109
|
* @param latest - The newest published version.
|
|
110
110
|
* @returns The formatted, styled notice (no leading/trailing blank lines).
|
|
111
111
|
*/
|
|
112
112
|
export function upgradeNotice(current, latest) {
|
|
113
|
-
const
|
|
113
|
+
const name = pkgName();
|
|
114
|
+
const latestLink = c.cyan(link(latest, npmPackageUrl(name)));
|
|
114
115
|
return (" " +
|
|
115
116
|
c.amber("⬆ speclaw ") +
|
|
116
117
|
c.muted(current + " → ") +
|
|
@@ -118,9 +119,11 @@ export function upgradeNotice(current, latest) {
|
|
|
118
119
|
c.muted(" available") +
|
|
119
120
|
"\n" +
|
|
120
121
|
" " +
|
|
121
|
-
c.muted("
|
|
122
|
+
c.muted("prefer ") +
|
|
123
|
+
c.cyan(`npx ${name}@latest update`) +
|
|
124
|
+
c.muted(" — or ") +
|
|
122
125
|
c.cyan("speclaw update") +
|
|
123
|
-
c.muted("
|
|
126
|
+
c.muted(" to migrate this project"));
|
|
124
127
|
}
|
|
125
128
|
/**
|
|
126
129
|
* Print the "update available" notice to stderr when a newer version exists.
|
|
@@ -13,6 +13,9 @@ Turn the explorer brief + user intent into a reviewable change under
|
|
|
13
13
|
`lawbook/changes/<name>/` at the confirmed ceremony level. Prefer `draft` /
|
|
14
14
|
`quick` skills.
|
|
15
15
|
|
|
16
|
+
A complete explorer brief is the code map. Do not re-investigate it. Call
|
|
17
|
+
Compass only for a gap the brief names.
|
|
18
|
+
|
|
16
19
|
## Questions
|
|
17
20
|
|
|
18
21
|
If anything material is ambiguous, **stop**. Return numbered questions to the
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
For the current Cortex stage (`cortex` action `brief` or `status`):
|
|
4
4
|
|
|
5
5
|
1. Dispatch (spawn or adopt) the matching role with a clear handoff brief.
|
|
6
|
+
When the role is the planner, paste the explorer brief into the prompt
|
|
7
|
+
unchanged: symbols with files, callers and callees, blast radius, standards
|
|
8
|
+
already read, recommended approach, open questions, and gaps.
|
|
6
9
|
2. On role completion, call the matching Cortex op:
|
|
7
10
|
- exploring → `advance`
|
|
8
11
|
- planning with questions → `advance` + `pauseForQuestions` + `openQuestions`
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
# Understand the request and the code
|
|
2
2
|
|
|
3
|
-
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
- When the handoff includes a complete explorer brief (symbols with files,
|
|
4
|
+
callers and callees, blast radius, standards already read, recommended
|
|
5
|
+
approach, open questions, and gaps), that brief is the code map. Call
|
|
6
|
+
`compass_find` or `compass_explore` only for a gap the brief names. Re-read
|
|
7
|
+
a file under `docs/standards/` only when the brief does not cite it.
|
|
8
|
+
- When the handoff has no complete explorer brief, refresh the index with
|
|
9
|
+
`compass_index`, then use `compass_explore` and `compass_find` (mode:
|
|
10
|
+
concept) before grep/read to locate the code and its blast radius. Read the
|
|
11
|
+
governing standards in `docs/standards/`.
|
|
6
12
|
- Clarify what the user wants (feature / fix / refactor) and confirm scope.
|
|
7
|
-
- Use `compass_explore` and `compass_find` (mode: concept) (speclaw's code index) BEFORE
|
|
8
|
-
grep/read to locate the real code the change touches and its blast radius.
|
|
9
13
|
- **Propose a ceremony level** with `lawbook_level` (mode `propose`) using the
|
|
10
|
-
paths
|
|
11
|
-
writing artifacts. For an obvious one-liner,
|
|
12
|
-
|
|
13
|
-
frontend, testing) so the change complies with the project's law.
|
|
14
|
+
paths and symbols from the brief or from that locate pass; **confirm with the
|
|
15
|
+
human** (mode `set`) before writing artifacts. For an obvious one-liner,
|
|
16
|
+
offer `speclaw quick` instead.
|
|
14
17
|
|
|
15
18
|
Next: read `steps/03-name-capabilities.md` and do only what it says.
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
# Summarize
|
|
2
2
|
|
|
3
|
-
Produce a
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Produce a brief the planner can use as the code map. Include only these fields:
|
|
4
|
+
|
|
5
|
+
- symbols, each with its file
|
|
6
|
+
- callers and callees
|
|
7
|
+
- blast radius
|
|
8
|
+
- standards in `docs/standards/` already read
|
|
9
|
+
- recommended approach
|
|
10
|
+
- open questions
|
|
11
|
+
- gaps: the phrase "nothing unresolved", or each symbol that is still unresolved
|
|
12
|
+
|
|
13
|
+
When the direction is clear, offer to `draft` the change.
|
|
6
14
|
|
|
7
15
|
No further steps remain — explore workflow complete.
|