@brainervirus/workit-cursor 8.29.1 → 8.29.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/.cursor-plugin/plugin.json +1 -1
- package/dist/cursor-session-start.js +74 -28
- package/dist/workit-hook.js +67 -23
- package/package.json +3 -3
|
@@ -15689,13 +15689,13 @@ Autonomy contract:
|
|
|
15689
15689
|
or an unresolved blocker; report open gaps and uncertain workers.
|
|
15690
15690
|
- No endpoint named: stop at a local commit on a policy-compliant branch and
|
|
15691
15691
|
state the next command. If the request implies delivery (fix, implement,
|
|
15692
|
-
ship), go to the effective endpoint in \`workit grant show\`: \`pr\`
|
|
15693
|
-
the PR; \`green\` babysits it
|
|
15694
|
-
never merging; \`merged\`
|
|
15695
|
-
|
|
15696
|
-
|
|
15697
|
-
around grant_required. Release: \`workit release
|
|
15698
|
-
\`finish\`; \`publish\` if asked.
|
|
15692
|
+
ship), go to the effective endpoint in \`workit grant show\`: \`pr\` stops
|
|
15693
|
+
at the PR even with merge granted; \`green\` babysits it (workit-ship) to
|
|
15694
|
+
merge-ready, never merging; \`merged\` lands it with \`workit pr merge\`.
|
|
15695
|
+
Only the user raises a grant or the endpoint, in a terminal outside the agent
|
|
15696
|
+
host (\`workit grant set <ws> defaultEndpoint=merged\`); never edit
|
|
15697
|
+
workspaces.json or route around grant_required. Release: \`workit release
|
|
15698
|
+
start <v>\`, commits, \`finish\`; \`publish\` if asked.
|
|
15699
15699
|
- Ask only for a product or preference choice, or for authority you lack, with
|
|
15700
15700
|
your recommended answer. Facts are yours: read, run or prototype.
|
|
15701
15701
|
- Label claims measured (run and seen this session), inferred, or guess.
|
|
@@ -15709,9 +15709,8 @@ Autonomy contract:
|
|
|
15709
15709
|
is not evidence of a requested remote push. Before reporting delivery,
|
|
15710
15710
|
reconcile every requested item and observe it (\`workit verify-delivery\`).
|
|
15711
15711
|
|
|
15712
|
-
|
|
15713
|
-
|
|
15714
|
-
else \`npx -y @brainervirus/workit-cli\`).
|
|
15712
|
+
Read-only git and gh run raw; mutations go through workit verbs
|
|
15713
|
+
(\`workit git|pr|ci|check|help\`; else \`npx -y @brainervirus/workit-cli\`).
|
|
15715
15714
|
Other checkout: \`workit <verb> --cwd <dir> …\` (verb first: host rules match it); one workit
|
|
15716
15715
|
verb per shell call, never \`cd <dir> && workit\`. zsh-safe: no \`echo =====\`
|
|
15717
15716
|
(\`printf '%s\\n' ---\`), quote globs and URLs, no variable named \`status\` or \`path\`.
|
|
@@ -17699,12 +17698,36 @@ ${invariantBootstrap()}${compact}${offer ? `
|
|
|
17699
17698
|
${offer}` : ""}${options.addendum ? `
|
|
17700
17699
|
${options.addendum}` : ""}
|
|
17701
17700
|
</workit-contract>`;
|
|
17701
|
+
}, checkoutAt = (cwd) => {
|
|
17702
|
+
for (let dir = path20.resolve(cwd);; dir = path20.dirname(dir)) {
|
|
17703
|
+
const dotGit = path20.join(dir, ".git");
|
|
17704
|
+
if (fs15.existsSync(dotGit)) {
|
|
17705
|
+
const admin = fs15.statSync(dotGit).isFile() ? path20.resolve(dir, /^gitdir:\s*(.+)$/mu.exec(fs15.readFileSync(dotGit, "utf8"))?.[1]?.trim() ?? "") : dotGit;
|
|
17706
|
+
const head = fs15.readFileSync(path20.join(admin, "HEAD"), "utf8").trim();
|
|
17707
|
+
return { root: dir, branch: /^ref: refs\/heads\/(.+)$/u.exec(head)?.[1] ?? null };
|
|
17708
|
+
}
|
|
17709
|
+
if (path20.dirname(dir) === dir)
|
|
17710
|
+
return null;
|
|
17711
|
+
}
|
|
17712
|
+
}, whereLine = (cwd) => {
|
|
17713
|
+
try {
|
|
17714
|
+
const checkout = checkoutAt(cwd);
|
|
17715
|
+
if (!checkout)
|
|
17716
|
+
return null;
|
|
17717
|
+
const allowed = branchPolicySnapshotFor(cwd).namePolicy.allowed;
|
|
17718
|
+
const kinds = allowed.some((pattern) => pattern.source === "^.*$") ? "any" : allowedKinds(allowed).join(", ") || "see `workit help git`";
|
|
17719
|
+
const place = checkout.root === path20.resolve(cwd) ? "" : ` in ${checkout.root}`;
|
|
17720
|
+
return `cwd ${cwd}${place} on ${checkout.branch ?? "detached HEAD"}; branch kinds: ${kinds}`;
|
|
17721
|
+
} catch {
|
|
17722
|
+
return null;
|
|
17723
|
+
}
|
|
17702
17724
|
}, turnContextText = (input, descriptor) => {
|
|
17703
17725
|
try {
|
|
17704
17726
|
const text = sessionCompactContext(new TaskStore(input.cwd), { host: input.host, handle: input.session.id }, hookOperationContext(input, descriptor), descriptor.context.task);
|
|
17705
17727
|
if (text === MIGRATION_PENDING_NOTE)
|
|
17706
17728
|
return text;
|
|
17707
|
-
return text ? `<workit-task-context>${text
|
|
17729
|
+
return text ? `<workit-task-context>${[whereLine(input.cwd), text].filter(Boolean).join(`
|
|
17730
|
+
`)}</workit-task-context>` : null;
|
|
17708
17731
|
} catch {
|
|
17709
17732
|
return null;
|
|
17710
17733
|
}
|
|
@@ -17770,6 +17793,7 @@ ${options.addendum}` : ""}
|
|
|
17770
17793
|
clearTurnDigest(file);
|
|
17771
17794
|
};
|
|
17772
17795
|
var init_context = __esm(() => {
|
|
17796
|
+
init_branch();
|
|
17773
17797
|
init_methods();
|
|
17774
17798
|
init_paths();
|
|
17775
17799
|
init_task_contract();
|
|
@@ -19440,7 +19464,6 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
|
|
|
19440
19464
|
case "pr-create":
|
|
19441
19465
|
return `workit: prefer ${quote("workit pr create --fill")} (or --title/--body): it records the PR the merge gate checks.`;
|
|
19442
19466
|
case "pr-read":
|
|
19443
|
-
return `workit: ${quote("workit pr status")} shows the PR, its checks and the verdict state; ${quote("workit ci wait")} waits for checks.`;
|
|
19444
19467
|
case "merge":
|
|
19445
19468
|
return null;
|
|
19446
19469
|
}
|
|
@@ -22511,6 +22534,31 @@ var init_worktree_confine = __esm(() => {
|
|
|
22511
22534
|
CONFIG_VALUE = /^(?:--file|-f|--blob|--type|--default|--comment)$/;
|
|
22512
22535
|
});
|
|
22513
22536
|
|
|
22537
|
+
// packages/workit-core/src/hooks/steering.ts
|
|
22538
|
+
var ROLES, workitRole = (descriptor, agentType) => {
|
|
22539
|
+
const prefix = descriptor.subagents.agentPrefix;
|
|
22540
|
+
const name = agentType.startsWith(prefix) ? agentType.slice(prefix.length) : "";
|
|
22541
|
+
return Object.hasOwn(ROLES, name) ? ROLES[name] : null;
|
|
22542
|
+
}, CLAUDE_WORKTREE, roleSteering = (role, isolated) => ({
|
|
22543
|
+
role,
|
|
22544
|
+
isolated,
|
|
22545
|
+
git: role === "implementer" ? isolated ? "plain" : "workit" : null,
|
|
22546
|
+
nudges: role === null
|
|
22547
|
+
}), agentSteering = (descriptor, cwd, agent) => {
|
|
22548
|
+
const role = agent.type ? workitRole(descriptor, agent.type) : null;
|
|
22549
|
+
const isolated = descriptor.subagents.worktreeIsolation === "native" && (role === "implementer" ? hostIsolated(cwd, agent.id) : CLAUDE_WORKTREE.test(cwd));
|
|
22550
|
+
return roleSteering(role, isolated);
|
|
22551
|
+
};
|
|
22552
|
+
var init_steering = __esm(() => {
|
|
22553
|
+
init_worktree_confine();
|
|
22554
|
+
ROLES = {
|
|
22555
|
+
implementer: "implementer",
|
|
22556
|
+
verifier: "judge",
|
|
22557
|
+
reviewer: "judge"
|
|
22558
|
+
};
|
|
22559
|
+
CLAUDE_WORKTREE = /[\\/]\.claude[\\/]worktrees[\\/]/;
|
|
22560
|
+
});
|
|
22561
|
+
|
|
22514
22562
|
// packages/workit-core/src/hooks/handle.ts
|
|
22515
22563
|
function handleHook(input, deps) {
|
|
22516
22564
|
const decision = decide(input, deps);
|
|
@@ -22596,7 +22644,12 @@ function decide(input, deps) {
|
|
|
22596
22644
|
} : NONE6;
|
|
22597
22645
|
if (descriptor.transport !== "hook-process")
|
|
22598
22646
|
return rewritten(null);
|
|
22599
|
-
const
|
|
22647
|
+
const { nudges } = agentSteering(descriptor, input.cwd, {
|
|
22648
|
+
type: input.session.agentType,
|
|
22649
|
+
id: input.session.agentId
|
|
22650
|
+
});
|
|
22651
|
+
const nudge = canDeny ? rawGitPre(input, event.command, { nudge: nudges }) : NONE6;
|
|
22652
|
+
const nudged = withContextLine(withContextLine(nudge, aside), shipNudge(input, event.command));
|
|
22600
22653
|
if (!lease)
|
|
22601
22654
|
return cwdCommand && nudged.kind !== "deny" ? rewritten(nudged.kind === "context" ? nudged.text : null) : nudged;
|
|
22602
22655
|
return rewritten([rewriteNote(lease), nudged.kind === "context" ? nudged.text : null].filter(Boolean).join(`
|
|
@@ -22644,22 +22697,20 @@ function decide(input, deps) {
|
|
|
22644
22697
|
return NONE6;
|
|
22645
22698
|
}
|
|
22646
22699
|
}
|
|
22647
|
-
var usable2 = (value) => value === "native" || value === "partial", NONE6, resendsOnChange = (descriptor) => descriptor.context.turnResend === "on-change" && usable2(descriptor.context.perTurn), offered,
|
|
22648
|
-
const prefix = descriptor.subagents.agentPrefix;
|
|
22649
|
-
const name = agentType.startsWith(prefix) ? agentType.slice(prefix.length) : "";
|
|
22650
|
-
return Object.hasOwn(ROLES, name) ? ROLES[name] : null;
|
|
22651
|
-
}, implementerAgent = (input, descriptor) => Boolean(input.session.agentId) && input.session.agentType !== null && workitRole(descriptor, input.session.agentType) === "implementer", subagentSession = (session, agentId) => [session, agentId].filter((part) => Boolean(part)).join(":").replace(/[^A-Za-z0-9_.:@/+-]/g, "-").slice(0, 128), CLAUDE_WORKTREE, isolatedGit = (cwd) => `Run git as plain, separate commands inside your worktree (\`git switch -c <branch> <base>\`, ${workspaceTrailers(cwd).enabled ? '`git commit --trailer "Workit-Session=<your session>"`, `git push`; `workit doctor --fix` can install a prepare-commit-msg hook that adds the trailer' : "`git commit` (this workspace sets trailers: false: add no Workit-Session trailer), `git push`"}; add Co-Authored-By with \`git commit --trailer\` in the same commit, never by amending), never \`workit git …\`: Claude Code's worktree isolation refuses a command that wraps git and cannot be turned off (https://code.claude.com/docs/en/worktrees#how-claude-code-enforces-isolation). Never dodge that check by renaming or re-wrapping git. Use workit for the non-git verbs (\`workit check\`, \`workit ledger\`, \`workit pr\`).`, subagentStartText = (input, descriptor, event) => {
|
|
22700
|
+
var usable2 = (value) => value === "native" || value === "partial", NONE6, resendsOnChange = (descriptor) => descriptor.context.turnResend === "on-change" && usable2(descriptor.context.perTurn), offered, implementerAgent = (input, descriptor) => Boolean(input.session.agentId) && input.session.agentType !== null && workitRole(descriptor, input.session.agentType) === "implementer", subagentSession = (session, agentId) => [session, agentId].filter((part) => Boolean(part)).join(":").replace(/[^A-Za-z0-9_.:@/+-]/g, "-").slice(0, 128), isolatedGit = (cwd) => `Run git as plain, separate commands inside your worktree (\`git switch -c <branch> <base>\`, ${workspaceTrailers(cwd).enabled ? '`git commit --trailer "Workit-Session=<your session>"`, `git push`; `workit doctor --fix` can install a prepare-commit-msg hook that adds the trailer' : "`git commit` (this workspace sets trailers: false: add no Workit-Session trailer), `git push`"}; add Co-Authored-By with \`git commit --trailer\` in the same commit, never by amending), never \`workit git …\`: Claude Code's worktree isolation refuses a command that wraps git and cannot be turned off (https://code.claude.com/docs/en/worktrees#how-claude-code-enforces-isolation). Never dodge that check by renaming or re-wrapping git. Use workit for the non-git verbs (\`workit check\`, \`workit ledger\`, \`workit pr\`).`, subagentStartText = (input, descriptor, event) => {
|
|
22652
22701
|
const session = input.session.id ?? null;
|
|
22653
|
-
const role =
|
|
22702
|
+
const { role, isolated, git } = agentSteering(descriptor, input.cwd, {
|
|
22703
|
+
type: event.agentType,
|
|
22704
|
+
id: event.agentId
|
|
22705
|
+
});
|
|
22654
22706
|
const who = `${descriptor.label} subagent ${event.agentId} (${event.agentType})`;
|
|
22655
|
-
const isolated = descriptor.subagents.worktreeIsolation === "native" && (role === "implementer" ? hostIsolated(input.cwd, event.agentId) : CLAUDE_WORKTREE.test(input.cwd));
|
|
22656
22707
|
const guide = role === "implementer" ? branchGuidance(input.cwd) : null;
|
|
22657
|
-
if (
|
|
22708
|
+
if (git === "plain")
|
|
22658
22709
|
return `Workit observed ${who} working in its own git worktree: it may edit and commit there, within its brief's scope. ${isolatedGit(input.cwd)} Plain git is expected here, and the branch name is still policy-checked: a raw \`git switch -c\`, \`git checkout -b\`, \`git branch\` or \`git worktree add -b\` onto a protected or non-compliant name is denied, so use a policy-compliant branch.${guide ? ` ${guide}` : " (e.g. feature/<slug>)"} Never record a verdict on your own work. Never push, open a PR, or merge unless the brief asks for it.`;
|
|
22659
22710
|
if (isolated)
|
|
22660
22711
|
return `${isolatedGit(input.cwd)}
|
|
22661
22712
|
${subagentStartText({ ...input, cwd: "" }, descriptor, event)}`;
|
|
22662
|
-
if (
|
|
22713
|
+
if (git === "workit")
|
|
22663
22714
|
return `Workit observed ${who} as an implementer: it edits and commits only in its own git worktree, the one its brief names (the lead makes it with \`workit fanout worktree create <slice>\` before spawning), never in the lead's checkout, within its brief's scope. Workit binds it to the first Workit worktree it changes: from then on an edit or a mutating git command outside that worktree is denied, and before then so is one outside every Workit worktree. Run Workit against the worktree one verb per call, never \`cd … &&\` chains or \`$VAR\` paths: \`workit git --cwd <worktree> commit -m "<message>" -- <paths>\`, \`workit check --cwd <worktree> <name>\` (verb first, so host allow rules match). The worktree is on the brief's branch once the lead made it; otherwise switch with \`workit git --cwd <worktree> branch <branch> --base <base>\` (or \`--kind <kind> --slug <slug>\`, which picks the base); branch policy hooks still deny protected or non-compliant branches, raw git included.${guide ? ` ${guide}` : " (e.g. feature/<slug>)"} Never record a verdict on your own work. Never push, open a PR, or merge unless the brief asks for it.`;
|
|
22664
22715
|
const readOnly = `Workit observed ${who} as read-only/agent-guided.`;
|
|
22665
22716
|
if (role !== "judge" || !event.agentId)
|
|
@@ -22722,14 +22773,9 @@ var init_handle = __esm(() => {
|
|
|
22722
22773
|
init_live_session();
|
|
22723
22774
|
init_write_gate();
|
|
22724
22775
|
init_worktree_confine();
|
|
22776
|
+
init_steering();
|
|
22725
22777
|
NONE6 = { kind: "none" };
|
|
22726
22778
|
offered = new Set;
|
|
22727
|
-
ROLES = {
|
|
22728
|
-
implementer: "implementer",
|
|
22729
|
-
verifier: "judge",
|
|
22730
|
-
reviewer: "judge"
|
|
22731
|
-
};
|
|
22732
|
-
CLAUDE_WORKTREE = /[\\/]\.claude[\\/]worktrees[\\/]/;
|
|
22733
22779
|
PRE_TOOL = new Set(["shell.pre", "write.pre", "tool.pre"]);
|
|
22734
22780
|
});
|
|
22735
22781
|
|
package/dist/workit-hook.js
CHANGED
|
@@ -15735,13 +15735,13 @@ Autonomy contract:
|
|
|
15735
15735
|
or an unresolved blocker; report open gaps and uncertain workers.
|
|
15736
15736
|
- No endpoint named: stop at a local commit on a policy-compliant branch and
|
|
15737
15737
|
state the next command. If the request implies delivery (fix, implement,
|
|
15738
|
-
ship), go to the effective endpoint in \`workit grant show\`: \`pr\`
|
|
15739
|
-
the PR; \`green\` babysits it
|
|
15740
|
-
never merging; \`merged\`
|
|
15741
|
-
|
|
15742
|
-
|
|
15743
|
-
around grant_required. Release: \`workit release
|
|
15744
|
-
\`finish\`; \`publish\` if asked.
|
|
15738
|
+
ship), go to the effective endpoint in \`workit grant show\`: \`pr\` stops
|
|
15739
|
+
at the PR even with merge granted; \`green\` babysits it (workit-ship) to
|
|
15740
|
+
merge-ready, never merging; \`merged\` lands it with \`workit pr merge\`.
|
|
15741
|
+
Only the user raises a grant or the endpoint, in a terminal outside the agent
|
|
15742
|
+
host (\`workit grant set <ws> defaultEndpoint=merged\`); never edit
|
|
15743
|
+
workspaces.json or route around grant_required. Release: \`workit release
|
|
15744
|
+
start <v>\`, commits, \`finish\`; \`publish\` if asked.
|
|
15745
15745
|
- Ask only for a product or preference choice, or for authority you lack, with
|
|
15746
15746
|
your recommended answer. Facts are yours: read, run or prototype.
|
|
15747
15747
|
- Label claims measured (run and seen this session), inferred, or guess.
|
|
@@ -15755,9 +15755,8 @@ Autonomy contract:
|
|
|
15755
15755
|
is not evidence of a requested remote push. Before reporting delivery,
|
|
15756
15756
|
reconcile every requested item and observe it (\`workit verify-delivery\`).
|
|
15757
15757
|
|
|
15758
|
-
|
|
15759
|
-
|
|
15760
|
-
else \`npx -y @brainervirus/workit-cli\`).
|
|
15758
|
+
Read-only git and gh run raw; mutations go through workit verbs
|
|
15759
|
+
(\`workit git|pr|ci|check|help\`; else \`npx -y @brainervirus/workit-cli\`).
|
|
15761
15760
|
Other checkout: \`workit <verb> --cwd <dir> …\` (verb first: host rules match it); one workit
|
|
15762
15761
|
verb per shell call, never \`cd <dir> && workit\`. zsh-safe: no \`echo =====\`
|
|
15763
15762
|
(\`printf '%s\\n' ---\`), quote globs and URLs, no variable named \`status\` or \`path\`.
|
|
@@ -17759,12 +17758,38 @@ ${offer}` : ""}${options.addendum ? `
|
|
|
17759
17758
|
${options.addendum}` : ""}
|
|
17760
17759
|
</workit-contract>`;
|
|
17761
17760
|
};
|
|
17761
|
+
var checkoutAt = (cwd) => {
|
|
17762
|
+
for (let dir = path20.resolve(cwd);; dir = path20.dirname(dir)) {
|
|
17763
|
+
const dotGit = path20.join(dir, ".git");
|
|
17764
|
+
if (fs15.existsSync(dotGit)) {
|
|
17765
|
+
const admin = fs15.statSync(dotGit).isFile() ? path20.resolve(dir, /^gitdir:\s*(.+)$/mu.exec(fs15.readFileSync(dotGit, "utf8"))?.[1]?.trim() ?? "") : dotGit;
|
|
17766
|
+
const head = fs15.readFileSync(path20.join(admin, "HEAD"), "utf8").trim();
|
|
17767
|
+
return { root: dir, branch: /^ref: refs\/heads\/(.+)$/u.exec(head)?.[1] ?? null };
|
|
17768
|
+
}
|
|
17769
|
+
if (path20.dirname(dir) === dir)
|
|
17770
|
+
return null;
|
|
17771
|
+
}
|
|
17772
|
+
};
|
|
17773
|
+
var whereLine = (cwd) => {
|
|
17774
|
+
try {
|
|
17775
|
+
const checkout = checkoutAt(cwd);
|
|
17776
|
+
if (!checkout)
|
|
17777
|
+
return null;
|
|
17778
|
+
const allowed = branchPolicySnapshotFor(cwd).namePolicy.allowed;
|
|
17779
|
+
const kinds = allowed.some((pattern) => pattern.source === "^.*$") ? "any" : allowedKinds(allowed).join(", ") || "see `workit help git`";
|
|
17780
|
+
const place = checkout.root === path20.resolve(cwd) ? "" : ` in ${checkout.root}`;
|
|
17781
|
+
return `cwd ${cwd}${place} on ${checkout.branch ?? "detached HEAD"}; branch kinds: ${kinds}`;
|
|
17782
|
+
} catch {
|
|
17783
|
+
return null;
|
|
17784
|
+
}
|
|
17785
|
+
};
|
|
17762
17786
|
var turnContextText = (input, descriptor) => {
|
|
17763
17787
|
try {
|
|
17764
17788
|
const text = sessionCompactContext(new TaskStore(input.cwd), { host: input.host, handle: input.session.id }, hookOperationContext(input, descriptor), descriptor.context.task);
|
|
17765
17789
|
if (text === MIGRATION_PENDING_NOTE)
|
|
17766
17790
|
return text;
|
|
17767
|
-
return text ? `<workit-task-context>${text
|
|
17791
|
+
return text ? `<workit-task-context>${[whereLine(input.cwd), text].filter(Boolean).join(`
|
|
17792
|
+
`)}</workit-task-context>` : null;
|
|
17768
17793
|
} catch {
|
|
17769
17794
|
return null;
|
|
17770
17795
|
}
|
|
@@ -19654,7 +19679,6 @@ var nudgeFor = (action, host, session) => {
|
|
|
19654
19679
|
case "pr-create":
|
|
19655
19680
|
return `workit: prefer ${quote("workit pr create --fill")} (or --title/--body): it records the PR the merge gate checks.`;
|
|
19656
19681
|
case "pr-read":
|
|
19657
|
-
return `workit: ${quote("workit pr status")} shows the PR, its checks and the verdict state; ${quote("workit ci wait")} waits for checks.`;
|
|
19658
19682
|
case "merge":
|
|
19659
19683
|
return null;
|
|
19660
19684
|
}
|
|
@@ -22739,11 +22763,7 @@ function confineImplementerShell(input, command, dialect = "posix") {
|
|
|
22739
22763
|
return confineImplementer(input, shellMutationTargets(input.cwd, command, dialect, true));
|
|
22740
22764
|
}
|
|
22741
22765
|
|
|
22742
|
-
// packages/workit-core/src/hooks/
|
|
22743
|
-
var usable2 = (value) => value === "native" || value === "partial";
|
|
22744
|
-
var NONE6 = { kind: "none" };
|
|
22745
|
-
var resendsOnChange = (descriptor) => descriptor.context.turnResend === "on-change" && usable2(descriptor.context.perTurn);
|
|
22746
|
-
var offered = new Set;
|
|
22766
|
+
// packages/workit-core/src/hooks/steering.ts
|
|
22747
22767
|
var ROLES = {
|
|
22748
22768
|
implementer: "implementer",
|
|
22749
22769
|
verifier: "judge",
|
|
@@ -22754,22 +22774,41 @@ var workitRole = (descriptor, agentType) => {
|
|
|
22754
22774
|
const name = agentType.startsWith(prefix) ? agentType.slice(prefix.length) : "";
|
|
22755
22775
|
return Object.hasOwn(ROLES, name) ? ROLES[name] : null;
|
|
22756
22776
|
};
|
|
22777
|
+
var CLAUDE_WORKTREE = /[\\/]\.claude[\\/]worktrees[\\/]/;
|
|
22778
|
+
var roleSteering = (role, isolated) => ({
|
|
22779
|
+
role,
|
|
22780
|
+
isolated,
|
|
22781
|
+
git: role === "implementer" ? isolated ? "plain" : "workit" : null,
|
|
22782
|
+
nudges: role === null
|
|
22783
|
+
});
|
|
22784
|
+
var agentSteering = (descriptor, cwd, agent) => {
|
|
22785
|
+
const role = agent.type ? workitRole(descriptor, agent.type) : null;
|
|
22786
|
+
const isolated = descriptor.subagents.worktreeIsolation === "native" && (role === "implementer" ? hostIsolated(cwd, agent.id) : CLAUDE_WORKTREE.test(cwd));
|
|
22787
|
+
return roleSteering(role, isolated);
|
|
22788
|
+
};
|
|
22789
|
+
|
|
22790
|
+
// packages/workit-core/src/hooks/handle.ts
|
|
22791
|
+
var usable2 = (value) => value === "native" || value === "partial";
|
|
22792
|
+
var NONE6 = { kind: "none" };
|
|
22793
|
+
var resendsOnChange = (descriptor) => descriptor.context.turnResend === "on-change" && usable2(descriptor.context.perTurn);
|
|
22794
|
+
var offered = new Set;
|
|
22757
22795
|
var implementerAgent = (input, descriptor) => Boolean(input.session.agentId) && input.session.agentType !== null && workitRole(descriptor, input.session.agentType) === "implementer";
|
|
22758
22796
|
var subagentSession = (session, agentId) => [session, agentId].filter((part) => Boolean(part)).join(":").replace(/[^A-Za-z0-9_.:@/+-]/g, "-").slice(0, 128);
|
|
22759
|
-
var CLAUDE_WORKTREE = /[\\/]\.claude[\\/]worktrees[\\/]/;
|
|
22760
22797
|
var isolatedGit = (cwd) => `Run git as plain, separate commands inside your worktree (\`git switch -c <branch> <base>\`, ${workspaceTrailers(cwd).enabled ? '`git commit --trailer "Workit-Session=<your session>"`, `git push`; `workit doctor --fix` can install a prepare-commit-msg hook that adds the trailer' : "`git commit` (this workspace sets trailers: false: add no Workit-Session trailer), `git push`"}; add Co-Authored-By with \`git commit --trailer\` in the same commit, never by amending), never \`workit git …\`: Claude Code's worktree isolation refuses a command that wraps git and cannot be turned off (https://code.claude.com/docs/en/worktrees#how-claude-code-enforces-isolation). Never dodge that check by renaming or re-wrapping git. Use workit for the non-git verbs (\`workit check\`, \`workit ledger\`, \`workit pr\`).`;
|
|
22761
22798
|
var subagentStartText = (input, descriptor, event) => {
|
|
22762
22799
|
const session = input.session.id ?? null;
|
|
22763
|
-
const role =
|
|
22800
|
+
const { role, isolated, git } = agentSteering(descriptor, input.cwd, {
|
|
22801
|
+
type: event.agentType,
|
|
22802
|
+
id: event.agentId
|
|
22803
|
+
});
|
|
22764
22804
|
const who = `${descriptor.label} subagent ${event.agentId} (${event.agentType})`;
|
|
22765
|
-
const isolated = descriptor.subagents.worktreeIsolation === "native" && (role === "implementer" ? hostIsolated(input.cwd, event.agentId) : CLAUDE_WORKTREE.test(input.cwd));
|
|
22766
22805
|
const guide = role === "implementer" ? branchGuidance(input.cwd) : null;
|
|
22767
|
-
if (
|
|
22806
|
+
if (git === "plain")
|
|
22768
22807
|
return `Workit observed ${who} working in its own git worktree: it may edit and commit there, within its brief's scope. ${isolatedGit(input.cwd)} Plain git is expected here, and the branch name is still policy-checked: a raw \`git switch -c\`, \`git checkout -b\`, \`git branch\` or \`git worktree add -b\` onto a protected or non-compliant name is denied, so use a policy-compliant branch.${guide ? ` ${guide}` : " (e.g. feature/<slug>)"} Never record a verdict on your own work. Never push, open a PR, or merge unless the brief asks for it.`;
|
|
22769
22808
|
if (isolated)
|
|
22770
22809
|
return `${isolatedGit(input.cwd)}
|
|
22771
22810
|
${subagentStartText({ ...input, cwd: "" }, descriptor, event)}`;
|
|
22772
|
-
if (
|
|
22811
|
+
if (git === "workit")
|
|
22773
22812
|
return `Workit observed ${who} as an implementer: it edits and commits only in its own git worktree, the one its brief names (the lead makes it with \`workit fanout worktree create <slice>\` before spawning), never in the lead's checkout, within its brief's scope. Workit binds it to the first Workit worktree it changes: from then on an edit or a mutating git command outside that worktree is denied, and before then so is one outside every Workit worktree. Run Workit against the worktree one verb per call, never \`cd … &&\` chains or \`$VAR\` paths: \`workit git --cwd <worktree> commit -m "<message>" -- <paths>\`, \`workit check --cwd <worktree> <name>\` (verb first, so host allow rules match). The worktree is on the brief's branch once the lead made it; otherwise switch with \`workit git --cwd <worktree> branch <branch> --base <base>\` (or \`--kind <kind> --slug <slug>\`, which picks the base); branch policy hooks still deny protected or non-compliant branches, raw git included.${guide ? ` ${guide}` : " (e.g. feature/<slug>)"} Never record a verdict on your own work. Never push, open a PR, or merge unless the brief asks for it.`;
|
|
22774
22813
|
const readOnly = `Workit observed ${who} as read-only/agent-guided.`;
|
|
22775
22814
|
if (role !== "judge" || !event.agentId)
|
|
@@ -22872,7 +22911,12 @@ function decide(input, deps) {
|
|
|
22872
22911
|
} : NONE6;
|
|
22873
22912
|
if (descriptor.transport !== "hook-process")
|
|
22874
22913
|
return rewritten(null);
|
|
22875
|
-
const
|
|
22914
|
+
const { nudges } = agentSteering(descriptor, input.cwd, {
|
|
22915
|
+
type: input.session.agentType,
|
|
22916
|
+
id: input.session.agentId
|
|
22917
|
+
});
|
|
22918
|
+
const nudge = canDeny ? rawGitPre(input, event.command, { nudge: nudges }) : NONE6;
|
|
22919
|
+
const nudged = withContextLine(withContextLine(nudge, aside), shipNudge(input, event.command));
|
|
22876
22920
|
if (!lease)
|
|
22877
22921
|
return cwdCommand && nudged.kind !== "deny" ? rewritten(nudged.kind === "context" ? nudged.text : null) : nudged;
|
|
22878
22922
|
return rewritten([rewriteNote(lease), nudged.kind === "context" ? nudged.text : null].filter(Boolean).join(`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-cursor",
|
|
3
|
-
"version": "8.29.
|
|
3
|
+
"version": "8.29.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit Cursor plugin — shared MCP transport, native hooks, and sixteen method skills",
|
|
6
6
|
"keywords": [
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"build": "bun scripts/build.ts"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@brainervirus/workit-core": "^8.29.
|
|
50
|
-
"@brainervirus/workit-mcp": "^8.29.
|
|
49
|
+
"@brainervirus/workit-core": "^8.29.2",
|
|
50
|
+
"@brainervirus/workit-mcp": "^8.29.2"
|
|
51
51
|
},
|
|
52
52
|
"engines": {
|
|
53
53
|
"node": ">=24"
|