@ericrisco/rsc 4.0.0 → 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 +3 -2
- package/package.json +1 -1
- package/scripts/lib/review-ledger.js +4 -2
- package/scripts/lib/risk.js +6 -3
- package/scripts/rsc.js +16 -3
- package/scripts/spec-gate.js +13 -3
- package/skills/asdd/SKILL.md +35 -11
- package/skills/asdd/evals/cases.yaml +1 -1
- package/skills/clarify/SKILL.md +12 -1
- package/skills/constitution/SKILL.md +9 -8
- package/skills/constitution/evals/cases.yaml +1 -1
- package/skills/debug/SKILL.md +2 -2
- package/skills/implement/SKILL.md +45 -43
- package/skills/implement/references/per-task-review.md +11 -2
- package/skills/implement/scripts/task-brief +37 -22
- package/skills/plan/SKILL.md +1 -1
- package/skills/plan/evals/cases.yaml +1 -1
- package/skills/plan/references/plan-template.md +2 -2
- package/skills/review/SKILL.md +31 -19
- package/skills/sdd-init/SKILL.md +6 -4
- package/skills/ship/SKILL.md +25 -17
- package/skills/specify/SKILL.md +11 -9
- package/skills/specify/evals/cases.yaml +1 -1
- package/skills/specify/references/eliciting-requirements.md +1 -1
- package/skills/specify/references/spec-template.md +1 -1
- package/skills/tasks/evals/cases.yaml +1 -1
- package/skills/verify/SKILL.md +5 -4
- package/skills/verify/evals/cases.yaml +1 -1
- package/skills/verify/references/generic-gate.md +43 -0
- package/targets/branch-guard.mjs +12 -3
- package/targets/sello.mjs +8 -2
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 }) {
|
package/targets/sello.mjs
CHANGED
|
@@ -45,6 +45,11 @@ export const SELLO_STATE_PATHS = [
|
|
|
45
45
|
'.rsc/automation-gaps.md', '.rsc/review-ledger.jsonl',
|
|
46
46
|
];
|
|
47
47
|
|
|
48
|
+
// Worktrees nested inside the project (the assistant's native `.claude/worktrees/`, rsc's own
|
|
49
|
+
// `.worktrees/`) are other checkouts, not part of this change. Untracked, they showed up as one
|
|
50
|
+
// `.claude/…` path, scored as harness — tier 2 for every task of a run that used isolation.
|
|
51
|
+
export const NESTED_WORKTREES = /^(?:\.claude\/worktrees|\.worktrees)(?:\/|$)/;
|
|
52
|
+
|
|
48
53
|
export function selloPaths(root) {
|
|
49
54
|
return {
|
|
50
55
|
config: join(root, '.rsc', 'sello-config.json'),
|
|
@@ -241,7 +246,8 @@ export function computeCandidate(rawRoot, cfg = null) {
|
|
|
241
246
|
|
|
242
247
|
const names = new Set();
|
|
243
248
|
for (const n of nulList(git(root, 'diff', '--name-only', '-z', base))) names.add(n);
|
|
244
|
-
|
|
249
|
+
// Untracked nested worktrees are other checkouts; committed paths under them are part of the change.
|
|
250
|
+
for (const n of nulList(git(root, 'ls-files', '--others', '--exclude-standard', '-z'))) if (!NESTED_WORKTREES.test(n)) names.add(n);
|
|
245
251
|
for (const p of SELLO_STATE_PATHS) names.delete(p);
|
|
246
252
|
|
|
247
253
|
const files = {};
|
|
@@ -266,7 +272,7 @@ export function computeCandidate(rawRoot, cfg = null) {
|
|
|
266
272
|
// Untracked files never appear in numstat, so a fix hidden in a new file would
|
|
267
273
|
// cost zero budget. Count their lines.
|
|
268
274
|
for (const n of nulList(git(root, 'ls-files', '--others', '--exclude-standard', '-z'))) {
|
|
269
|
-
if (SELLO_STATE_PATHS.includes(n) || numstat[n] !== undefined) continue;
|
|
275
|
+
if (SELLO_STATE_PATHS.includes(n) || NESTED_WORKTREES.test(n) || numstat[n] !== undefined) continue;
|
|
270
276
|
try {
|
|
271
277
|
const st = lstatSync(join(root, n));
|
|
272
278
|
if (st.isFile()) numstat[n] = readFileSync(join(root, n), 'utf8').split('\n').length;
|