harnery 0.41.0 → 0.43.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/dist/commander.d.ts +16 -0
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +21 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +63 -5
- package/dist/commands/artifacts.d.ts.map +1 -1
- package/dist/commands/artifacts.js +113 -12
- package/dist/commands/browse.d.ts +164 -0
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +263 -51
- package/dist/commands/claude-desktop.d.ts.map +1 -1
- package/dist/commands/claude-desktop.js +52 -0
- package/dist/commands/disk.d.ts +6 -0
- package/dist/commands/disk.d.ts.map +1 -0
- package/dist/commands/disk.js +80 -0
- package/dist/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +48 -1
- package/dist/commands/files.d.ts +16 -0
- package/dist/commands/files.d.ts.map +1 -1
- package/dist/commands/files.js +54 -2
- package/dist/commands/init.d.ts +2 -2
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +43 -9
- package/dist/commands/rm.d.ts +4 -0
- package/dist/commands/rm.d.ts.map +1 -0
- package/dist/commands/rm.js +87 -0
- package/dist/commands/servers.d.ts +7 -0
- package/dist/commands/servers.d.ts.map +1 -0
- package/dist/commands/servers.js +394 -0
- package/dist/commands/tunnel.d.ts +65 -0
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +372 -103
- package/dist/commands/web-fetch.d.ts +3 -2
- package/dist/commands/web-fetch.d.ts.map +1 -1
- package/dist/commands/web-fetch.js +25 -19
- package/dist/commands/web.d.ts +7 -1
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +9 -3
- package/dist/core/adapters/profiles.d.ts +9 -0
- package/dist/core/adapters/profiles.d.ts.map +1 -1
- package/dist/core/adapters/profiles.js +22 -1
- package/dist/core/adapters/types.d.ts +9 -0
- package/dist/core/adapters/types.d.ts.map +1 -1
- package/dist/core/agents/cli.js +13 -6
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +11 -5
- package/dist/core/agents/render/session-context.d.ts.map +1 -1
- package/dist/core/agents/render/session-context.js +59 -13
- package/dist/core/agents/state/live-coordination-view.d.ts +20 -0
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +60 -0
- package/dist/core/agents/state/names.d.ts +43 -3
- package/dist/core/agents/state/names.d.ts.map +1 -1
- package/dist/core/agents/state/names.js +87 -3
- package/dist/core/artifacts/delivery-card.js +9 -2
- package/dist/core/artifacts/index.d.ts +140 -4
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +522 -49
- package/dist/core/config.d.ts +68 -11
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +128 -3
- package/dist/core/diagnostics/bundle.d.ts.map +1 -1
- package/dist/core/diagnostics/bundle.js +2 -2
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +16 -0
- package/dist/core/events/v3/projection.js +9 -1
- package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -1
- package/dist/core/events/v3/support-storage/pack-reader.js +42 -16
- package/dist/core/hooks/adapter/events.d.ts +17 -0
- package/dist/core/hooks/adapter/events.d.ts.map +1 -1
- package/dist/core/hooks/adapter/events.js +5 -0
- package/dist/core/hooks/adapter/runtime-telemetry.js +3 -1
- package/dist/core/hooks/adapter/wiring.d.ts +37 -7
- package/dist/core/hooks/adapter/wiring.d.ts.map +1 -1
- package/dist/core/hooks/adapter/wiring.js +62 -4
- package/dist/core/hooks/cli.js +131 -23
- package/dist/core/hooks/fork-lineage.d.ts +40 -0
- package/dist/core/hooks/fork-lineage.d.ts.map +1 -0
- package/dist/core/hooks/fork-lineage.js +62 -0
- package/dist/core/hooks/resolve/transcript.d.ts +16 -0
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +84 -0
- package/dist/core/hooks/run-markers.d.ts +37 -0
- package/dist/core/hooks/run-markers.d.ts.map +1 -0
- package/dist/core/hooks/run-markers.js +109 -0
- package/dist/core/hooks/shell-rm.d.ts +2 -0
- package/dist/core/hooks/shell-rm.d.ts.map +1 -0
- package/dist/core/hooks/shell-rm.js +105 -0
- package/dist/core/hooks/shell-tokens.d.ts +12 -0
- package/dist/core/hooks/shell-tokens.d.ts.map +1 -0
- package/dist/core/hooks/shell-tokens.js +97 -0
- package/dist/core/hooks/shell-waiter.d.ts.map +1 -1
- package/dist/core/hooks/shell-waiter.js +3 -93
- package/dist/core/semantic/contract.d.ts +5 -5
- package/dist/core/servers/index.d.ts +211 -0
- package/dist/core/servers/index.d.ts.map +1 -0
- package/dist/core/servers/index.js +560 -0
- package/dist/core/servers/net.d.ts +58 -0
- package/dist/core/servers/net.d.ts.map +1 -0
- package/dist/core/servers/net.js +270 -0
- package/dist/core/servers/tunnels.d.ts +14 -0
- package/dist/core/servers/tunnels.d.ts.map +1 -0
- package/dist/core/servers/tunnels.js +33 -0
- package/dist/core/storage/builtins.js +1 -0
- package/dist/core/storage/process-log.d.ts +12 -0
- package/dist/core/storage/process-log.d.ts.map +1 -1
- package/dist/core/storage/process-log.js +10 -2
- package/dist/core/workflow/engine.d.ts.map +1 -1
- package/dist/core/workflow/engine.js +30 -1
- package/dist/core/workflow/sandbox-projection.d.ts +13 -2
- package/dist/core/workflow/sandbox-projection.d.ts.map +1 -1
- package/dist/core/workflow/sandbox-projection.js +23 -0
- package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
- package/dist/core/workflow/spawn-claude.js +6 -1
- package/dist/core/workflow/spawn-codex.d.ts +2 -0
- package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
- package/dist/core/workflow/spawn-codex.js +20 -1
- package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
- package/dist/core/workflow/spawn-cursor.js +6 -1
- package/dist/core/workflow/spawn-opencode.d.ts.map +1 -1
- package/dist/core/workflow/spawn-opencode.js +4 -1
- package/dist/core/workflow/types.d.ts +47 -2
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/worker-access.d.ts +92 -0
- package/dist/core/workflow/worker-access.d.ts.map +1 -0
- package/dist/core/workflow/worker-access.js +450 -0
- package/dist/lib/browser/batch-steps.d.ts +18 -0
- package/dist/lib/browser/batch-steps.d.ts.map +1 -0
- package/dist/lib/browser/batch-steps.js +82 -0
- package/dist/lib/browser/collect/collector.d.ts +99 -0
- package/dist/lib/browser/collect/collector.d.ts.map +1 -0
- package/dist/lib/browser/collect/collector.js +202 -0
- package/dist/lib/browser/collect/fields.d.ts +31 -0
- package/dist/lib/browser/collect/fields.d.ts.map +1 -0
- package/dist/lib/browser/collect/fields.js +75 -0
- package/dist/lib/browser/collect/index.d.ts +6 -0
- package/dist/lib/browser/collect/index.d.ts.map +1 -0
- package/dist/lib/browser/collect/index.js +5 -0
- package/dist/lib/browser/collect/page-driver.d.ts +14 -0
- package/dist/lib/browser/collect/page-driver.d.ts.map +1 -0
- package/dist/lib/browser/collect/page-driver.js +306 -0
- package/dist/lib/browser/collect/presets.d.ts +52 -0
- package/dist/lib/browser/collect/presets.d.ts.map +1 -0
- package/dist/lib/browser/collect/presets.js +176 -0
- package/dist/lib/browser/collect/scroll-plan.d.ts +85 -0
- package/dist/lib/browser/collect/scroll-plan.d.ts.map +1 -0
- package/dist/lib/browser/collect/scroll-plan.js +118 -0
- package/dist/lib/browser/index.d.ts +1 -1
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/page-review-judge.d.ts +2 -0
- package/dist/lib/browser/page-review-judge.d.ts.map +1 -1
- package/dist/lib/browser/page-review-judge.js +13 -0
- package/dist/lib/browser/qa-run-contracts.d.ts +10 -0
- package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -1
- package/dist/lib/browser/qa-run.d.ts.map +1 -1
- package/dist/lib/browser/qa-run.js +1 -0
- package/dist/lib/browser/windows-chrome.d.ts +59 -0
- package/dist/lib/browser/windows-chrome.d.ts.map +1 -0
- package/dist/lib/browser/windows-chrome.js +179 -0
- package/dist/lib/claude-desktop-share.d.ts +136 -0
- package/dist/lib/claude-desktop-share.d.ts.map +1 -0
- package/dist/lib/claude-desktop-share.js +394 -0
- package/dist/lib/disk-usage.d.ts +50 -0
- package/dist/lib/disk-usage.d.ts.map +1 -0
- package/dist/lib/disk-usage.js +303 -0
- package/dist/lib/docs-lint.d.ts +6 -0
- package/dist/lib/docs-lint.d.ts.map +1 -1
- package/dist/lib/docs-lint.js +8 -3
- package/dist/lib/guarded-remove.d.ts +34 -0
- package/dist/lib/guarded-remove.d.ts.map +1 -0
- package/dist/lib/guarded-remove.js +310 -0
- package/dist/lib/instructions/templates.js +8 -8
- package/dist/lib/tunnel/allowlist.d.ts +44 -0
- package/dist/lib/tunnel/allowlist.d.ts.map +1 -0
- package/dist/lib/tunnel/allowlist.js +204 -0
- package/dist/lib/tunnel/current-address.d.ts +41 -0
- package/dist/lib/tunnel/current-address.d.ts.map +1 -0
- package/dist/lib/tunnel/current-address.js +123 -0
- package/dist/lib/tunnel/error-page.d.ts +1 -1
- package/dist/lib/tunnel/error-page.d.ts.map +1 -1
- package/dist/lib/tunnel/error-page.js +19 -8
- package/dist/lib/tunnel/gate.js +33 -7
- package/dist/lib/tunnel/path-scope.d.ts +22 -0
- package/dist/lib/tunnel/path-scope.d.ts.map +1 -0
- package/dist/lib/tunnel/path-scope.js +62 -0
- package/dist/lib/tunnel/processes.d.ts +39 -0
- package/dist/lib/tunnel/processes.d.ts.map +1 -0
- package/dist/lib/tunnel/processes.js +121 -0
- package/dist/lib/tunnel/state.d.ts +33 -3
- package/dist/lib/tunnel/state.d.ts.map +1 -1
- package/dist/lib/tunnel/state.js +115 -30
- package/package.json +7 -1
- package/schemas/config.schema.json +91 -0
- package/src/commander.ts +51 -0
- package/src/commands/agents.ts +111 -11
- package/src/commands/artifacts.ts +171 -19
- package/src/commands/browse.ts +400 -57
- package/src/commands/claude-desktop.ts +61 -0
- package/src/commands/disk.ts +114 -0
- package/src/commands/doctor.ts +52 -1
- package/src/commands/files.ts +93 -2
- package/src/commands/init.ts +55 -5
- package/src/commands/rm.ts +115 -0
- package/src/commands/servers.ts +506 -0
- package/src/commands/tunnel.ts +494 -116
- package/src/commands/web-fetch.ts +30 -19
- package/src/commands/web.ts +9 -3
- package/src/core/adapters/profiles.ts +22 -1
- package/src/core/adapters/types.ts +10 -0
- package/src/core/agents/cli.ts +14 -6
- package/src/core/agents/render/prompt-context.ts +25 -8
- package/src/core/agents/render/session-context.ts +84 -16
- package/src/core/agents/state/live-coordination-view.ts +73 -0
- package/src/core/agents/state/names.ts +117 -6
- package/src/core/artifacts/delivery-card.ts +10 -2
- package/src/core/artifacts/index.ts +697 -44
- package/src/core/config.ts +183 -4
- package/src/core/diagnostics/bundle.ts +2 -1
- package/src/core/events/v3/producers/recorder.ts +16 -0
- package/src/core/events/v3/projection.ts +11 -1
- package/src/core/events/v3/support-storage/pack-reader.ts +45 -19
- package/src/core/hooks/adapter/events.ts +19 -0
- package/src/core/hooks/adapter/runtime-telemetry.ts +3 -1
- package/src/core/hooks/adapter/wiring.ts +116 -8
- package/src/core/hooks/cli.ts +152 -22
- package/src/core/hooks/fork-lineage.ts +82 -0
- package/src/core/hooks/resolve/transcript.ts +88 -0
- package/src/core/hooks/run-markers.ts +132 -0
- package/src/core/hooks/shell-rm.ts +103 -0
- package/src/core/hooks/shell-tokens.ts +96 -0
- package/src/core/hooks/shell-waiter.ts +4 -91
- package/src/core/servers/index.ts +712 -0
- package/src/core/servers/net.ts +283 -0
- package/src/core/servers/tunnels.ts +39 -0
- package/src/core/storage/builtins.ts +1 -0
- package/src/core/storage/process-log.ts +17 -2
- package/src/core/workflow/engine.ts +38 -1
- package/src/core/workflow/sandbox-projection.ts +38 -2
- package/src/core/workflow/spawn-claude.ts +5 -1
- package/src/core/workflow/spawn-codex.ts +18 -1
- package/src/core/workflow/spawn-cursor.ts +5 -1
- package/src/core/workflow/spawn-opencode.ts +4 -1
- package/src/core/workflow/types.ts +62 -2
- package/src/core/workflow/worker-access.ts +525 -0
- package/src/lib/browser/batch-steps.ts +79 -0
- package/src/lib/browser/collect/collector.ts +306 -0
- package/src/lib/browser/collect/fields.ts +87 -0
- package/src/lib/browser/collect/index.ts +47 -0
- package/src/lib/browser/collect/page-driver.ts +327 -0
- package/src/lib/browser/collect/presets.ts +237 -0
- package/src/lib/browser/collect/scroll-plan.ts +179 -0
- package/src/lib/browser/index.ts +1 -0
- package/src/lib/browser/page-review-judge.ts +16 -0
- package/src/lib/browser/qa-run-contracts.ts +11 -0
- package/src/lib/browser/qa-run.ts +1 -0
- package/src/lib/browser/windows-chrome.ts +227 -0
- package/src/lib/claude-desktop-share.ts +511 -0
- package/src/lib/disk-usage.ts +347 -0
- package/src/lib/docs-lint.ts +8 -3
- package/src/lib/guarded-remove.ts +376 -0
- package/src/lib/instructions/templates.ts +8 -8
- package/src/lib/tunnel/allowlist.ts +208 -0
- package/src/lib/tunnel/current-address.ts +158 -0
- package/src/lib/tunnel/error-page.ts +25 -9
- package/src/lib/tunnel/gate.ts +38 -9
- package/src/lib/tunnel/path-scope.ts +73 -0
- package/src/lib/tunnel/processes.ts +149 -0
- package/src/lib/tunnel/state.ts +143 -30
|
@@ -11,13 +11,18 @@
|
|
|
11
11
|
* — there's exactly one definition of the `agent-hook <subcommand>` match.
|
|
12
12
|
*/
|
|
13
13
|
import { type AdapterId, type AdapterSpec, type HookEntryShape, type HookEvent } from "./events.js";
|
|
14
|
-
/** Claude Code
|
|
14
|
+
/** One Claude Code or Codex command handler. */
|
|
15
|
+
export interface ClaudeHookHandler {
|
|
16
|
+
type: string;
|
|
17
|
+
command: string;
|
|
18
|
+
/** Codex: run instead of `command` on Windows. */
|
|
19
|
+
commandWindows?: string;
|
|
20
|
+
timeout?: number;
|
|
21
|
+
}
|
|
22
|
+
/** Claude Code + Codex entry: `{ hooks: [{ type, command, commandWindows?, timeout? }] }`. */
|
|
15
23
|
export interface ClaudeHookGroup {
|
|
16
24
|
matcher?: string;
|
|
17
|
-
hooks:
|
|
18
|
-
type: string;
|
|
19
|
-
command: string;
|
|
20
|
-
}[];
|
|
25
|
+
hooks: ClaudeHookHandler[];
|
|
21
26
|
}
|
|
22
27
|
/** Cursor entry: a flat `{ command }`. */
|
|
23
28
|
export interface CursorHookGroup {
|
|
@@ -39,7 +44,32 @@ export interface SettingsFile {
|
|
|
39
44
|
/** Build a hook entry in the adapter's shape. */
|
|
40
45
|
export declare function makeEntry(shape: HookEntryShape, command: string, extras?: {
|
|
41
46
|
loop_limit?: number;
|
|
47
|
+
timeout?: number;
|
|
48
|
+
commandWindows?: string;
|
|
42
49
|
}): HookGroup;
|
|
50
|
+
/**
|
|
51
|
+
* Rebuild a handler with Harnery's fields first in a fixed order, dropping
|
|
52
|
+
* undefined ones and keeping any other fields after them.
|
|
53
|
+
*/
|
|
54
|
+
export declare function orderHandlerKeys(handler: ClaudeHookHandler): ClaudeHookHandler;
|
|
55
|
+
/**
|
|
56
|
+
* The Windows command for an opted-in project (ADR 0197). It hands the hook to
|
|
57
|
+
* the bridge entry point when that is on PATH and the working directory is a
|
|
58
|
+
* WSL UNC path, and otherwise runs the usual command. `ProviderPath` drops the
|
|
59
|
+
* provider prefix that `Path` carries. The trailing `exit $LASTEXITCODE` is
|
|
60
|
+
* required: without it PowerShell reports any non-zero exit from inside the
|
|
61
|
+
* `if` block as 1, which would turn a hook's blocking exit 2 into a failure.
|
|
62
|
+
*/
|
|
63
|
+
export declare function hookCommandWindows(spec: AdapterSpec, agentHookPath: string, subcommand: string, adapter: AdapterId, entryPoint: string): string;
|
|
64
|
+
/** Project-level choices that change what init writes. */
|
|
65
|
+
export interface WiringOptions {
|
|
66
|
+
/** Bridge entry point from `hooks.codexWindowsBridge`, or null when not opted in. */
|
|
67
|
+
windowsBridgeEntryPoint?: string | null;
|
|
68
|
+
}
|
|
69
|
+
/** The `commandWindows` init writes for one event, or undefined for none. */
|
|
70
|
+
export declare function expectedCommandWindows(spec: AdapterSpec, agentHookPath: string, subcommand: string, adapter: AdapterId, options?: WiringOptions): string | undefined;
|
|
71
|
+
/** The `timeout` init writes on one event's Harnery hook, or undefined for none. */
|
|
72
|
+
export declare function hookTimeoutFor(spec: AdapterSpec, subcommand: string): number | undefined;
|
|
43
73
|
/** Pin Cursor Stop followups to Harnery's loop cap. Returns true when the entry changed. */
|
|
44
74
|
export declare function applyCursorStopLoopLimit(group: HookGroup, subcommand: string): boolean;
|
|
45
75
|
/** Pull every command string out of a hook entry, regardless of shape. */
|
|
@@ -76,7 +106,7 @@ export interface WiringDiff {
|
|
|
76
106
|
duplicates: HookEvent[];
|
|
77
107
|
/** Spec events wired under an event key other than the canonical one. */
|
|
78
108
|
misplaced: HookEvent[];
|
|
79
|
-
/** Spec events whose correct-key command differs from init
|
|
109
|
+
/** Spec events whose correct-key command, `commandWindows`, or `timeout` differs from what init writes. */
|
|
80
110
|
stale: HookEvent[];
|
|
81
111
|
/** Settings fields rejected by a adapter with a strict top-level schema. */
|
|
82
112
|
invalidTopLevelKeys: string[];
|
|
@@ -90,7 +120,7 @@ export interface WiringDiff {
|
|
|
90
120
|
export declare function diffWiring(settings: SettingsFile, spec: AdapterSpec, expected?: {
|
|
91
121
|
agentHookPath: string;
|
|
92
122
|
adapter: AdapterId;
|
|
93
|
-
}): WiringDiff;
|
|
123
|
+
} & WiringOptions): WiringDiff;
|
|
94
124
|
export interface AdapterWiringStatus {
|
|
95
125
|
adapter: AdapterId;
|
|
96
126
|
/** Settings file path, relative to the project root. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wiring.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/adapter/wiring.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,aAAa,CAAC;AAGrB,
|
|
1
|
+
{"version":3,"file":"wiring.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/adapter/wiring.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,aAAa,CAAC;AAGrB,gDAAgD;AAChD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,8FAA8F;AAC9F,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,iBAAiB,EAAE,CAAC;CAC5B;AACD,0CAA0C;AAC1C,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AACD,MAAM,MAAM,SAAS,GAAG,eAAe,GAAG,eAAe,CAAC;AAE1D,2FAA2F;AAC3F,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAEjD,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB;AAED,iDAAiD;AACjD,wBAAgB,SAAS,CACvB,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1E,SAAS,CAgBX;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,iBAAiB,CAS9E;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,WAAW,EACjB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,SAAS,EAClB,UAAU,EAAE,MAAM,GACjB,MAAM,CAMR;AAED,0DAA0D;AAC1D,MAAM,WAAW,aAAa;IAC5B,qFAAqF;IACrF,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC;AAED,6EAA6E;AAC7E,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,WAAW,EACjB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,SAAS,EAClB,OAAO,CAAC,EAAE,aAAa,GACtB,MAAM,GAAG,SAAS,CASpB;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGxF;AAED,4FAA4F;AAC5F,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAMtF;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,EAAE,CAMxD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAGnF;AAQD,oEAAoE;AACpE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CACzB,IAAI,EAAE,WAAW,EACjB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,SAAS,GACjB,MAAM,CAMR;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAOxF;AAED,MAAM,WAAW,UAAU;IACzB,kDAAkD;IAClD,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,iCAAiC;IACjC,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB;;;;OAIG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sEAAsE;IACtE,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,yEAAyE;IACzE,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,2GAA2G;IAC3G,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,4EAA4E;IAC5E,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,yEAAyE;IACzE,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,WAAW,EACjB,QAAQ,CAAC,EAAE;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,SAAS,CAAA;CAAE,GAAG,aAAa,GACvE,UAAU,CAwFZ;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,SAAS,CAAC;IACnB,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAsCD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAyD5E;AAED,MAAM,WAAW,oBAAoB;IACnC,mDAAmD;IACnD,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB;;;;OAIG;IACH,OAAO,EAAE,SAAS,EAAE,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,oBAAoB,CA8BhF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAUvC;AAED,uEAAuE;AACvE,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,IAAI,CAkBlD"}
|
|
@@ -13,19 +13,68 @@
|
|
|
13
13
|
import { existsSync, readFileSync } from "node:fs";
|
|
14
14
|
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
15
15
|
import { fileURLToPath } from "node:url";
|
|
16
|
-
import { resolveBinName } from "../../config.js";
|
|
16
|
+
import { codexWindowsBridgeConfig, resolveBinName } from "../../config.js";
|
|
17
17
|
import { ADAPTER_SPECS, } from "./events.js";
|
|
18
18
|
import { checkOpenCodePlugin, isOwnedOpenCodePlugin } from "./opencode-plugin.js";
|
|
19
19
|
/** Bound Cursor Stop `followup_message` retries so a missed ritual cannot loop 5 times. */
|
|
20
20
|
export const CURSOR_STOP_FOLLOWUP_LOOP_LIMIT = 2;
|
|
21
21
|
/** Build a hook entry in the adapter's shape. */
|
|
22
22
|
export function makeEntry(shape, command, extras) {
|
|
23
|
-
if (shape !== "cursor")
|
|
24
|
-
return {
|
|
23
|
+
if (shape !== "cursor") {
|
|
24
|
+
return {
|
|
25
|
+
hooks: [
|
|
26
|
+
orderHandlerKeys({
|
|
27
|
+
type: "command",
|
|
28
|
+
command,
|
|
29
|
+
commandWindows: extras?.commandWindows,
|
|
30
|
+
timeout: extras?.timeout,
|
|
31
|
+
}),
|
|
32
|
+
],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
25
35
|
return extras?.loop_limit !== undefined
|
|
26
36
|
? { command, loop_limit: extras.loop_limit }
|
|
27
37
|
: { command };
|
|
28
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Rebuild a handler with Harnery's fields first in a fixed order, dropping
|
|
41
|
+
* undefined ones and keeping any other fields after them.
|
|
42
|
+
*/
|
|
43
|
+
export function orderHandlerKeys(handler) {
|
|
44
|
+
const { type, command, commandWindows, timeout, ...rest } = handler;
|
|
45
|
+
return {
|
|
46
|
+
type,
|
|
47
|
+
command,
|
|
48
|
+
...(commandWindows !== undefined ? { commandWindows } : {}),
|
|
49
|
+
...(timeout !== undefined ? { timeout } : {}),
|
|
50
|
+
...rest,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The Windows command for an opted-in project (ADR 0197). It hands the hook to
|
|
55
|
+
* the bridge entry point when that is on PATH and the working directory is a
|
|
56
|
+
* WSL UNC path, and otherwise runs the usual command. `ProviderPath` drops the
|
|
57
|
+
* provider prefix that `Path` carries. The trailing `exit $LASTEXITCODE` is
|
|
58
|
+
* required: without it PowerShell reports any non-zero exit from inside the
|
|
59
|
+
* `if` block as 1, which would turn a hook's blocking exit 2 into a failure.
|
|
60
|
+
*/
|
|
61
|
+
export function hookCommandWindows(spec, agentHookPath, subcommand, adapter, entryPoint) {
|
|
62
|
+
const direct = hookCommand(spec, agentHookPath, subcommand, adapter);
|
|
63
|
+
return (`if ((Get-Command ${entryPoint} -ErrorAction Ignore) -and $PWD.ProviderPath -like '\\\\wsl*') ` +
|
|
64
|
+
`{ ${entryPoint} ${subcommand} --adapter ${adapter} } else { ${direct} }; exit $LASTEXITCODE`);
|
|
65
|
+
}
|
|
66
|
+
/** The `commandWindows` init writes for one event, or undefined for none. */
|
|
67
|
+
export function expectedCommandWindows(spec, agentHookPath, subcommand, adapter, options) {
|
|
68
|
+
if (!spec.windowsBridgeHooks || !options?.windowsBridgeEntryPoint)
|
|
69
|
+
return undefined;
|
|
70
|
+
return hookCommandWindows(spec, agentHookPath, subcommand, adapter, options.windowsBridgeEntryPoint);
|
|
71
|
+
}
|
|
72
|
+
/** The `timeout` init writes on one event's Harnery hook, or undefined for none. */
|
|
73
|
+
export function hookTimeoutFor(spec, subcommand) {
|
|
74
|
+
if (!spec.hookTimeouts)
|
|
75
|
+
return undefined;
|
|
76
|
+
return spec.hookTimeouts.bySubcommand?.[subcommand] ?? spec.hookTimeouts.default;
|
|
77
|
+
}
|
|
29
78
|
/** Pin Cursor Stop followups to Harnery's loop cap. Returns true when the entry changed. */
|
|
30
79
|
export function applyCursorStopLoopLimit(group, subcommand) {
|
|
31
80
|
if (subcommand !== "stop")
|
|
@@ -107,7 +156,15 @@ export function diffWiring(settings, spec, expected) {
|
|
|
107
156
|
duplicates.push(event);
|
|
108
157
|
if (expected && commands.length > 0) {
|
|
109
158
|
const canonical = hookCommand(spec, expected.agentHookPath, event.subcommand, expected.adapter);
|
|
110
|
-
|
|
159
|
+
const timeout = hookTimeoutFor(spec, event.subcommand);
|
|
160
|
+
const commandWindows = expectedCommandWindows(spec, expected.agentHookPath, event.subcommand, expected.adapter, expected);
|
|
161
|
+
const handlerDrift = groups.some((group) => "hooks" in group &&
|
|
162
|
+
Array.isArray(group.hooks) &&
|
|
163
|
+
group.hooks.some((hook) => typeof hook.command === "string" &&
|
|
164
|
+
commandWiresSubcommand(hook.command, event.subcommand) &&
|
|
165
|
+
((timeout !== undefined && hook.timeout !== timeout) ||
|
|
166
|
+
(spec.windowsBridgeHooks === true && hook.commandWindows !== commandWindows))));
|
|
167
|
+
if (handlerDrift || commands.some((command) => command !== canonical))
|
|
111
168
|
stale.push(event);
|
|
112
169
|
}
|
|
113
170
|
const wrongKey = Object.entries(hooks).some(([key, otherGroups]) => key !== event.settingsKey &&
|
|
@@ -222,6 +279,7 @@ export function loadAdapterWiring(projectRoot) {
|
|
|
222
279
|
? {
|
|
223
280
|
agentHookPath: agentHookPathForProject(projectRoot, packageRoot),
|
|
224
281
|
adapter: id,
|
|
282
|
+
windowsBridgeEntryPoint: codexWindowsBridgeConfig(projectRoot).entryPoint,
|
|
225
283
|
}
|
|
226
284
|
: undefined);
|
|
227
285
|
if (diff.present.length === 0)
|
package/dist/core/hooks/cli.js
CHANGED
|
@@ -30,7 +30,7 @@ import { assistantTextStartsWithSessionNameBlock, isSessionNameRemediationComman
|
|
|
30
30
|
import { readHeartbeat, setAssignedNameCache, stampSessionNameReminded, stampSessionNameRequested, stampSessionNameSeen, } from "../agents/state/heartbeat-writer.js";
|
|
31
31
|
import { readLiveCoordinationRow } from "../agents/state/live-coordination-view.js";
|
|
32
32
|
import { ensureLiveCoordinationHeartbeat } from "../agents/state/live-coordination-writer.js";
|
|
33
|
-
import { assignName } from "../agents/state/names.js";
|
|
33
|
+
import { assignName, readForkParent, readForkState, recordForkDetection, resolveName, } from "../agents/state/names.js";
|
|
34
34
|
import { writePidmapRow } from "../agents/state/pidmap.js";
|
|
35
35
|
import { agentsRequireGitFinalization, coordFreshnessSeconds, hostPromptContextConfig, resolveBinName, } from "../config.js";
|
|
36
36
|
import { checkpointContext, completeContextRecovery, extractContextSample, markContextCompactionCompleted, prepareContextRecovery, readContextState, recordContextSample, } from "../context/index.js";
|
|
@@ -42,19 +42,25 @@ import { closeProcessLoggers, legacyLogFields, processLogger } from "../storage/
|
|
|
42
42
|
import { stableScopeId } from "../workflow/scope-id.js";
|
|
43
43
|
import { adapterBehavior } from "./adapter/behaviors/index.js";
|
|
44
44
|
import { detectAdapter, shouldSkipHookAdapter } from "./adapter/detect.js";
|
|
45
|
+
import { ADAPTER_SPECS } from "./adapter/events.js";
|
|
45
46
|
import { extractBashCommand, extractToolDescription, normalizeEventName, parsePayload, } from "./adapter/parse.js";
|
|
47
|
+
import { hookTimeoutFor } from "./adapter/wiring.js";
|
|
46
48
|
import { scheduleBackupSnapshot } from "./backup-schedule.js";
|
|
47
49
|
import { captureImages, detectPresence, imageJanitor, journalArchive, journalJanitor, journalRecoveryCue, playSound, recordImageArtifactsV3, resetSoundCounters, runSessionSyncExtension, soundForEvent, } from "./effects/index.js";
|
|
48
50
|
import { toolInputHash, toolTargetHash } from "./events/input-hash.js";
|
|
51
|
+
import { detectClaudeCodeFork } from "./fork-lineage.js";
|
|
49
52
|
import { canonicalize } from "./guard-path.js";
|
|
50
53
|
import { beginHookHealth, observeHookDebug, observeHookError, writeHookHealthCompletion, } from "./health.js";
|
|
51
54
|
import { adapterPidFromEnv, parsePsChainLine, selectAnchorPid } from "./resolve/anchor.js";
|
|
52
55
|
import { extractIntentComment, resolveIntent } from "./resolve/intent.js";
|
|
53
56
|
import { resolveOwner } from "./resolve/owner.js";
|
|
54
57
|
import { inspectSessionNameDisplayImmediately, scanAssistantStatusBoxPresent, scanStatusBoxPresent, scanTranscriptRuntime, } from "./resolve/transcript.js";
|
|
58
|
+
import { clearHookRunMarker, writeHookRunMarker } from "./run-markers.js";
|
|
55
59
|
import { sessionNamePresence } from "./session-name-presence.js";
|
|
60
|
+
import { shellRmReason } from "./shell-rm.js";
|
|
56
61
|
import { shellWaiterReason } from "./shell-waiter.js";
|
|
57
62
|
let hookHealthState;
|
|
63
|
+
let hookRunMarkerPath = null;
|
|
58
64
|
function parseArgv(argv) {
|
|
59
65
|
const out = { eventName: null, extra: [] };
|
|
60
66
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -151,11 +157,13 @@ function logError(coordRoot, err, context) {
|
|
|
151
157
|
* Mint or recover the hurricane-style name for this owner in-process. Returns
|
|
152
158
|
* null on any failure so session.started emission never breaks adapter flow.
|
|
153
159
|
*/
|
|
154
|
-
function assignNameInProcess(coordRoot, instanceId, kind,
|
|
160
|
+
function assignNameInProcess(coordRoot, instanceId, kind, fork) {
|
|
155
161
|
try {
|
|
156
162
|
const name = assignName(coordRoot, instanceId, kind, {
|
|
157
163
|
freshnessSecs: coordFreshnessSeconds(coordRoot),
|
|
158
|
-
...(forkedFrom ? { forkedFrom } : {}),
|
|
164
|
+
...(fork?.forkedFrom ? { forkedFrom: fork.forkedFrom } : {}),
|
|
165
|
+
...(fork?.fork ? { fork: true } : {}),
|
|
166
|
+
...(fork?.forkChecked ? { forkChecked: true } : {}),
|
|
159
167
|
});
|
|
160
168
|
return { name, kind };
|
|
161
169
|
}
|
|
@@ -163,9 +171,60 @@ function assignNameInProcess(coordRoot, instanceId, kind, forkedFrom) {
|
|
|
163
171
|
return null;
|
|
164
172
|
}
|
|
165
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Name a main session, recording fork lineage when the instance is new. Every
|
|
176
|
+
* main-session naming path goes through here: whichever hook first sees a new
|
|
177
|
+
* instance writes its history row, and lineage can only ride that first row
|
|
178
|
+
* (later detection appends a `fork.detected` row instead).
|
|
179
|
+
*/
|
|
180
|
+
function assignSessionNameInProcess(coordRoot, instanceId, payload, adapter) {
|
|
181
|
+
let fork;
|
|
182
|
+
try {
|
|
183
|
+
if (adapter === "claude-code" &&
|
|
184
|
+
payload?.session_id === instanceId &&
|
|
185
|
+
!resolveName(coordRoot, instanceId)) {
|
|
186
|
+
const detected = detectClaudeCodeFork({
|
|
187
|
+
coordRoot,
|
|
188
|
+
transcriptPath: payload.transcript_path,
|
|
189
|
+
sessionId: instanceId,
|
|
190
|
+
source: payload.source,
|
|
191
|
+
});
|
|
192
|
+
fork = {
|
|
193
|
+
...(detected.forkedFrom ? { forkedFrom: detected.forkedFrom } : {}),
|
|
194
|
+
fork: detected.fork,
|
|
195
|
+
forkChecked: detected.checked,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
fork = undefined;
|
|
201
|
+
}
|
|
202
|
+
return assignNameInProcess(coordRoot, instanceId, "session", fork);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Finish fork detection that session start could not: a CLI fork starts before
|
|
206
|
+
* its transcript exists, and a mid-flight instance may never see SessionStart.
|
|
207
|
+
* Runs once per instance; the appended `fork_checked` row stops later calls.
|
|
208
|
+
*/
|
|
209
|
+
function healForkLineage(coordRoot, instanceId, payload) {
|
|
210
|
+
if (!payload?.transcript_path || payload.session_id !== instanceId)
|
|
211
|
+
return;
|
|
212
|
+
const state = readForkState(coordRoot, instanceId);
|
|
213
|
+
if (!state || state.checked)
|
|
214
|
+
return;
|
|
215
|
+
const detected = detectClaudeCodeFork({
|
|
216
|
+
coordRoot,
|
|
217
|
+
transcriptPath: payload.transcript_path,
|
|
218
|
+
sessionId: instanceId,
|
|
219
|
+
knownFork: state.fork,
|
|
220
|
+
});
|
|
221
|
+
if (!detected.checked)
|
|
222
|
+
return;
|
|
223
|
+
recordForkDetection(coordRoot, instanceId, detected);
|
|
224
|
+
}
|
|
166
225
|
/** Mid-flight sessions can emit tools before SessionStart assigns a pool name.
|
|
167
226
|
* Stamp the disposable cache so Codec does not render the 8-character id. */
|
|
168
|
-
function ensureSessionDisplayName(coordRoot, instanceId, sessionId, adapter) {
|
|
227
|
+
function ensureSessionDisplayName(coordRoot, instanceId, sessionId, adapter, payload) {
|
|
169
228
|
if (coordEnv("WORKFLOW_CHILD") === "1")
|
|
170
229
|
return;
|
|
171
230
|
const row = readLiveCoordinationRow(coordRoot, instanceId) ?? readHeartbeat(coordRoot, instanceId);
|
|
@@ -173,7 +232,7 @@ function ensureSessionDisplayName(coordRoot, instanceId, sessionId, adapter) {
|
|
|
173
232
|
return;
|
|
174
233
|
if (row?.name?.trim())
|
|
175
234
|
return;
|
|
176
|
-
const assigned =
|
|
235
|
+
const assigned = assignSessionNameInProcess(coordRoot, instanceId, payload, adapter);
|
|
177
236
|
if (!assigned?.name)
|
|
178
237
|
return;
|
|
179
238
|
if (!readHeartbeat(coordRoot, instanceId)) {
|
|
@@ -226,17 +285,21 @@ function buildEventData(eventType, ctx) {
|
|
|
226
285
|
// The platform label is the adapter id itself; enumerating and defaulting
|
|
227
286
|
// to codex silently mislabels any adapter not in the list.
|
|
228
287
|
const adapterPlatform = ctx.adapter;
|
|
229
|
-
// Recorded fork lineage is NOT detected here. On claude-code a fork
|
|
230
|
-
// never fires its own session.started — SessionStart fires under the
|
|
231
|
-
// PARENT's session id (source=resume) before the fork id is minted
|
|
232
|
-
// (verified 2026-08-05) — so detection at this point can only mislabel
|
|
233
|
-
// the resumed parent. The fork's new instance is caught by the
|
|
234
|
-
// tool.requested heal path instead. The forkedFrom plumbing below stays
|
|
235
|
-
// for adapters that DO report a parent at session start.
|
|
236
|
-
const forkedFrom = undefined;
|
|
237
288
|
// Assign (or recover) name + kind in-process. Idempotent: resume
|
|
238
|
-
// returns the original name; new owner consumes a counter slot
|
|
239
|
-
|
|
289
|
+
// returns the original name; new owner consumes a counter slot and,
|
|
290
|
+
// on claude-code, runs fork detection (fork-lineage.ts). Since Claude
|
|
291
|
+
// Code 2.1.283 both fork flows fire SessionStart under the FORK's own
|
|
292
|
+
// id (verified 2026-10-07), superseding the 2026-08-05 finding that a
|
|
293
|
+
// fork never started on its own id. A resumed parent keeps its existing
|
|
294
|
+
// history row, so it is never relabeled here.
|
|
295
|
+
// Workflow children stay unnamed, as on the tool path: a pool name
|
|
296
|
+
// would make them the addressee of mail held for that name.
|
|
297
|
+
const assigned = coordEnv("WORKFLOW_CHILD") === "1"
|
|
298
|
+
? undefined
|
|
299
|
+
: assignSessionNameInProcess(ctx.coordRoot, ctx.instanceId, p, ctx.adapter);
|
|
300
|
+
const forkedFrom = assigned
|
|
301
|
+
? readForkParent(ctx.coordRoot, ctx.instanceId)?.instance_id
|
|
302
|
+
: undefined;
|
|
240
303
|
// Write the adapter pid-map row so `harn agents whoami` ppid-walks find
|
|
241
304
|
// this owner. Prefer the payload pid (the actual claude binary), then the
|
|
242
305
|
// anchor walk (the `node` ancestor for Cursor, which has no payload pid),
|
|
@@ -299,8 +362,9 @@ function buildEventData(eventType, ctx) {
|
|
|
299
362
|
// SessionStart. Mint durable display identity here so a later
|
|
300
363
|
// SessionStart remains idempotent and Codec is not stuck on the
|
|
301
364
|
// 8-character native id.
|
|
302
|
-
if (
|
|
303
|
-
|
|
365
|
+
if (coordEnv("WORKFLOW_CHILD") !== "1" &&
|
|
366
|
+
!readLiveCoordinationRow(ctx.coordRoot, ctx.instanceId)?.name) {
|
|
367
|
+
assignSessionNameInProcess(ctx.coordRoot, ctx.instanceId, p, ctx.adapter);
|
|
304
368
|
}
|
|
305
369
|
const prompt = p?.prompt ?? "";
|
|
306
370
|
const { value, truncated } = clampString(prompt, 4000);
|
|
@@ -475,6 +539,23 @@ async function main() {
|
|
|
475
539
|
const { eventName, extra } = parseArgv(process.argv.slice(2));
|
|
476
540
|
const adapter = detectAdapter(process.argv.slice(2));
|
|
477
541
|
const behavior = adapter ? adapterBehavior(adapter) : null;
|
|
542
|
+
// Adapters that kill a hook at its timeout get a start marker, so a killed
|
|
543
|
+
// run leaves evidence for doctor (ADR 0197). Written before stdin is read.
|
|
544
|
+
const markerSpec = adapter ? ADAPTER_SPECS[adapter] : undefined;
|
|
545
|
+
const markerTimeout = markerSpec && eventName && markerSpec.events.some((e) => e.subcommand === eventName)
|
|
546
|
+
? hookTimeoutFor(markerSpec, eventName)
|
|
547
|
+
: undefined;
|
|
548
|
+
if (markerTimeout !== undefined && adapter && eventName && coordEnv("AGENT_COORD_OFF") !== "1") {
|
|
549
|
+
const markerRoot = resolveCoordRoot(process.cwd());
|
|
550
|
+
if (markerRoot) {
|
|
551
|
+
hookRunMarkerPath = writeHookRunMarker(markerRoot, {
|
|
552
|
+
event: eventName,
|
|
553
|
+
adapter,
|
|
554
|
+
pid: process.pid,
|
|
555
|
+
timeout_sec: markerTimeout,
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
}
|
|
478
559
|
const raw = await readStdin();
|
|
479
560
|
hookHealthState = beginHookHealth({
|
|
480
561
|
started_at_ms: hookStartedAt,
|
|
@@ -619,7 +700,7 @@ async function main() {
|
|
|
619
700
|
priorCoordination?.kind !== "transient" &&
|
|
620
701
|
!priorCoordination?.workflow_run_id &&
|
|
621
702
|
!priorCoordination?.name?.trim()) {
|
|
622
|
-
|
|
703
|
+
assignSessionNameInProcess(coordRoot, owner.instance_id, payload, adapter);
|
|
623
704
|
}
|
|
624
705
|
const data = buildEventData(norm.event_type, {
|
|
625
706
|
coordRoot,
|
|
@@ -794,12 +875,20 @@ function recordSignal(run) {
|
|
|
794
875
|
}
|
|
795
876
|
if (norm.event_type !== "session.ended") {
|
|
796
877
|
try {
|
|
797
|
-
ensureSessionDisplayName(coordRoot, owner.instance_id, sessionId, adapter);
|
|
878
|
+
ensureSessionDisplayName(coordRoot, owner.instance_id, sessionId, adapter, payload);
|
|
798
879
|
}
|
|
799
880
|
catch (error) {
|
|
800
881
|
logError(coordRoot, error, { phase: "session-display-name" });
|
|
801
882
|
}
|
|
802
883
|
}
|
|
884
|
+
if (norm.event_type === "tool.requested" && adapter === "claude-code" && run.topLevelSession) {
|
|
885
|
+
try {
|
|
886
|
+
healForkLineage(coordRoot, owner.instance_id, payload);
|
|
887
|
+
}
|
|
888
|
+
catch (error) {
|
|
889
|
+
logError(coordRoot, error, { phase: "fork-lineage-heal" });
|
|
890
|
+
}
|
|
891
|
+
}
|
|
803
892
|
const v3EventId = v3Result && "event" in v3Result
|
|
804
893
|
? v3Result.event.event_id
|
|
805
894
|
: v3Result && "event_id" in v3Result
|
|
@@ -941,9 +1030,12 @@ async function handleSessionStarted(run) {
|
|
|
941
1030
|
const { autoCleanArtifacts } = await import("../artifacts/index.js");
|
|
942
1031
|
const { autoCleanEventV3Archives } = await import("../events/v3/archive-retention.js");
|
|
943
1032
|
const { createAutomaticMaintenanceComposition, runAutomaticMaintenancePass } = await import("../storage/maintenance-providers.js");
|
|
944
|
-
// Effect: throttled
|
|
945
|
-
//
|
|
946
|
-
//
|
|
1033
|
+
// Effect: throttled hourly artifact sweep (see autoCleanArtifacts). It
|
|
1034
|
+
// deletes expired workspaces, plus unheld workspaces over the per-bundle
|
|
1035
|
+
// ceiling or repository budget once they have been idle past
|
|
1036
|
+
// artifacts.idle_grace_hours. Each deletion is rechecked first and recorded
|
|
1037
|
+
// in .harnery/artifact-deletions.jsonl. Best-effort like every janitor
|
|
1038
|
+
// here: a failure logs and never blocks session start.
|
|
947
1039
|
try {
|
|
948
1040
|
autoCleanArtifacts(coordRoot);
|
|
949
1041
|
}
|
|
@@ -1252,6 +1344,12 @@ async function handleToolRequested(run) {
|
|
|
1252
1344
|
emitDeny(adapter, waiterReason);
|
|
1253
1345
|
return 0;
|
|
1254
1346
|
}
|
|
1347
|
+
const rmReason = shellRmReason(payload?.tool_name, payload?.tool_input, resolveBinName(coordRoot));
|
|
1348
|
+
if (rmReason) {
|
|
1349
|
+
const { emitDeny } = await import("./adapter/output.js");
|
|
1350
|
+
emitDeny(adapter, rmReason);
|
|
1351
|
+
return 0;
|
|
1352
|
+
}
|
|
1255
1353
|
// G-guard for ALL adapters. Claude Code previously ran this via a
|
|
1256
1354
|
// pre-tool-use bash adapter (which called `agent-coord verdict --rule=claim`);
|
|
1257
1355
|
// that adapter is now deleted, so agent-hook owns the deny for every adapter.
|
|
@@ -1291,7 +1389,8 @@ async function handlePostToolUse(run) {
|
|
|
1291
1389
|
// status is the wrong place to ask.
|
|
1292
1390
|
try {
|
|
1293
1391
|
const row = readLiveCoordinationRow(coordRoot, owner.instance_id);
|
|
1294
|
-
|
|
1392
|
+
// A workflow child has no user-visible title to set.
|
|
1393
|
+
const name = coordEnv("WORKFLOW_CHILD") === "1" ? undefined : sessionNameDisplayPending(row);
|
|
1295
1394
|
if (name && toolResponseMintedSessionName(payload?.tool_response, name)) {
|
|
1296
1395
|
// Record the title before asking for it. The suggestion can still
|
|
1297
1396
|
// change afterwards (an assigned-name rewrite, a lifecycle re-mint, a
|
|
@@ -1469,6 +1568,8 @@ function reportSessionNameObservationUnavailable(coordRoot, instanceId, adapter,
|
|
|
1469
1568
|
process.stderr.write(`Harnery: session-name observation unavailable (${reason}); allowing this ${eventName} without display enforcement. The name remains pending.\n`);
|
|
1470
1569
|
}
|
|
1471
1570
|
async function enforcePendingSessionNameDisplay(coordRoot, instanceId, adapter, payload, coordination) {
|
|
1571
|
+
if (coordEnv("WORKFLOW_CHILD") === "1")
|
|
1572
|
+
return true;
|
|
1472
1573
|
const name = sessionNameDisplayPending(coordination);
|
|
1473
1574
|
if (!name)
|
|
1474
1575
|
return true;
|
|
@@ -1830,6 +1931,11 @@ function cleanupSessionEnd(coordRoot, instanceId) {
|
|
|
1830
1931
|
}
|
|
1831
1932
|
}
|
|
1832
1933
|
async function emitUserPromptSubmitSystemMessage(coordRoot, instanceId, sessionId, adapter, workspaceCwd, recoveryBriefing = "", hostPromptContext = "") {
|
|
1934
|
+
// Workflow children get no prompt-time coordination context, matching
|
|
1935
|
+
// SessionStart. The turn ritual is not enforced for them, the naming nudge
|
|
1936
|
+
// would register them as named peers, and rendering drains peer mail.
|
|
1937
|
+
if (coordEnv("WORKFLOW_CHILD") === "1")
|
|
1938
|
+
return false;
|
|
1833
1939
|
const behavior = adapterBehavior(adapter);
|
|
1834
1940
|
const { renderPromptContext } = await import("../agents/render/prompt-context.js");
|
|
1835
1941
|
let additionalContext = renderPromptContext({
|
|
@@ -1943,6 +2049,7 @@ function completeRecoveryInjection(coordRoot, instanceId, sessionId, recovery) {
|
|
|
1943
2049
|
}
|
|
1944
2050
|
main()
|
|
1945
2051
|
.then(async (code) => {
|
|
2052
|
+
clearHookRunMarker(hookRunMarkerPath);
|
|
1946
2053
|
writeHookHealthCompletion(hookHealthState, {
|
|
1947
2054
|
finished_at_ms: performance.now(),
|
|
1948
2055
|
finished_rss_bytes: process.memoryUsage().rss,
|
|
@@ -1957,6 +2064,7 @@ main()
|
|
|
1957
2064
|
pid: process.pid,
|
|
1958
2065
|
phase: "top-level",
|
|
1959
2066
|
});
|
|
2067
|
+
clearHookRunMarker(hookRunMarkerPath);
|
|
1960
2068
|
writeHookHealthCompletion(hookHealthState, {
|
|
1961
2069
|
finished_at_ms: performance.now(),
|
|
1962
2070
|
finished_rss_bytes: process.memoryUsage().rss,
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code fork detection: decide whether a new main-session instance is a
|
|
3
|
+
* branch of another session, and which one.
|
|
4
|
+
*
|
|
5
|
+
* Two shapes exist as of Claude Code 2.1.283 (verified 2026-10-07):
|
|
6
|
+
*
|
|
7
|
+
* - CLI `--resume <id> --fork-session` fires SessionStart under the FORK's id
|
|
8
|
+
* with `source: "fork"`, before its transcript exists, and names no parent.
|
|
9
|
+
* The transcript later holds the parent's message uuids with every row's
|
|
10
|
+
* `sessionId` rewritten, so the parent is found by uuid containment
|
|
11
|
+
* (`detectForkParent`) once the transcript is on disk.
|
|
12
|
+
* - The desktop app's "Fork from here" copies the parent's rows into the
|
|
13
|
+
* fork's transcript with their original `sessionId`, so inherited rows
|
|
14
|
+
* name the parent directly (`detectInheritedSessionParent`).
|
|
15
|
+
*
|
|
16
|
+
* Inherited rows alone do not prove a fork: a continuation of a finished
|
|
17
|
+
* session can carry them too. The parent's liveness separates the two. A
|
|
18
|
+
* parent with an unended generation is still running (or resumable) and owns
|
|
19
|
+
* its name, task, and claims, so the new instance is a fork. A finished
|
|
20
|
+
* parent makes it a continuation, which keeps the generic notice.
|
|
21
|
+
*
|
|
22
|
+
* Everything here fails open: an unreadable transcript or an unknown layout
|
|
23
|
+
* yields "not a fork", never an error.
|
|
24
|
+
*/
|
|
25
|
+
export interface ForkDetection {
|
|
26
|
+
fork: boolean;
|
|
27
|
+
forkedFrom?: string;
|
|
28
|
+
/** Detection had the evidence it needs; the tool-path heal can skip it. */
|
|
29
|
+
checked: boolean;
|
|
30
|
+
}
|
|
31
|
+
export declare function detectClaudeCodeFork(input: {
|
|
32
|
+
coordRoot: string;
|
|
33
|
+
transcriptPath: string | undefined;
|
|
34
|
+
sessionId: string;
|
|
35
|
+
source?: string;
|
|
36
|
+
/** The instance was already recorded as a fork without a parent. */
|
|
37
|
+
knownFork?: boolean;
|
|
38
|
+
isLive?: (instanceId: string) => boolean;
|
|
39
|
+
}): ForkDetection;
|
|
40
|
+
//# sourceMappingURL=fork-lineage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fork-lineage.d.ts","sourceRoot":"","sources":["../../../src/core/hooks/fork-lineage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAMH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,OAAO,EAAE,OAAO,CAAC;CAClB;AAKD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC;CAC1C,GAAG,aAAa,CAkChB"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code fork detection: decide whether a new main-session instance is a
|
|
3
|
+
* branch of another session, and which one.
|
|
4
|
+
*
|
|
5
|
+
* Two shapes exist as of Claude Code 2.1.283 (verified 2026-10-07):
|
|
6
|
+
*
|
|
7
|
+
* - CLI `--resume <id> --fork-session` fires SessionStart under the FORK's id
|
|
8
|
+
* with `source: "fork"`, before its transcript exists, and names no parent.
|
|
9
|
+
* The transcript later holds the parent's message uuids with every row's
|
|
10
|
+
* `sessionId` rewritten, so the parent is found by uuid containment
|
|
11
|
+
* (`detectForkParent`) once the transcript is on disk.
|
|
12
|
+
* - The desktop app's "Fork from here" copies the parent's rows into the
|
|
13
|
+
* fork's transcript with their original `sessionId`, so inherited rows
|
|
14
|
+
* name the parent directly (`detectInheritedSessionParent`).
|
|
15
|
+
*
|
|
16
|
+
* Inherited rows alone do not prove a fork: a continuation of a finished
|
|
17
|
+
* session can carry them too. The parent's liveness separates the two. A
|
|
18
|
+
* parent with an unended generation is still running (or resumable) and owns
|
|
19
|
+
* its name, task, and claims, so the new instance is a fork. A finished
|
|
20
|
+
* parent makes it a continuation, which keeps the generic notice.
|
|
21
|
+
*
|
|
22
|
+
* Everything here fails open: an unreadable transcript or an unknown layout
|
|
23
|
+
* yields "not a fork", never an error.
|
|
24
|
+
*/
|
|
25
|
+
import { existsSync } from "node:fs";
|
|
26
|
+
import { readLiveCoordinationRow } from "../agents/state/live-coordination-view.js";
|
|
27
|
+
import { detectForkParent, detectInheritedSessionParent } from "./resolve/transcript.js";
|
|
28
|
+
/** Sources after which a brand-new instance cannot hold inherited history. */
|
|
29
|
+
const FRESH_SOURCES = new Set(["startup", "clear"]);
|
|
30
|
+
export function detectClaudeCodeFork(input) {
|
|
31
|
+
try {
|
|
32
|
+
const declared = input.source === "fork" || input.knownFork === true;
|
|
33
|
+
const transcriptReady = !!input.transcriptPath && existsSync(input.transcriptPath);
|
|
34
|
+
const isLive = input.isLive ?? ((id) => readLiveCoordinationRow(input.coordRoot, id) !== null);
|
|
35
|
+
const inherited = transcriptReady
|
|
36
|
+
? detectInheritedSessionParent(input.transcriptPath, input.sessionId)
|
|
37
|
+
: undefined;
|
|
38
|
+
if (inherited && inherited !== input.sessionId) {
|
|
39
|
+
if (declared || isLive(inherited)) {
|
|
40
|
+
return { fork: true, forkedFrom: inherited, checked: true };
|
|
41
|
+
}
|
|
42
|
+
return { fork: false, checked: true };
|
|
43
|
+
}
|
|
44
|
+
if (declared) {
|
|
45
|
+
if (!transcriptReady)
|
|
46
|
+
return { fork: true, checked: false };
|
|
47
|
+
const parent = detectForkParent(input.transcriptPath, input.sessionId);
|
|
48
|
+
return {
|
|
49
|
+
fork: true,
|
|
50
|
+
...(parent && parent !== input.sessionId ? { forkedFrom: parent } : {}),
|
|
51
|
+
checked: true,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
fork: false,
|
|
56
|
+
checked: transcriptReady || FRESH_SOURCES.has(input.source ?? ""),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return { fork: false, checked: true };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -92,6 +92,22 @@ export interface TranscriptRuntimeScan {
|
|
|
92
92
|
* SessionStart).
|
|
93
93
|
*/
|
|
94
94
|
export declare function scanTranscriptRuntime(transcriptPath: string | undefined): TranscriptRuntimeScan | undefined;
|
|
95
|
+
/**
|
|
96
|
+
* Detect inherited history from row session ids: the session whose rows were
|
|
97
|
+
* copied into this transcript, or undefined when every row is this session's.
|
|
98
|
+
*
|
|
99
|
+
* Empirical basis (verified 2026-10-07, Claude Code 2.1.283): the desktop
|
|
100
|
+
* app's "Fork from here" copies the parent's rows into the fork's transcript
|
|
101
|
+
* WITHOUT rewriting their `sessionId`, so the fork's file opens with thousands
|
|
102
|
+
* of rows stamped with the parent's id. The CLI `--fork-session` path rewrites
|
|
103
|
+
* the ids instead and is covered by {@link detectForkParent}.
|
|
104
|
+
*
|
|
105
|
+
* When the history is itself several generations deep, the LAST foreign row is
|
|
106
|
+
* the nearest ancestor, so the tail is scanned first. Whether the foreign
|
|
107
|
+
* session is a fork parent or a dead predecessor (a continuation) is the
|
|
108
|
+
* caller's call. Fail-soft: never throws, undefined on any read problem.
|
|
109
|
+
*/
|
|
110
|
+
export declare function detectInheritedSessionParent(transcriptPath: string | undefined, sessionId: string): string | undefined;
|
|
95
111
|
/**
|
|
96
112
|
* Detect the parent session of a forked CC conversation from its transcript.
|
|
97
113
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/resolve/transcript.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,2BAA2B,wBAAc,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAQhF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CACvC,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,MAAM,EAAE,MAAM,GACb,OAAO,CAiCT;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,oBAAoB,EAAE,MAAM,GAAG,SAAS,GACvC,OAAO,CAKT;AAED,kFAAkF;AAClF,wBAAgB,uBAAuB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAgB9F;AAED;;;;;GAKG;AACH,wBAAgB,mCAAmC,CACjD,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,OAAO,GAC/D,OAAO,CAIT;AAED,MAAM,MAAM,4BAA4B,GACpC;IAAE,KAAK,EAAE,SAAS,CAAA;CAAE,GACpB;IAAE,KAAK,EAAE,QAAQ,CAAA;CAAE,GACnB;IACE,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,oBAAoB,GAAG,sBAAsB,GAAG,wBAAwB,CAAC;CAClF,CAAC;AAEN;;;;;GAKG;AACH,wBAAgB,oCAAoC,CAClD,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,OAAO,GAC/D,4BAA4B,CAqD9B;AAgBD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAUrF;AAwDD;4CAC4C;AAC5C,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd;+EAC2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,MAAM,GAAG,SAAS,GACjC,qBAAqB,GAAG,SAAS,CA8BnC;
|
|
1
|
+
{"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/resolve/transcript.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,2BAA2B,wBAAc,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAQhF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CACvC,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,MAAM,EAAE,MAAM,GACb,OAAO,CAiCT;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,oBAAoB,EAAE,MAAM,GAAG,SAAS,GACvC,OAAO,CAKT;AAED,kFAAkF;AAClF,wBAAgB,uBAAuB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAgB9F;AAED;;;;;GAKG;AACH,wBAAgB,mCAAmC,CACjD,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,OAAO,GAC/D,OAAO,CAIT;AAED,MAAM,MAAM,4BAA4B,GACpC;IAAE,KAAK,EAAE,SAAS,CAAA;CAAE,GACpB;IAAE,KAAK,EAAE,QAAQ,CAAA;CAAE,GACnB;IACE,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,oBAAoB,GAAG,sBAAsB,GAAG,wBAAwB,CAAC;CAClF,CAAC;AAEN;;;;;GAKG;AACH,wBAAgB,oCAAoC,CAClD,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,OAAO,GAC/D,4BAA4B,CAqD9B;AAgBD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAUrF;AAwDD;4CAC4C;AAC5C,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd;+EAC2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,MAAM,GAAG,SAAS,GACjC,qBAAqB,GAAG,SAAS,CA8BnC;AAgBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAC1C,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,SAAS,CAiBpB;AA6CD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,gBAAgB,CAC9B,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,SAAS,CAkDpB"}
|