@ericrisco/rsc 4.0.1 → 4.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/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -258,8 +258,8 @@ each dispatch self-sufficient and make its return machine-checkable:
|
|
|
258
258
|
- **Carry the task, not your context.** Hand the worker its task brief, its **Interfaces** block
|
|
259
259
|
(`Consumes`/`Produces`, exact signatures — from `tasks`), and the plan's **§0 Global Constraints**.
|
|
260
260
|
Anything not in those three is invisible to it. Prefer **file paths over pasted text** —
|
|
261
|
-
`scripts/task-brief <plan> <N>` (N as `1`, `001` or `T001`; reads the `tasks` table row
|
|
262
|
-
`### T1` detail block) and `scripts/review-package` — pasted briefs and diffs stay resident in
|
|
261
|
+
`scripts/task-brief <plan> <N>` (N as `1`, `001` or `T001`; reads the `tasks` table row, its `**T001 — Interfaces**` block and
|
|
262
|
+
any `### T1` detail block) and `scripts/review-package` — pasted briefs and diffs stay resident in
|
|
263
263
|
your context and get re-read every turn.
|
|
264
264
|
- **Native isolation leaves worktrees behind.** A subagent dispatched with worktree isolation
|
|
265
265
|
works in `.claude/worktrees/`. `rsc risk` ignores that folder, but after you cherry-pick the
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
#
|
|
6
6
|
# Two task shapes are read, because `tasks` prescribes a table and older plans used headings:
|
|
7
7
|
# - a table row `| T002 | ... |` → the table's header, its separator and that row;
|
|
8
|
-
# - a heading `### T2 …` / `## T002 …` → the block up to the next ## / ### heading
|
|
8
|
+
# - a heading `### T2 …` / `## T002 …` → the block up to the next ## / ### heading;
|
|
9
|
+
# - a bold block `**T002 — Interfaces**` → that line and what follows up to a blank line.
|
|
9
10
|
# Both are printed when both exist (the row is the contract, the heading its detail).
|
|
10
11
|
# If task N is not found, exits nonzero with a clear message.
|
|
11
12
|
|
|
@@ -42,7 +43,7 @@ esac
|
|
|
42
43
|
|
|
43
44
|
CONTENT="$(awk -v n="$N" '
|
|
44
45
|
function idnum(s) { sub(/^[Tt]/, "", s); return s + 0 }
|
|
45
|
-
BEGIN { n = n + 0; printing = 0; found = 0; head = ""; sep = "" }
|
|
46
|
+
BEGIN { n = n + 0; printing = 0; bold = 0; found = 0; head = ""; sep = "" }
|
|
46
47
|
# Table rows: remember the latest header + separator, print the matching row.
|
|
47
48
|
/^\|/ {
|
|
48
49
|
split($0, cell, "|"); id = cell[2]; gsub(/[[:space:]]/, "", id)
|
|
@@ -52,6 +53,14 @@ CONTENT="$(awk -v n="$N" '
|
|
|
52
53
|
else { head = $0; sep = "" }
|
|
53
54
|
if (!printing) next
|
|
54
55
|
}
|
|
56
|
+
# A bold block `**T004 — Interfaces**` (what `tasks` writes under the table): the line and every
|
|
57
|
+
# line after it up to the first blank one. It is the task-local contract an isolated worker needs.
|
|
58
|
+
bold && /^[[:space:]]*$/ { bold = 0 }
|
|
59
|
+
bold { print; next }
|
|
60
|
+
/^\*\*[Tt][0-9]+/ {
|
|
61
|
+
t = $0; sub(/^\*\*/, "", t); sub(/[^Tt0-9].*$/, "", t)
|
|
62
|
+
if (idnum(t) == n) { bold = 1; found = 1; print ""; print; next }
|
|
63
|
+
}
|
|
55
64
|
/^#{2,3}[[:space:]]/ {
|
|
56
65
|
if (printing) { printing = 0 }
|
|
57
66
|
if (match($0, /^#{2,3}[[:space:]]+[Tt][0-9]+([[:space:](]|-|$)/)) {
|
package/targets/branch-guard.mjs
CHANGED
|
@@ -274,17 +274,26 @@ async function trunkDenial({ root, here, sessionId, self, trunk, policy }) {
|
|
|
274
274
|
const branch = others.length
|
|
275
275
|
? '`git worktree add .worktrees/<branch> -b feat/<what>` and commit inside `.worktrees/<branch>/` (another session is working in this folder)'
|
|
276
276
|
: '`git switch -c feat/<what>` in this same folder, no worktree';
|
|
277
|
-
return `This project keeps its default branch "${trunk}" closed for the agent (it looks complex or in production: ${policy.signals.join(', ')}), so this
|
|
277
|
+
return `This project keeps its default branch "${trunk}" closed for the agent (it looks complex or in production: ${policy.signals.join(', ')}), so this change was not made. ` +
|
|
278
278
|
`Do not choose for the person: ask them in one line whether to open a branch for this change or to unlock "${trunk}". ` +
|
|
279
279
|
`Branch → ${branch}; it reaches "${trunk}" through a pull request. ` +
|
|
280
|
-
'Unlock → only on their explicit answer, `npx @ericrisco/rsc main unlock` (a project decision, saved in .rsc.json), then commit again.'
|
|
280
|
+
'Unlock → only on their explicit answer, `npx @ericrisco/rsc main unlock` (a project decision, saved in .rsc.json), then commit again. ' +
|
|
281
|
+
AUTOPILOT_LANDING;
|
|
281
282
|
}
|
|
282
283
|
|
|
284
|
+
// An autopilot run has nobody to ask, and the 4.0.1 test run read "ask them" as a reason to look for
|
|
285
|
+
// another way in. Landing a finished branch is `ship`'s job, and with the trunk closed it has exactly
|
|
286
|
+
// one legal path per case — this says which, so the denial ends the attempt instead of starting one.
|
|
287
|
+
const AUTOPILOT_LANDING = 'In autopilot (nobody to ask) and landing a finished feature branch: do not merge another way — ' +
|
|
288
|
+
'with a remote, push the branch and open a pull request; without one, park it: write the exact merge command for the person ' +
|
|
289
|
+
'in `02-DOCS/wiki/sdd/progress/<slug>.md` and stop (the `ship` skill, "No remote").';
|
|
290
|
+
|
|
283
291
|
function refDenial({ trunk, policy, how = '`git update-ref` and a forced `git branch`' }) {
|
|
284
292
|
return `This project keeps its default branch "${trunk}" closed for the agent (it looks complex or in production: ${policy.signals.join(', ')}), so "${trunk}" was not moved — ` +
|
|
285
293
|
`${how} land${how.includes(' and ') ? '' : 's'} work on it with no review. ` +
|
|
286
294
|
`Work reaches "${trunk}" through a pull request: push the branch and open one (the \`ship\` skill). ` +
|
|
287
|
-
`Do not choose for the person: if they want "${trunk}" moved by hand, ask them in one line; only on their explicit answer, \`npx @ericrisco/rsc main unlock\` (a project decision, saved in .rsc.json)
|
|
295
|
+
`Do not choose for the person: if they want "${trunk}" moved by hand, ask them in one line; only on their explicit answer, \`npx @ericrisco/rsc main unlock\` (a project decision, saved in .rsc.json). ` +
|
|
296
|
+
AUTOPILOT_LANDING;
|
|
288
297
|
}
|
|
289
298
|
|
|
290
299
|
async function isolationDenial({ root, here, sessionId, self }) {
|