harnery 0.31.6 → 0.33.0
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 +2 -0
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +5 -1
- package/dist/commands/agents.d.ts +0 -9
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +280 -94
- package/dist/commands/browse-session.d.ts +21 -0
- package/dist/commands/browse-session.d.ts.map +1 -0
- package/dist/commands/browse-session.js +157 -0
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +205 -37
- package/dist/commands/checkpoint.js +1 -1
- package/dist/commands/claude-desktop.d.ts +2 -2
- package/dist/commands/claude-desktop.d.ts.map +1 -1
- package/dist/commands/claude-desktop.js +74 -3
- package/dist/commands/deinit.d.ts.map +1 -1
- package/dist/commands/deinit.js +4 -0
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +40 -0
- package/dist/commands/doctor.d.ts +4 -2
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +141 -19
- package/dist/commands/init.d.ts +2 -2
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +26 -5
- package/dist/commands/instructions.d.ts +4 -0
- package/dist/commands/instructions.d.ts.map +1 -0
- package/dist/commands/instructions.js +100 -0
- package/dist/commands/presence.d.ts.map +1 -1
- package/dist/commands/presence.js +4 -1
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +2 -3
- package/dist/core/agents/canonical-emit.d.ts +2 -3
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +6 -5
- package/dist/core/agents/cli.js +128 -89
- package/dist/core/agents/coord-client.d.ts +18 -3
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +5 -4
- package/dist/core/agents/finalization.d.ts +68 -0
- package/dist/core/agents/finalization.d.ts.map +1 -0
- package/dist/core/agents/finalization.js +443 -0
- package/dist/core/agents/git-hook.d.ts +51 -0
- package/dist/core/agents/git-hook.d.ts.map +1 -0
- package/dist/core/agents/git-hook.js +118 -0
- package/dist/core/agents/index.d.ts +1 -0
- package/dist/core/agents/index.d.ts.map +1 -1
- package/dist/core/agents/index.js +1 -0
- package/dist/core/agents/render/prompt-context.d.ts +12 -5
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +70 -16
- package/dist/core/agents/render/session-context.d.ts.map +1 -1
- package/dist/core/agents/render/session-context.js +23 -4
- package/dist/core/agents/rules/claim-conflict.js +3 -3
- package/dist/core/agents/rules/commit-conflict.d.ts +15 -6
- package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/commit-conflict.js +21 -5
- package/dist/core/agents/rules/stop-hook.d.ts +3 -0
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +59 -23
- package/dist/core/agents/session-events.d.ts +8 -16
- package/dist/core/agents/session-events.d.ts.map +1 -1
- package/dist/core/agents/session-events.js +12 -26
- package/dist/core/agents/state/heartbeat-projector.d.ts +14 -0
- package/dist/core/agents/state/heartbeat-projector.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-projector.js +98 -1
- package/dist/core/agents/state/heartbeat-writer.d.ts +47 -5
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +86 -17
- package/dist/core/agents/state/names.d.ts +22 -1
- package/dist/core/agents/state/names.d.ts.map +1 -1
- package/dist/core/agents/state/names.js +40 -2
- package/dist/core/agents/state/session-state.d.ts +44 -0
- package/dist/core/agents/state/session-state.d.ts.map +1 -0
- package/dist/core/agents/state/session-state.js +81 -0
- package/dist/core/config.d.ts +30 -2
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +74 -11
- package/dist/core/governor/planning.d.ts.map +1 -1
- package/dist/core/governor/planning.js +12 -13
- package/dist/core/hooks/adapter/detect.d.ts +2 -4
- package/dist/core/hooks/adapter/detect.d.ts.map +1 -1
- package/dist/core/hooks/adapter/detect.js +4 -14
- package/dist/core/hooks/adapter/events.d.ts.map +1 -1
- package/dist/core/hooks/adapter/events.js +1 -0
- package/dist/core/hooks/adapter/output.d.ts +1 -1
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +5 -4
- package/dist/core/hooks/adapter/parse.d.ts +1 -1
- package/dist/core/hooks/adapter/parse.d.ts.map +1 -1
- package/dist/core/hooks/adapter/parse.js +2 -0
- package/dist/core/hooks/adapter/wiring.d.ts +23 -0
- package/dist/core/hooks/adapter/wiring.d.ts.map +1 -1
- package/dist/core/hooks/adapter/wiring.js +32 -0
- package/dist/core/hooks/cli.d.ts +1 -2
- package/dist/core/hooks/cli.d.ts.map +1 -1
- package/dist/core/hooks/cli.js +258 -32
- package/dist/core/hooks/codex-authorization.d.ts +30 -0
- package/dist/core/hooks/codex-authorization.d.ts.map +1 -0
- package/dist/core/hooks/codex-authorization.js +199 -0
- package/dist/core/hooks/codex-wsl-bridge.d.ts +46 -0
- package/dist/core/hooks/codex-wsl-bridge.d.ts.map +1 -0
- package/dist/core/hooks/codex-wsl-bridge.js +137 -0
- package/dist/core/hooks/effects/index.d.ts +1 -1
- package/dist/core/hooks/effects/index.js +3 -3
- package/dist/core/hooks/events/schema.d.ts +57 -1
- package/dist/core/hooks/events/schema.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.d.ts +7 -1
- package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.js +15 -0
- package/dist/core/hooks/resolve/transcript.d.ts +44 -0
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +176 -1
- package/dist/core/hooks/session-name-presence.d.ts +30 -0
- package/dist/core/hooks/session-name-presence.d.ts.map +1 -0
- package/dist/core/hooks/session-name-presence.js +43 -0
- package/dist/core/hooks/unsafe-cross-shell.d.ts +13 -0
- package/dist/core/hooks/unsafe-cross-shell.d.ts.map +1 -0
- package/dist/core/hooks/unsafe-cross-shell.js +151 -0
- package/dist/core/presence/blob.d.ts +4 -0
- package/dist/core/presence/blob.d.ts.map +1 -1
- package/dist/core/presence/blob.js +12 -0
- package/dist/core/presence/index.js +15 -1
- package/dist/core/work/state.d.ts +4 -5
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +5 -8
- package/dist/core/workflow/index.d.ts +1 -1
- package/dist/core/workflow/index.d.ts.map +1 -1
- package/dist/core/workflow/proof.d.ts +2 -2
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +2 -2
- package/dist/core/workflow/run-state.d.ts +2 -2
- package/dist/core/workflow/run-state.d.ts.map +1 -1
- package/dist/core/workflow/run-state.js +2 -2
- package/dist/core/workflow/types.d.ts +3 -3
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/execution.d.ts +2 -2
- package/dist/core/workflow/workspaces/execution.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/execution.js +5 -0
- package/dist/core/workflow/workspaces/index.d.ts +1 -1
- package/dist/core/workflow/workspaces/index.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/local-git.js +1 -2
- package/dist/core/workflow/workspaces/paths.d.ts +2 -2
- package/dist/core/workflow/workspaces/types.d.ts +0 -6
- package/dist/core/workflow/workspaces/types.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/validate.d.ts +0 -2
- package/dist/core/workflow/workspaces/validate.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/validate.js +0 -2
- package/dist/lib/browser/client.d.ts +118 -1
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +435 -6
- package/dist/lib/browser/geometry.d.ts.map +1 -1
- package/dist/lib/browser/geometry.js +180 -37
- package/dist/lib/browser/index.d.ts +5 -1
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +5 -1
- package/dist/lib/browser/netscape-cookies.d.ts +6 -0
- package/dist/lib/browser/netscape-cookies.d.ts.map +1 -0
- package/dist/lib/browser/netscape-cookies.js +31 -0
- package/dist/lib/browser/proxy.d.ts +24 -0
- package/dist/lib/browser/proxy.d.ts.map +1 -0
- package/dist/lib/browser/proxy.js +84 -0
- package/dist/lib/browser/runts.d.ts +6 -0
- package/dist/lib/browser/runts.d.ts.map +1 -1
- package/dist/lib/browser/runts.js +21 -4
- package/dist/lib/browser/session-control.d.ts +112 -0
- package/dist/lib/browser/session-control.d.ts.map +1 -0
- package/dist/lib/browser/session-control.js +670 -0
- package/dist/lib/claude-desktop.d.ts +47 -0
- package/dist/lib/claude-desktop.d.ts.map +1 -1
- package/dist/lib/claude-desktop.js +169 -1
- package/dist/lib/docs-links.d.ts +108 -0
- package/dist/lib/docs-links.d.ts.map +1 -0
- package/dist/lib/docs-links.js +555 -0
- package/dist/lib/exec.d.ts +1 -1
- package/dist/lib/exec.js +1 -1
- package/dist/lib/identities/assume.d.ts +4 -2
- package/dist/lib/identities/assume.d.ts.map +1 -1
- package/dist/lib/identities/assume.js +15 -2
- package/dist/lib/instructions/bundle.d.ts +33 -0
- package/dist/lib/instructions/bundle.d.ts.map +1 -0
- package/dist/lib/instructions/bundle.js +149 -0
- package/dist/lib/instructions/git-hooks.d.ts +75 -0
- package/dist/lib/instructions/git-hooks.d.ts.map +1 -0
- package/dist/lib/instructions/git-hooks.js +238 -0
- package/dist/lib/instructions/splice.d.ts +10 -4
- package/dist/lib/instructions/splice.d.ts.map +1 -1
- package/dist/lib/instructions/splice.js +19 -11
- package/package.json +2 -2
- package/schemas/config.schema.json +32 -0
- package/src/commander.ts +5 -1
- package/src/commands/agents.ts +341 -113
- package/src/commands/browse-session.ts +245 -0
- package/src/commands/browse.ts +287 -44
- package/src/commands/checkpoint.ts +1 -1
- package/src/commands/claude-desktop.ts +106 -5
- package/src/commands/deinit.ts +7 -1
- package/src/commands/docs.ts +56 -0
- package/src/commands/doctor.ts +155 -21
- package/src/commands/init.ts +28 -9
- package/src/commands/instructions.ts +129 -0
- package/src/commands/presence.ts +7 -1
- package/src/commands/tunnel.ts +2 -5
- package/src/core/agents/canonical-emit.ts +7 -6
- package/src/core/agents/cli.ts +143 -89
- package/src/core/agents/coord-client.ts +21 -5
- package/src/core/agents/finalization.ts +595 -0
- package/src/core/agents/git-hook.ts +126 -0
- package/src/core/agents/index.ts +1 -0
- package/src/core/agents/render/prompt-context.ts +96 -16
- package/src/core/agents/render/session-context.ts +29 -4
- package/src/core/agents/rules/claim-conflict.ts +3 -3
- package/src/core/agents/rules/commit-conflict.ts +35 -8
- package/src/core/agents/rules/stop-hook.ts +71 -23
- package/src/core/agents/session-events.ts +14 -41
- package/src/core/agents/state/heartbeat-projector.ts +108 -1
- package/src/core/agents/state/heartbeat-writer.ts +129 -16
- package/src/core/agents/state/names.ts +54 -2
- package/src/core/agents/state/session-state.ts +131 -0
- package/src/core/config.ts +92 -12
- package/src/core/governor/planning.ts +17 -12
- package/src/core/hooks/adapter/detect.ts +4 -13
- package/src/core/hooks/adapter/events.ts +1 -0
- package/src/core/hooks/adapter/output.ts +9 -4
- package/src/core/hooks/adapter/parse.ts +3 -0
- package/src/core/hooks/adapter/wiring.ts +43 -0
- package/src/core/hooks/cli.ts +296 -27
- package/src/core/hooks/codex-authorization.ts +253 -0
- package/src/core/hooks/codex-wsl-bridge.ts +188 -0
- package/src/core/hooks/effects/index.ts +5 -5
- package/src/core/hooks/events/schema.ts +71 -0
- package/src/core/hooks/resolve/owner.ts +22 -1
- package/src/core/hooks/resolve/transcript.ts +164 -1
- package/src/core/hooks/session-name-presence.ts +52 -0
- package/src/core/hooks/unsafe-cross-shell.ts +160 -0
- package/src/core/presence/blob.ts +18 -0
- package/src/core/presence/index.ts +18 -1
- package/src/core/work/state.ts +8 -12
- package/src/core/workflow/engine.ts +2 -2
- package/src/core/workflow/index.ts +0 -1
- package/src/core/workflow/proof.ts +4 -4
- package/src/core/workflow/run-state.ts +5 -5
- package/src/core/workflow/types.ts +3 -3
- package/src/core/workflow/workspaces/execution.ts +11 -4
- package/src/core/workflow/workspaces/index.ts +0 -3
- package/src/core/workflow/workspaces/local-git.ts +1 -2
- package/src/core/workflow/workspaces/paths.ts +2 -2
- package/src/core/workflow/workspaces/types.ts +0 -9
- package/src/core/workflow/workspaces/validate.ts +1 -5
- package/src/lib/browser/client.ts +528 -6
- package/src/lib/browser/geometry.ts +197 -37
- package/src/lib/browser/index.ts +39 -0
- package/src/lib/browser/netscape-cookies.ts +39 -0
- package/src/lib/browser/proxy.ts +105 -0
- package/src/lib/browser/runts.ts +27 -3
- package/src/lib/browser/session-control.ts +892 -0
- package/src/lib/claude-desktop.ts +232 -1
- package/src/lib/docs-links.ts +674 -0
- package/src/lib/exec.ts +1 -1
- package/src/lib/identities/assume.ts +22 -1
- package/src/lib/instructions/bundle.ts +199 -0
- package/src/lib/instructions/git-hooks.ts +259 -0
- package/src/lib/instructions/splice.ts +41 -11
|
@@ -47,7 +47,9 @@ const MAX_RECORD_BYTES = 256 * 1024;
|
|
|
47
47
|
const MAX_EVENTS_BYTES = 512 * 1024;
|
|
48
48
|
const MAX_REASON = 2_000;
|
|
49
49
|
const PROPOSAL_ROOT_RULE =
|
|
50
|
-
"proposal.root
|
|
50
|
+
"proposal.root is inferred by Harnery as the single final outcome that no other proposed item depends on; it must use a root-capable template and depend transitively on every other proposed item; it never preserves or repeats active_root, which is context only";
|
|
51
|
+
const PLANNER_ROOT_RULE =
|
|
52
|
+
"Dependencies point from later work to earlier prerequisites. Do not return proposal.root. Harnery infers it as the single final outcome that no other proposed item depends on; make that outcome use a root-capable template and depend transitively on every other proposed item.";
|
|
51
53
|
|
|
52
54
|
export interface RunGovernorPlannerInput {
|
|
53
55
|
coordRoot: string;
|
|
@@ -729,7 +731,7 @@ function plannerScript(
|
|
|
729
731
|
: "Return decision=apply with a replacement immutable root graph, or decision=attention when human judgment is required.",
|
|
730
732
|
"Never claim mission completion unless the frozen mission acceptance is met. Never request a workflow outside the frozen template catalog.",
|
|
731
733
|
"Dependencies may name an active work ID or an earlier key in your proposed work array.",
|
|
732
|
-
|
|
734
|
+
PLANNER_ROOT_RULE,
|
|
733
735
|
"Work keys are lowercase identifiers no longer than 32 characters. Keep titles within 200 characters, objectives within 4000 characters, and each acceptance criterion within 500 characters.",
|
|
734
736
|
`Plan id: ${planId}`,
|
|
735
737
|
`Planning trigger: ${trigger}`,
|
|
@@ -1331,12 +1333,6 @@ function planProposalSchema(
|
|
|
1331
1333
|
const applyProperties: Record<string, StageSchema> = {
|
|
1332
1334
|
decision: { type: "string", enum: ["apply"] },
|
|
1333
1335
|
rationale,
|
|
1334
|
-
root: {
|
|
1335
|
-
type: "string",
|
|
1336
|
-
minLength: 1,
|
|
1337
|
-
maxLength: 32,
|
|
1338
|
-
pattern: "^[a-z][a-z0-9-]{0,31}$",
|
|
1339
|
-
},
|
|
1340
1336
|
work: {
|
|
1341
1337
|
type: "array",
|
|
1342
1338
|
minItems: 1,
|
|
@@ -1344,7 +1340,7 @@ function planProposalSchema(
|
|
|
1344
1340
|
items: workItem,
|
|
1345
1341
|
},
|
|
1346
1342
|
};
|
|
1347
|
-
const applyRequired = ["decision", "rationale", "
|
|
1343
|
+
const applyRequired = ["decision", "rationale", "work"];
|
|
1348
1344
|
if (record.intent.mission) {
|
|
1349
1345
|
applyProperties.milestone = milestone;
|
|
1350
1346
|
applyRequired.push("milestone");
|
|
@@ -1390,10 +1386,10 @@ function normalizeProposal(
|
|
|
1390
1386
|
const proposedAt = preservedProposedAt ?? new Date().toISOString();
|
|
1391
1387
|
const decision = enumValue(value.decision, ["apply", "complete", "attention"], "plan decision");
|
|
1392
1388
|
const rationale = bounded(value.rationale, "plan rationale", MAX_REASON);
|
|
1393
|
-
const
|
|
1389
|
+
const terminalRoot = typeof value.root === "string" ? value.root.trim() : "";
|
|
1394
1390
|
if (!Array.isArray(value.work)) throw new Error("plan work must be an array");
|
|
1395
1391
|
if (decision === "attention" || decision === "complete") {
|
|
1396
|
-
if (
|
|
1392
|
+
if (terminalRoot || value.work.length > 0 || value.milestone !== undefined) {
|
|
1397
1393
|
throw new Error(`${decision} plan must not contain work or milestone data`);
|
|
1398
1394
|
}
|
|
1399
1395
|
if (decision === "complete" && (!record.intent.mission || trigger !== "milestone")) {
|
|
@@ -1473,7 +1469,16 @@ function normalizeProposal(
|
|
|
1473
1469
|
template,
|
|
1474
1470
|
};
|
|
1475
1471
|
});
|
|
1476
|
-
|
|
1472
|
+
const dependedOn = new Set(
|
|
1473
|
+
work.flatMap((item) => item.dependencies.filter((dependency) => seen.has(dependency))),
|
|
1474
|
+
);
|
|
1475
|
+
const terminalOutcomes = work.filter((item) => !dependedOn.has(item.key));
|
|
1476
|
+
if (terminalOutcomes.length !== 1) {
|
|
1477
|
+
throw new Error(
|
|
1478
|
+
`plan must have exactly one final outcome; found ${terminalOutcomes.map((item) => item.key).join(", ")}`,
|
|
1479
|
+
);
|
|
1480
|
+
}
|
|
1481
|
+
const root = terminalOutcomes[0]!.key;
|
|
1477
1482
|
const rootSpec = work.find((item) => item.key === root);
|
|
1478
1483
|
if (!rootSpec || !policy.templates[rootSpec.template]?.root) {
|
|
1479
1484
|
throw new Error(`plan root ${root} must use a root-capable template`);
|
|
@@ -4,32 +4,23 @@ import type { Adapter } from "../events/schema.ts";
|
|
|
4
4
|
/**
|
|
5
5
|
* Resolve the adapter firing the hook. The dispatcher binary is always
|
|
6
6
|
* invoked with `--adapter <name>` per the current wiring in each adapter's
|
|
7
|
-
* settings file.
|
|
8
|
-
*
|
|
9
|
-
* re-runs `harn init`. Returns null when neither flag is present; caller falls
|
|
10
|
-
* through to the env-based fallback or skips emission.
|
|
7
|
+
* settings file. Returns null when the flag is absent; caller falls through to
|
|
8
|
+
* the environment fallback or skips emission.
|
|
11
9
|
*/
|
|
12
10
|
export function detectAdapter(argv: readonly string[]): Adapter | null {
|
|
13
11
|
for (let i = 0; i < argv.length; i++) {
|
|
14
12
|
const a = argv[i]!;
|
|
15
|
-
if (a === "--adapter"
|
|
13
|
+
if (a === "--adapter") {
|
|
16
14
|
return validate(argv[i + 1]);
|
|
17
15
|
}
|
|
18
16
|
if (a.startsWith("--adapter=")) {
|
|
19
17
|
return validate(a.slice("--adapter=".length));
|
|
20
18
|
}
|
|
21
|
-
if (a.startsWith("--harness=")) {
|
|
22
|
-
return validate(a.slice("--harness=".length));
|
|
23
|
-
}
|
|
24
19
|
}
|
|
25
|
-
return validate(coordEnv("AGENT_COORD_ADAPTER")
|
|
20
|
+
return validate(coordEnv("AGENT_COORD_ADAPTER"));
|
|
26
21
|
}
|
|
27
22
|
|
|
28
23
|
function validate(v: string | undefined): Adapter | null {
|
|
29
24
|
if (v === "claude-code" || v === "cursor" || v === "codex") return v;
|
|
30
|
-
// Legacy: some adapters use `claude_code` (underscore). Map
|
|
31
|
-
// it through so the env-based fallback works for callers that haven't
|
|
32
|
-
// updated yet.
|
|
33
|
-
if (v === "claude_code") return "claude-code";
|
|
34
25
|
return null;
|
|
35
26
|
}
|
|
@@ -87,6 +87,7 @@ export const CURSOR_EVENTS: HookEvent[] = [
|
|
|
87
87
|
export const CODEX_EVENTS: HookEvent[] = [
|
|
88
88
|
{ settingsKey: "SessionStart", subcommand: "session-start" },
|
|
89
89
|
{ settingsKey: "PreToolUse", subcommand: "pre-tool-use" },
|
|
90
|
+
{ settingsKey: "PermissionRequest", subcommand: "permission-request" },
|
|
90
91
|
{ settingsKey: "PostToolUse", subcommand: "post-tool-use" },
|
|
91
92
|
{ settingsKey: "UserPromptSubmit", subcommand: "user-prompt-submit" },
|
|
92
93
|
{ settingsKey: "SubagentStart", subcommand: "sub-agent-start" },
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
import { STOP_REMEDIATION_MARKER } from "../../agents/rules/stop-hook.ts";
|
|
22
|
-
import { resolveBinName } from "../../config.ts";
|
|
22
|
+
import { endOfTurnStatusCommand, resolveBinName } from "../../config.ts";
|
|
23
23
|
import type { Adapter } from "../events/schema.ts";
|
|
24
24
|
|
|
25
25
|
export type SystemEvent = "SessionStart" | "UserPromptSubmit" | "SubagentStart";
|
|
@@ -60,7 +60,11 @@ export function emitDeny(adapter: Adapter, reason: string): void {
|
|
|
60
60
|
* We exit 0 so Cursor treats the run as a success and honors the output.
|
|
61
61
|
* (Confirmed against cursor.com/docs/agent/hooks.)
|
|
62
62
|
*/
|
|
63
|
-
export function emitStopBlock(
|
|
63
|
+
export function emitStopBlock(
|
|
64
|
+
adapter: Adapter,
|
|
65
|
+
verdict: { reason?: string; rule: string },
|
|
66
|
+
coordRoot?: string,
|
|
67
|
+
): 0 | 2 {
|
|
64
68
|
if (adapter === "codex") return 0;
|
|
65
69
|
|
|
66
70
|
const reason = verdict.reason ?? "End-of-turn coordination ritual incomplete.";
|
|
@@ -70,11 +74,12 @@ export function emitStopBlock(adapter: Adapter, verdict: { reason?: string; rule
|
|
|
70
74
|
// see in chat that the message came from Harnery rather than from them.
|
|
71
75
|
// Both commands are named because one message that repairs the whole ritual
|
|
72
76
|
// ends the chain in a single followup; the failing rule is context.
|
|
73
|
-
const bin = resolveBinName();
|
|
77
|
+
const bin = resolveBinName(coordRoot);
|
|
78
|
+
const statusCommand = endOfTurnStatusCommand(coordRoot);
|
|
74
79
|
const message = [
|
|
75
80
|
`${STOP_REMEDIATION_MARKER} rule=${verdict.rule}]`,
|
|
76
81
|
reason,
|
|
77
|
-
`Repair the ritual in this turn: run \`${bin} agents set-task "<short focus>"\` and then \`${
|
|
82
|
+
`Repair the ritual in this turn: run \`${bin} agents set-task "<short focus>"\` and then \`${statusCommand}\` as your last tool call.`,
|
|
78
83
|
].join("\n");
|
|
79
84
|
process.stdout.write(`${JSON.stringify({ followup_message: message })}\n`);
|
|
80
85
|
return 0;
|
|
@@ -178,6 +178,8 @@ export function normalizeEventName(
|
|
|
178
178
|
case "pre-tool-use":
|
|
179
179
|
case "before-shell-execution":
|
|
180
180
|
return { event_type: "tool.pre_use", intra_turn: true };
|
|
181
|
+
case "permission-request":
|
|
182
|
+
return { event_type: "interaction.input_requested", intra_turn: true };
|
|
181
183
|
case "post-tool-use":
|
|
182
184
|
return { event_type: "tool.post_use", intra_turn: true };
|
|
183
185
|
case "post-tool-use-failure":
|
|
@@ -199,6 +201,7 @@ export type NormalizedEventType =
|
|
|
199
201
|
| "subagent.start"
|
|
200
202
|
| "subagent.stop"
|
|
201
203
|
| "tool.pre_use"
|
|
204
|
+
| "interaction.input_requested"
|
|
202
205
|
| "tool.post_use"
|
|
203
206
|
| "tool.post_use_failure"
|
|
204
207
|
| "context.compaction.started"
|
|
@@ -200,6 +200,49 @@ export function loadAdapterWiring(projectRoot: string): AdapterWiringStatus[] {
|
|
|
200
200
|
return out;
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
+
export interface AdapterWiringSummary {
|
|
204
|
+
/** Adapters carrying at least one harnery hook. */
|
|
205
|
+
wired: AdapterId[];
|
|
206
|
+
/**
|
|
207
|
+
* Adapters carrying none: no settings file at all, or a settings file with
|
|
208
|
+
* none of ours in it. An unparseable file lands in neither list, since
|
|
209
|
+
* `loadAdapterWiring` already reports that as drift.
|
|
210
|
+
*/
|
|
211
|
+
unwired: AdapterId[];
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Classify every known adapter as wired or unwired, without judging whether an
|
|
216
|
+
* unwired one is a problem.
|
|
217
|
+
*
|
|
218
|
+
* `loadAdapterWiring` stays deliberately silent about an adapter with zero
|
|
219
|
+
* harnery hooks, because a bare settings file is not an opt-out signal and
|
|
220
|
+
* nagging about it would false-warn every session. That silence is right in
|
|
221
|
+
* isolation and wrong once you also know the adapter's CLI is installed: then
|
|
222
|
+
* an agent can start a session here and register nothing. Splitting the fact
|
|
223
|
+
* from the judgement lets a caller holding both (doctor) tell "not used here"
|
|
224
|
+
* from "never wired" without changing what counts as drift.
|
|
225
|
+
*/
|
|
226
|
+
export function summarizeAdapterWiring(projectRoot: string): AdapterWiringSummary {
|
|
227
|
+
const wired: AdapterId[] = [];
|
|
228
|
+
const unwired: AdapterId[] = [];
|
|
229
|
+
for (const [id, spec] of Object.entries(ADAPTER_SPECS) as [AdapterId, AdapterSpec][]) {
|
|
230
|
+
const settingsPath = resolve(projectRoot, spec.settingsFile);
|
|
231
|
+
if (!existsSync(settingsPath)) {
|
|
232
|
+
unwired.push(id);
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
let settings: SettingsFile;
|
|
236
|
+
try {
|
|
237
|
+
settings = JSON.parse(readFileSync(settingsPath, "utf8")) as SettingsFile;
|
|
238
|
+
} catch {
|
|
239
|
+
continue; // unparseable → already surfaced by loadAdapterWiring
|
|
240
|
+
}
|
|
241
|
+
(diffWiring(settings, spec).present.length > 0 ? wired : unwired).push(id);
|
|
242
|
+
}
|
|
243
|
+
return { wired, unwired };
|
|
244
|
+
}
|
|
245
|
+
|
|
203
246
|
/**
|
|
204
247
|
* Resolve the harnery package version for context in nudges/checks. Walks up
|
|
205
248
|
* from this module to the package root (works under Bun from `src/` and Node
|