projectstore-claude 0.30.1 → 0.30.3
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/node_modules/projectstore/.claude-plugin/marketplace.json +1 -1
- package/node_modules/projectstore/.claude-plugin/plugin.json +1 -1
- package/node_modules/projectstore/AGENTS.md +7 -5
- package/node_modules/projectstore/README.md +5 -5
- package/node_modules/projectstore/agents/clerk.md +2 -2
- package/node_modules/projectstore/commands/agents.md +38 -26
- package/node_modules/projectstore/commands/bind.md +1 -1
- package/node_modules/projectstore/commands/doctor.md +15 -3
- package/node_modules/projectstore/commands/reconcile.md +2 -2
- package/node_modules/projectstore/commands/review.md +1 -1
- package/node_modules/projectstore/commands/story.md +2 -1
- package/node_modules/projectstore/docs/getting-started.md +1 -1
- package/node_modules/projectstore/docs/harnesses.md +3 -2
- package/node_modules/projectstore/harnesses/claude-code.json +92 -2
- package/node_modules/projectstore/harnesses/codex.json +81 -14
- package/node_modules/projectstore/package.json +1 -1
- package/node_modules/projectstore/scripts/agents-change.mjs +64 -10
- package/node_modules/projectstore/scripts/build-adapters.mjs +28 -13
- package/node_modules/projectstore/scripts/cli.mjs +32 -9
- package/node_modules/projectstore/scripts/configure-menu.mjs +716 -0
- package/node_modules/projectstore/scripts/configure.mjs +239 -91
- package/node_modules/projectstore/scripts/doctor.mjs +95 -31
- package/node_modules/projectstore/scripts/harness.mjs +13 -3
- package/node_modules/projectstore/scripts/install-harness.mjs +29 -0
- package/node_modules/projectstore/scripts/lib.mjs +32 -9
- package/node_modules/projectstore/scripts/menu.mjs +746 -0
- package/node_modules/projectstore/scripts/models.mjs +649 -0
- package/node_modules/projectstore/scripts/term.mjs +167 -0
- package/node_modules/projectstore/templates/claude-md-block.md.tmpl +7 -5
- package/package.json +2 -2
|
@@ -137,6 +137,17 @@ export const GLYPHS = Object.freeze({
|
|
|
137
137
|
// A move or a state change in a step's text: `a → b` (decided 2026-10-10,
|
|
138
138
|
// added to the spec's table at the story's close-out).
|
|
139
139
|
transition: Object.freeze(["→", "->"]),
|
|
140
|
+
// The settings menu's frames and marks (contract 14, added 2026-10-13): a
|
|
141
|
+
// frame's corners (its sides are the rail and the rule), the cursor on the
|
|
142
|
+
// row the keys act on, the rows a frame hides above and below, and the
|
|
143
|
+
// path line's separator.
|
|
144
|
+
frameTopLeft: Object.freeze(["╭", "+"]),
|
|
145
|
+
frameTopRight: Object.freeze(["╮", "+"]),
|
|
146
|
+
frameBottomLeft: Object.freeze(["╰", "+"]),
|
|
147
|
+
frameBottomRight: Object.freeze(["╯", "+"]),
|
|
148
|
+
cursor: Object.freeze(["›", ">"]),
|
|
149
|
+
moreAbove: Object.freeze(["↑", "^"]),
|
|
150
|
+
moreBelow: Object.freeze(["↓", "v"]),
|
|
140
151
|
});
|
|
141
152
|
|
|
142
153
|
// The other names a glyph answers to: the spec's shared rows (fail / issue,
|
|
@@ -160,6 +171,8 @@ export const GLYPH_ALIASES = Object.freeze({
|
|
|
160
171
|
// The question rail's checklist cursor: the row it is on is marked by a
|
|
161
172
|
// glyph, not by colour alone (contract 3).
|
|
162
173
|
pointer: "transition",
|
|
174
|
+
// The menu's path line: Settings › Agents · Claude Code › critic.
|
|
175
|
+
pathSeparator: "cursor",
|
|
163
176
|
});
|
|
164
177
|
|
|
165
178
|
// The spinner (presentation spec contract 4): braille frames, one every 80 ms.
|
|
@@ -1090,6 +1103,160 @@ export function openRail({
|
|
|
1090
1103
|
};
|
|
1091
1104
|
}
|
|
1092
1105
|
|
|
1106
|
+
// A full screen for the settings menu (presentation spec contract 14): the
|
|
1107
|
+
// terminal's alternate screen, raw keys and a hidden cursor for the screen's
|
|
1108
|
+
// whole life, each draw from the top-left, and the terminal restored on
|
|
1109
|
+
// every path — close(), `exit`, SIGTERM / SIGHUP / SIGINT — as the rail
|
|
1110
|
+
// restores it. What the screen showed is gone from the scrollback when it
|
|
1111
|
+
// closes; the caller prints what should stay after that.
|
|
1112
|
+
//
|
|
1113
|
+
// screen.size() → { columns, rows }
|
|
1114
|
+
// screen.draw(lines) → the lines, each line's rest cleared, then the rest
|
|
1115
|
+
// screen.next() → the next event: a key name (up, down, left, right,
|
|
1116
|
+
// space, enter, escape, backspace, cancel), { char },
|
|
1117
|
+
// "resize", or what wake() was given
|
|
1118
|
+
// screen.wake(event) → an event for next(), from outside the keys (a
|
|
1119
|
+
// background read that answered)
|
|
1120
|
+
// screen.drain(turns) → the keys queued so far dropped, and those arriving in
|
|
1121
|
+
// the next `turns` turns of the loop (the review screen)
|
|
1122
|
+
// screen.close() → the terminal is the caller's again
|
|
1123
|
+
//
|
|
1124
|
+
// Ctrl+C and the end of input are "cancel": an answer, never process.exit.
|
|
1125
|
+
export const ALT_ON = "\x1b[?1049h";
|
|
1126
|
+
export const ALT_OFF = "\x1b[?1049l";
|
|
1127
|
+
export function openScreen({
|
|
1128
|
+
stdin = process.stdin,
|
|
1129
|
+
stdout = process.stdout,
|
|
1130
|
+
caps: c = caps(stdout),
|
|
1131
|
+
proc = process,
|
|
1132
|
+
escapeMs = ESCAPE_MS,
|
|
1133
|
+
} = {}) {
|
|
1134
|
+
if (!railAvailable(stdin, c))
|
|
1135
|
+
throw new Error("no screen: stdin must be a terminal with setRawMode and stdout a live one (railAvailable)");
|
|
1136
|
+
const write = (s) => stdout.write(s);
|
|
1137
|
+
const queue = [];
|
|
1138
|
+
let waiter = null;
|
|
1139
|
+
const push = (e) => {
|
|
1140
|
+
queue.push(e);
|
|
1141
|
+
if (waiter) {
|
|
1142
|
+
const w = waiter;
|
|
1143
|
+
waiter = null;
|
|
1144
|
+
w();
|
|
1145
|
+
}
|
|
1146
|
+
};
|
|
1147
|
+
// A lone Esc is reported after the escape timeout as { name: "escape",
|
|
1148
|
+
// meta: true }: it is ←, never a modifier (the rail reads it the same way).
|
|
1149
|
+
const nameOf = (str, k = {}) => {
|
|
1150
|
+
if (k.ctrl && k.name === "c") return "cancel";
|
|
1151
|
+
if (k.name === "escape") return "escape";
|
|
1152
|
+
if (k.ctrl || k.meta) return null;
|
|
1153
|
+
if (["up", "down", "left", "right", "space", "escape", "backspace"].includes(k.name)) return k.name;
|
|
1154
|
+
if (isEnter(k)) return "enter";
|
|
1155
|
+
return printable({ ...k, str }) ? { char: str } : null;
|
|
1156
|
+
};
|
|
1157
|
+
// While a drain lasts, keys are dropped as they arrive (drain() below).
|
|
1158
|
+
let dropping = false;
|
|
1159
|
+
const onKey = (str, key) => {
|
|
1160
|
+
const e = nameOf(str, key || {});
|
|
1161
|
+
if (e && !(dropping && e !== "cancel")) push(e);
|
|
1162
|
+
};
|
|
1163
|
+
const onEnd = () => push("cancel");
|
|
1164
|
+
const onResize = () => push("resize");
|
|
1165
|
+
let open = true;
|
|
1166
|
+
const restore = () => {
|
|
1167
|
+
try {
|
|
1168
|
+
stdin.setRawMode(false);
|
|
1169
|
+
} catch {}
|
|
1170
|
+
try {
|
|
1171
|
+
write(`${SHOW_CURSOR}${ALT_OFF}`);
|
|
1172
|
+
} catch {}
|
|
1173
|
+
};
|
|
1174
|
+
const onExit = () => restore();
|
|
1175
|
+
const onSignal = {};
|
|
1176
|
+
const release = () => {
|
|
1177
|
+
proc.removeListener("exit", onExit);
|
|
1178
|
+
for (const [sig, f] of Object.entries(onSignal)) proc.removeListener(sig, f);
|
|
1179
|
+
};
|
|
1180
|
+
for (const sig of ["SIGTERM", "SIGHUP", "SIGINT"]) {
|
|
1181
|
+
onSignal[sig] = () => {
|
|
1182
|
+
if (open) restore();
|
|
1183
|
+
open = false;
|
|
1184
|
+
release();
|
|
1185
|
+
try {
|
|
1186
|
+
proc.kill(proc.pid, sig);
|
|
1187
|
+
} catch {}
|
|
1188
|
+
};
|
|
1189
|
+
}
|
|
1190
|
+
proc.once("exit", onExit);
|
|
1191
|
+
for (const [sig, f] of Object.entries(onSignal)) proc.on(sig, f);
|
|
1192
|
+
emitKeypressEvents(stdin, { escapeCodeTimeout: escapeMs });
|
|
1193
|
+
stdin.on("keypress", onKey);
|
|
1194
|
+
stdin.on("end", onEnd);
|
|
1195
|
+
stdin.on("error", onEnd);
|
|
1196
|
+
if (typeof stdout.on === "function") stdout.on("resize", onResize);
|
|
1197
|
+
if (stdin.readableEnded) queue.push("cancel");
|
|
1198
|
+
try {
|
|
1199
|
+
stdin.setRawMode(true);
|
|
1200
|
+
write(`${ALT_ON}${HIDE_CURSOR}`);
|
|
1201
|
+
stdin.resume();
|
|
1202
|
+
} catch (e) {
|
|
1203
|
+
restore();
|
|
1204
|
+
release();
|
|
1205
|
+
throw e;
|
|
1206
|
+
}
|
|
1207
|
+
return {
|
|
1208
|
+
size: () => ({
|
|
1209
|
+
columns: Number(stdout.columns) > 0 ? Number(stdout.columns) : c.columns || 100,
|
|
1210
|
+
rows: Number(stdout.rows) > 0 ? Number(stdout.rows) : 24,
|
|
1211
|
+
}),
|
|
1212
|
+
// Each line after an erase of its row, at most `rows` of them, and no
|
|
1213
|
+
// newline after the last, so the alternate screen never scrolls.
|
|
1214
|
+
draw(lines) {
|
|
1215
|
+
if (!open) return;
|
|
1216
|
+
const rows = Number(stdout.rows) > 0 ? Number(stdout.rows) : 24;
|
|
1217
|
+
write(
|
|
1218
|
+
`\x1b[H${lines
|
|
1219
|
+
.slice(0, rows)
|
|
1220
|
+
.map((l) => `\x1b[2K${l}`)
|
|
1221
|
+
.join("\r\n")}\x1b[J`,
|
|
1222
|
+
);
|
|
1223
|
+
},
|
|
1224
|
+
// The keys queued so far dropped, and those that arrive in the next
|
|
1225
|
+
// `turns` turns of the event loop too: what was in the terminal's buffer
|
|
1226
|
+
// when the review was drawn was typed before it was seen, as drainInput
|
|
1227
|
+
// reasons for the line-mode confirm. Ctrl+C is never dropped.
|
|
1228
|
+
drain: (turns = 0) => {
|
|
1229
|
+
for (let k = queue.length - 1; k >= 0; k--) if (queue[k] !== "cancel") queue.splice(k, 1);
|
|
1230
|
+
if (!turns) return;
|
|
1231
|
+
dropping = true;
|
|
1232
|
+
let n = 0;
|
|
1233
|
+
const step = () => (++n >= turns ? (dropping = false) : setImmediate(step));
|
|
1234
|
+
setImmediate(step);
|
|
1235
|
+
},
|
|
1236
|
+
next: () =>
|
|
1237
|
+
queue.length
|
|
1238
|
+
? Promise.resolve(queue.shift())
|
|
1239
|
+
: new Promise((settle) => {
|
|
1240
|
+
waiter = () => settle(queue.shift());
|
|
1241
|
+
}),
|
|
1242
|
+
wake: (e) => push(e),
|
|
1243
|
+
close() {
|
|
1244
|
+
if (!open) return;
|
|
1245
|
+
open = false;
|
|
1246
|
+
stdin.removeListener("keypress", onKey);
|
|
1247
|
+
stdin.removeListener("end", onEnd);
|
|
1248
|
+
stdin.removeListener("error", onEnd);
|
|
1249
|
+
if (typeof stdout.removeListener === "function") stdout.removeListener("resize", onResize);
|
|
1250
|
+
queue.length = 0;
|
|
1251
|
+
try {
|
|
1252
|
+
stdin.pause();
|
|
1253
|
+
} catch {}
|
|
1254
|
+
restore();
|
|
1255
|
+
release();
|
|
1256
|
+
},
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1093
1260
|
// What was typed ahead of a line-mode question, discarded (the setup story,
|
|
1094
1261
|
// rule 2: the rail's raw mode ends at `└`, and the confirm after it is
|
|
1095
1262
|
// askLine's). Keys typed while the run fetched, read the registry and drew
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- projectstore:agents
|
|
1
|
+
<!-- projectstore:agents v5 (managed by projectstore — edit outside markers) -->
|
|
2
2
|
## projectstore agents
|
|
3
3
|
|
|
4
4
|
- **A feature-sized request opens a vault artifact before it opens an editor.**
|
|
@@ -11,10 +11,12 @@
|
|
|
11
11
|
harness-level instruction contradicts this block, say so and ask which wins.
|
|
12
12
|
Resolving it silently is how the contradiction becomes invisible to the person
|
|
13
13
|
who could have settled it.
|
|
14
|
-
- When spawning any agent below, resolve its model from
|
|
15
|
-
`.projectstore/harness/<harness>.json` → `agents.per_agent.<name>.model ?? agents.default.model
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
- When spawning any agent below, resolve its model and its effort from
|
|
15
|
+
`.projectstore/harness/<harness>.json` → `agents.per_agent.<name>.model ?? agents.default.model`
|
|
16
|
+
and `agents.per_agent.<name>.effort ?? agents.default.effort`, where `<name>` is
|
|
17
|
+
the **bare** agent name (`critic` for `projectstore:critic`), and pass them as
|
|
18
|
+
the spawn's model and effort parameters, the effort only when the spawn offers
|
|
19
|
+
one. No key — pass nothing.
|
|
18
20
|
- After authoring or revising any vault artifact (ADR/research/epic/story) or
|
|
19
21
|
design proposal: run the `projectstore:critic` agent on it before treating it final.
|
|
20
22
|
- Before implementing an epic/story: consult `projectstore:planner` — it plans
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projectstore-claude",
|
|
3
|
-
"version": "0.30.
|
|
3
|
+
"version": "0.30.3",
|
|
4
4
|
"description": "projectstore for Claude Code: the core pinned and bundled, the harness fixed. A release artifact; the way in is npx projectstore setup",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"projectstore",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"README.md"
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"projectstore": "=0.30.
|
|
40
|
+
"projectstore": "=0.30.3"
|
|
41
41
|
},
|
|
42
42
|
"bundleDependencies": [
|
|
43
43
|
"projectstore"
|