@skillstate/claude 2.0.6 → 2.1.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 CHANGED
@@ -2,11 +2,10 @@
2
2
 
3
3
  # @skillstate/claude
4
4
 
5
- **Claude Code platform adapter for the @skillstate/core runtime — state injection and persistence via hook scripts.**
5
+ **Claude Code platform adapter for the @skillstate/core runtime — state injection and patch persistence via hook scripts (2.1.260 hooks contract).**
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/@skillstate/claude)](https://www.npmjs.com/package/@skillstate/claude)
8
8
  [![node](https://img.shields.io/node/v/@skillstate/claude)](https://www.npmjs.com/package/@skillstate/claude)
9
- [![Tests](https://img.shields.io/badge/tests-873%20passing-brightgreen)](https://github.com/vitalykuzyaev/skillstate)
10
9
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](https://github.com/vitalykuzyaev/skillstate/blob/main/LICENSE)
11
10
 
12
11
  </div>
@@ -15,16 +14,40 @@
15
14
 
16
15
  `@skillstate/claude` bridges the paper-exact core ([`@skillstate/core`](../core))
17
16
  into **Claude Code** sessions. It emits self-contained CommonJS hook scripts
18
- (run via `node script.cjs`) that inject the persisted skill state into tool
19
- context and extract a validated `state_patch` from the model's response.
17
+ (run via `node script.cjs`) that inject the persisted skill state into every
18
+ turn, re-inject it after compaction, and merge a validated `state_patch` from
19
+ Bash tool responses back into the state file.
20
20
 
21
21
  > **@non-paper** — no adapters exist in arXiv 2608.26263v3. This adapter is an
22
22
  > additive integration, not part of the paper.
23
23
 
24
+ ## The honest architecture (Claude Code 2.1.260)
25
+
26
+ **History trimming from hooks is impossible.** The compaction-time hook cannot
27
+ inject context (its only decision is `decision: "block"` — forbid compaction),
28
+ and the post-compaction hook has no decision control at all (its
29
+ `systemMessage` is discarded). So this adapter implements the state-injection
30
+ model, not a trim model:
31
+
32
+ | Event | Matcher | What the script does |
33
+ | --- | --- | --- |
34
+ | `UserPromptSubmit` | — (no matcher support) | Injects `Current skill state (JSON): {...}` as `additionalContext` — the model gets the authoritative state at every turn. |
35
+ | `SessionStart` | `^compact$` | Re-injects the state right after auto/manual compaction — state SURVIVES compaction even though history was compressed. |
36
+ | `PostToolUse` | `^Bash$` | Extracts a fenced ```json `state_patch` from the tool response (or a raw JSON / object `tool_response.state_patch`), applies the paper's ⊕ null-deletion merge, and writes `{ version: 1, state }`. stdout is `{}` or a `systemMessage` when the patch is invalid. |
37
+
38
+ Reading and writing the full state is available at any time through the
39
+ skillstate MCP server (`state.get` / `state.patch` — schema-validated) that
40
+ `skillstate init` registers in the project's `.mcp.json`.
41
+
42
+ Prompts stay O(T) with a fresh state at every turn. **True O(1) requires
43
+ host-side trimming, which Claude Code does not expose.**
44
+
24
45
  ## Installation
25
46
 
26
47
  ```bash
27
48
  npm i @skillstate/core @skillstate/claude
49
+ # or wire everything into a live host at once:
50
+ skillstate init # writes scripts, merges ~/.claude/settings.json, adds .mcp.json + SKILL.md
28
51
  ```
29
52
 
30
53
  Requires Node.js >= 20. TypeScript types are bundled.
@@ -37,66 +60,75 @@ import { INTERCODE_CTF_SPEC } from '@skillstate/core/schemas';
37
60
 
38
61
  const adapter = new ClaudeAdapter();
39
62
 
40
- // System-prompt boilerplate that turns any Claude Code session into
41
- // state-based execution mode:
42
- const modePrompt = adapter.generateAppendPrompt();
43
-
44
- // PreToolUse: injects the persisted state into the tool call's additionalContext.
45
- const pre = adapter.generateHookScript('PreToolUse', './.skillstate.json');
46
-
47
- // PostToolUse: extracts state_patch from the response, validates it against the
48
- // embedded schema, applies the null-deletion ⊕ merge, and saves the state file.
49
- const post = adapter.generateHookScript(
50
- 'PostToolUse',
51
- './.skillstate.json',
52
- INTERCODE_CTF_SPEC.schema,
53
- );
54
-
55
- // PreCompact + SessionStart(compact): the best available O(1)-friendly pair.
56
- const hooks = adapter.generateAllHooksScripts('./.skillstate.json', INTERCODE_CTF_SPEC.schema);
57
- // hooks.preCompact -> injects state + diff into compaction summary
58
- // hooks.sessionStartCompact -> re-injects state after compaction
59
-
60
- // Persist a hook script to disk (atomic tmp + fsync + rename), returns path:
61
- const saved = await adapter.saveHookScript(
62
- './hooks/post-tool-use.cjs',
63
- 'PostToolUse',
64
- './.skillstate.json',
65
- INTERCODE_CTF_SPEC.schema,
66
- );
63
+ // Self-contained hook scripts (Node builtins only). Each resolves the
64
+ // per-project state from input.cwd at runtime — one global script dir
65
+ // serves every project:
66
+ const inject = adapter.generateHookScript('user-prompt-submit');
67
+ const survive = adapter.generateHookScript('session-start-compact');
68
+ const persist = adapter.generateHookScript('post-tool-use');
69
+
70
+ // The hooks section for ~/.claude/settings.json (2.1.260 schema:
71
+ // { hooks: { Event: [ { matcher?, hooks: [ { type: "command", command, timeout } ] } ] } }):
72
+ const hooksJson = adapter.generateHooksConfig('./.skillstate/skillstate.json', {
73
+ scriptDir: '/home/me/.claude/hooks/skillstate',
74
+ });
75
+
76
+ // Merge into a live settings.json — preserves env/permissions/model and
77
+ // every foreign hook; byte-identical (no-op) when already wired:
78
+ const merged = adapter.mergeHooksConfig(existingSettingsText, {
79
+ scriptDir: '/home/me/.claude/hooks/skillstate',
80
+ });
81
+
82
+ // Uninstall surgery: remove exactly the skillstate groups/handlers from a
83
+ // live settings.json (mixed groups keep their foreign handlers):
84
+ const { text, changed } = removeSkillstateHookGroups(liveSettingsText);
85
+
86
+ // Atomic persistence helpers (tmp + fsync + rename):
87
+ await adapter.saveHookScript('post-tool-use', '/h/skillstate/post-tool-use.cjs');
88
+ await adapter.saveSkillMd('/home/me/.claude/skills/skillstate/SKILL.md', spec);
67
89
  ```
68
90
 
69
91
  ## API / Exports
70
92
 
71
- Root path `@skillstate/claude` exports one thing: `ClaudeAdapter`.
72
-
73
- - `new ClaudeAdapter()` — implements `PlatformAdapter` (`name = 'claude'`).
74
- - `generateHookScript(eventType, statePath, schema?): string` — where
75
- `eventType` is `'PreToolUse' | 'PostToolUse'`. Accepts a raw path or a
76
- `{ root, name }` ref confined by `resolveStatePath` (`..` escapes throw).
77
- - `generateCompactHookScript(statePath, schema?): string` — PreCompact script
78
- injecting the current state + a diff since the last compact snapshot.
79
- - `generateSessionStartHookScript(statePath): string` — SessionStart hook with
80
- a `source: "compact"` matcher.
81
- - `generateAllHooksScripts(statePath, schema?): { preCompact; sessionStartCompact }`.
93
+ Root path `@skillstate/claude` exports:
94
+
95
+ - `new ClaudeAdapter()` — implements `PlatformAdapter` (`name = 'claude'`):
96
+ `injectState`, `extractPatch`, `extractAction`, `formatPrompt`.
97
+ - `generateHookScript(event, statePath?): string` — `event` is
98
+ `'user-prompt-submit' | 'session-start-compact' | 'post-tool-use'`.
99
+ Accepts a raw path or a `{ root, name }` ref confined by
100
+ `resolveStatePath` (`..` escapes throw). The path only documents the
101
+ header — the script resolves the state from the session cwd.
102
+ - `generateHooksConfig(statePath?, options?): string` — JSON with ONLY the
103
+ `hooks` section. Options: `scriptDir`, `command`, `timeoutSeconds`
104
+ (default 30).
105
+ - `mergeHooksConfig(existingJson, options?): string` — idempotent merge into
106
+ a live settings.json; preserves every other key.
107
+ - `removeSkillstateHookGroups(existingJson): { text, changed }` — surgical
108
+ uninstall (pure groups dropped, mixed groups trimmed, empty events
109
+ removed).
110
+ - `claudeHookScriptPath(scriptDir, event): string`.
111
+ - `generateSkillMd(spec, statePath?): string` + `saveSkillMd`,
112
+ `saveHookScript(event, target, statePath?)`, `saveHooksConfig(target,
113
+ statePath?, options?)` — atomic writes.
82
114
  - `generateAppendPrompt(): string` — mode-switch prompt boilerplate.
83
- - `injectState(state, spec): string` / `formatPrompt(state, observation, spec): string`.
84
- - `extractPatch(response): StatePatch | null` / `extractAction(response): string | null`.
85
- - `saveHookScript(target, eventType, statePath, schema?): Promise<string>` —
86
- generates a hook script and persists it atomically; returns the destination.
115
+ - `CLAUDE_HOOK_EVENTS`, `CLAUDE_SESSION_START_MATCHER` (`^compact$`),
116
+ `CLAUDE_POST_TOOL_USE_MATCHER` (`^Bash$`), `CLAUDE_HOOK_TIMEOUT_SECONDS`.
117
+ - `resolveStateForCwd(cwd, home?)` — re-export of the core
118
+ `resolveHostStateForCwd` (single source of truth for the per-project
119
+ resolver).
87
120
 
88
121
  ## Notes
89
122
 
90
- - **Honest limitation.** Claude Code hooks are **append-only** — history cannot
91
- be trimmed from hooks, so true O(1) is not possible. The hooks inject state
92
- into the compaction summary (PreCompact) and re-inject it after compaction
93
- (SessionStart), but the conversation history keeps growing until the host
94
- trims it.
95
- - The generated scripts are self-contained CommonJS and embed the schema, so
96
- unknown keys / wrong types are rejected and **malformed outputs are never
97
- persisted** — state corruption by a bad patch is impossible.
98
- - Depends on [`@skillstate/core`](../core) for the ⊕ merge semantics
99
- (`mergeState`), `PromptTransformer`, `atomicWriteFile`, and `resolveStatePath`.
123
+ - **Honest limitation.** Claude Code hooks cannot trim history and cannot
124
+ inject context at compaction time, so prompts are O(T) with fresh state
125
+ per turn. The injected state is authoritative — history is not.
126
+ - The generated scripts are self-contained CommonJS. Malformed patches are
127
+ never persisted — the ⊕ merge either fully applies or the hook reports a
128
+ `systemMessage` and leaves the state file untouched.
129
+ - Depends on [`@skillstate/core`](../core) for `PromptTransformer`,
130
+ `atomicWriteFile`, `resolveStatePath`, and the shared
131
+ `resolveHostStateForCwd`.
100
132
 
101
133
  ## Related
102
134
 
@@ -1,17 +1,37 @@
1
- /**
2
- * @non-paper adapter — no adapters exist in arXiv 2608.26263v3.
3
- *
4
- * This file bridges the paper-exact core (Algorithm 1 prompt, ⊕ merge,
5
- * §7 rollback-retry rejection) into Claude Code sessions via hook scripts
6
- * and prompt boilerplate.
7
- *
8
- * LIMITATION: Claude Code hooks are append-only — history cannot be trimmed
9
- * from hooks. The best strategy is: PreCompact injects state into the
10
- * compaction summary, SessionStart(source:compact) re-injects state after
11
- * compaction. True O(1) is not possible without host-side trimming.
12
- */
13
1
  import type { SkillState, StatePatch, ProceduralSpec, Observation, PlatformAdapter } from '@skillstate/core';
14
2
  import type { StatePathRef } from '@skillstate/core';
3
+ export { resolveHostStateForCwd as resolveStateForCwd } from '@skillstate/core';
4
+ /** Claude Code hook events this adapter generates scripts for (script/CLI names). */
5
+ export type ClaudeHookEvent = 'user-prompt-submit' | 'session-start-compact' | 'post-tool-use';
6
+ /** All {@link ClaudeHookEvent} values in generation order. */
7
+ export declare const CLAUDE_HOOK_EVENTS: readonly ["user-prompt-submit", "session-start-compact", "post-tool-use"];
8
+ /** SessionStart matcher that fires after Claude Code compacts the conversation. */
9
+ export declare const CLAUDE_SESSION_START_MATCHER = "^compact$";
10
+ /** PostToolUse matcher restricted to Bash tool results. */
11
+ export declare const CLAUDE_POST_TOOL_USE_MATCHER = "^Bash$";
12
+ /**
13
+ * Hook `timeout` in seconds written into every generated hook entry — the
14
+ * UserPromptSubmit default, spelled out so the budget is explicit.
15
+ */
16
+ export declare const CLAUDE_HOOK_TIMEOUT_SECONDS = 30;
17
+ /** Options for {@link ClaudeAdapter.generateHooksConfig} / merge. */
18
+ export interface ClaudeHooksConfigOptions {
19
+ /**
20
+ * Directory holding the generated `.cjs` hook scripts. Defaults to the
21
+ * state file's directory when a `statePath` is given, else a
22
+ * `<stateDir>/hooks` placeholder; the CLI install passes
23
+ * `~/.claude/hooks/skillstate`.
24
+ */
25
+ scriptDir?: string;
26
+ /** Full command override for every event (defaults to `node <script> <event>`). */
27
+ command?: string;
28
+ /** Hook `timeout` in seconds (default {@link CLAUDE_HOOK_TIMEOUT_SECONDS}). */
29
+ timeoutSeconds?: number;
30
+ }
31
+ /**
32
+ * Claude Code platform adapter (@non-paper; see module doc for the 2.1.260
33
+ * hooks contract and the honest O(T) limitation).
34
+ */
15
35
  export declare class ClaudeAdapter implements PlatformAdapter {
16
36
  readonly name = "claude";
17
37
  private transformer;
@@ -19,59 +39,131 @@ export declare class ClaudeAdapter implements PlatformAdapter {
19
39
  extractPatch(response: string): StatePatch | null;
20
40
  extractAction(response: string): string | null;
21
41
  /**
22
- * @non-paper — adapter convenience (delegates to the transformer).
42
+ * @non-paper adapter convenience (delegates to the transformer).
23
43
  * Paper-exact callers use `PromptTransformer.formatPaper` (Appendix A.4).
24
44
  */
25
45
  formatPrompt(state: SkillState, observation: Observation, spec: ProceduralSpec): string;
26
- generateHookScript(eventType: 'PreToolUse' | 'PostToolUse', statePath: string, schema?: ProceduralSpec['schema']): string;
27
46
  /**
28
- * @non-paper additive overload: accept a `{ root, name }` ref confined
29
- * via `resolveStatePath` — `..` escapes throw instead of embedding an
30
- * unsafe path into the generated script. The string overload above is
31
- * byte-identical to the pre-wave-2 codegen.
47
+ * Canonical absolute path of the hook script for `event` inside
48
+ * `scriptDir` (e.g. `~/.claude/hooks/skillstate/user-prompt-submit.cjs`).
49
+ * {@link generateHooksConfig} and {@link saveHookScript} share this
50
+ * convention so the settings.json commands and the on-disk scripts agree.
32
51
  */
33
- generateHookScript(eventType: 'PreToolUse' | 'PostToolUse', stateRef: StatePathRef, schema?: ProceduralSpec['schema']): string;
52
+ claudeHookScriptPath(scriptDir: string, event: ClaudeHookEvent): string;
34
53
  /**
35
- * @non-paper additive helper: generate a hook script and persist it via
36
- * `atomicWriteFile` (tmp + fsync + rename). Both the destination and the
37
- * embedded state path accept raw strings or
38
- * `{ root, name }` refs confined by `resolveStatePath`. Returns the
39
- * absolute destination path.
54
+ * Generate the hooks section for `~/.claude/settings.json` (2.1.260
55
+ * schema: `{ hooks: { Event: [ { matcher?, hooks: [ { type: "command",
56
+ * command, timeout } ] } ] } }`). The document carries ONLY the
57
+ * `hooks` key — {@link mergeHooksConfig} is what splices these groups
58
+ * into a live settings.json while preserving every other key:
59
+ *
60
+ * - `UserPromptSubmit` → inject the current state as additionalContext;
61
+ * - `SessionStart` (matcher `^compact$`) → re-inject after compaction;
62
+ * - `PostToolUse` (matcher `^Bash$`) → persist `state_patch` blocks from
63
+ * Bash tool outputs.
64
+ *
65
+ * Commands are absolute `node <script> <event>` lines pointing at the
66
+ * generated `.cjs` scripts in `options.scriptDir` (default: the state
67
+ * file's directory, else a `<stateDir>/hooks` placeholder). No matcher
68
+ * on UserPromptSubmit — the event has no matcher support and fires on
69
+ * every prompt.
40
70
  */
41
- saveHookScript(target: string | StatePathRef, eventType: 'PreToolUse' | 'PostToolUse', statePath: string | StatePathRef, schema?: ProceduralSpec['schema']): Promise<string>;
71
+ generateHooksConfig(statePath?: string | StatePathRef, options?: ClaudeHooksConfigOptions): string;
42
72
  /**
43
- * Generate a PreCompact hook script that injects the current skill state
44
- * into the compaction summary. Also tracks what changed since the last
45
- * compact to provide a diff in additionalContext.
73
+ * Generate a self-contained CommonJS hook script for a Claude Code
74
+ * lifecycle event. The script reads ONE hook JSON document from stdin,
75
+ * resolves the state file from `input.cwd` (the session cwd) via the
76
+ * {@link resolveStateForCwd} semantics, and:
77
+ *
78
+ * - `user-prompt-submit`: emits
79
+ * `{ hookSpecificOutput: { hookEventName: "UserPromptSubmit",
80
+ * additionalContext } }` carrying the current state JSON;
81
+ * - `session-start-compact`: the same injection with
82
+ * `hookEventName: "SessionStart"` (state survives compaction; wire
83
+ * with the `^compact$` matcher);
84
+ * - `post-tool-use`: extracts a `state_patch` from the tool_response
85
+ * (fenced ```json block or raw JSON), applies the ⊕ null-deletion merge
86
+ * and writes the state file; stdout is `{}` or a `systemMessage` when
87
+ * the patch is invalid.
46
88
  *
47
- * The script reads `.skillstate.json`, reads the previous compact snapshot
48
- * from `.skillstate.last-compact.json` (if it exists), computes a diff,
49
- * and injects the current state + diff into additionalContext. After
50
- * injection it saves the current state as the new compact snapshot.
89
+ * `statePath` is accepted for `{ root, name }` confinement (traversal
90
+ * refs throw) and documented in the script header; the content itself is
91
+ * cwd-resolving and never bakes an absolute state path in.
51
92
  */
52
- generateCompactHookScript(statePath: string, schema?: ProceduralSpec['schema']): string;
53
- generateCompactHookScript(stateRef: StatePathRef, schema?: ProceduralSpec['schema']): string;
93
+ generateHookScript(event: ClaudeHookEvent, statePath?: string | StatePathRef): string;
54
94
  /**
55
- * Generate a SessionStart hook script that re-injects state after
56
- * compaction. The hook uses a matcher for `source: "compact"` so it
57
- * only fires when the session was resumed from a compacted state.
95
+ * Generate a SKILL.md for Claude Code's skill directory
96
+ * (`~/.claude/skills/<name>/SKILL.md`). The body instructs the agent to
97
+ * treat the hook-injected state as authoritative (history is not
98
+ * reliable), to orient via `state.summary` (full dump via `state.get`),
99
+ * and to persist via `state.patch` — the PostToolUse hook also merges any
100
+ * fenced ```json `state_patch` block printed by a Bash tool call.
58
101
  */
59
- generateSessionStartHookScript(statePath: string): string;
60
- generateSessionStartHookScript(stateRef: StatePathRef): string;
102
+ generateSkillMd(spec: ProceduralSpec, statePath?: string): string;
61
103
  /**
62
- * Convenience: generate both compact-related hooks at once.
63
- * Returns `{ preCompact, sessionStartCompact }` — write each to a
64
- * `.cjs` file and register in Claude Code settings.
104
+ * Merge the skillstate hook groups into an existing `settings.json`
105
+ * text. Preserves every other top-level key (env, permissions, model,
106
+ * …) and every existing (non-skillstate) hook. Idempotent: if any
107
+ * skillstate command is already wired, the ORIGINAL text is returned
108
+ * byte-unchanged. Malformed/empty input starts from a fresh hooks-only
109
+ * document (the CLI guards a live settings.json before calling).
110
+ *
111
+ * The mechanics live in the shared {@link mergeHookGroups}; this method
112
+ * supplies only the format specifics (generated settings.json groups and
113
+ * the `node <script> <event>` skillstate commands).
114
+ */
115
+ mergeHooksConfig(existingJson: string, options?: ClaudeHooksConfigOptions): string;
116
+ /**
117
+ * Generate a hook script and persist it via the shared `saveGenerated`
118
+ * (atomic temp-rename write). `target` is the script destination (usually
119
+ * {@link ClaudeAdapter.claudeHookScriptPath}); `statePath` is forwarded
120
+ * to {@link generateHookScript}. Returns the absolute destination path.
121
+ */
122
+ saveHookScript(event: ClaudeHookEvent, target: string | StatePathRef, statePath?: string | StatePathRef): Promise<string>;
123
+ /**
124
+ * Generate the hooks config document and persist it via the shared
125
+ * `saveGenerated`. Both the destination and the embedded state path
126
+ * accept raw strings or `{ root, name }` refs confined by
127
+ * `resolveStatePath`. Returns the absolute destination path.
128
+ */
129
+ saveHooksConfig(target: string | StatePathRef, statePath?: string | StatePathRef, options?: ClaudeHooksConfigOptions): Promise<string>;
130
+ /**
131
+ * Generate a SKILL.md and persist it via the shared `saveGenerated`.
132
+ * Returns the absolute destination path.
65
133
  */
66
- generateAllHooksScripts(statePath: string, schema?: ProceduralSpec['schema']): {
67
- preCompact: string;
68
- sessionStartCompact: string;
69
- };
70
- generateAllHooksScripts(stateRef: StatePathRef, schema?: ProceduralSpec['schema']): {
71
- preCompact: string;
72
- sessionStartCompact: string;
73
- };
134
+ saveSkillMd(target: string | StatePathRef, spec: ProceduralSpec, statePath?: string): Promise<string>;
74
135
  generateAppendPrompt(): string;
75
- private describeSchema;
136
+ /**
137
+ * Inject-script template (`UserPromptSubmit` / `SessionStart`): brand
138
+ * header + the shared hook-runtime snippet ({@link hookRuntimeSnippet}
139
+ * inlined via `fn.toString()`) + a stdin loop that emits
140
+ * `{ hookSpecificOutput: { hookEventName, additionalContext } }` with the
141
+ * current state JSON read from the SESSION cwd. Brand specifics stay in
142
+ * the adapter (comment lines only); the `contextSuffix` is the shared
143
+ * {@link HISTORY_UNRELIABLE_NOTE} from `@skillstate/core`.
144
+ */
145
+ private buildInjectScriptTemplate;
146
+ /** PostToolUse script: extract state_patch, ⊕ merge, persist. */
147
+ private buildPostToolUseScript;
76
148
  }
149
+ /**
150
+ * Surgically remove every skillstate hook handler from an existing
151
+ * `settings.json` text (the uninstall path — restoring a backup would
152
+ * lose live settings, so groups are edited in place):
153
+ *
154
+ * - a handler is skillstate when its command points at a generated
155
+ * `<event>.cjs` script (matched by basename, independent of where the
156
+ * script dir lived);
157
+ * - groups whose handlers are ALL skillstate are dropped; MIXED groups
158
+ * keep their foreign handlers and lose only the skillstate ones;
159
+ * - event arrays left empty are removed from the `hooks` object;
160
+ * - every other top-level key (env, permissions, model, …) survives.
161
+ *
162
+ * Returns the original text untouched (`changed: false`) when it is
163
+ * malformed, has no hooks object, or carries no skillstate handlers.
164
+ */
165
+ export declare function removeSkillstateHookGroups(existingJson: string): {
166
+ text: string;
167
+ changed: boolean;
168
+ };
77
169
  //# sourceMappingURL=claude-adapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"claude-adapter.d.ts","sourceRoot":"","sources":["../src/claude-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,cAAc,EACd,WAAW,EACX,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAM1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,qBAAa,aAAc,YAAW,eAAe;IACnD,QAAQ,CAAC,IAAI,YAAY;IAEzB,OAAO,CAAC,WAAW,CAAiD;IAEpE,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,GAAG,MAAM,CA+B3D;IAED,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAEhD;IAED,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE7C;IAED;;;OAGG;IACH,YAAY,CACV,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,cAAc,GACnB,MAAM,CAER;IAED,kBAAkB,CAChB,SAAS,EAAE,YAAY,GAAG,aAAa,EACvC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,GAChC,MAAM,CAAC;IACV;;;;;OAKG;IACH,kBAAkB,CAChB,SAAS,EAAE,YAAY,GAAG,aAAa,EACvC,QAAQ,EAAE,YAAY,EACtB,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,GAChC,MAAM,CAAC;IAmJV;;;;;;OAMG;IACG,cAAc,CAClB,MAAM,EAAE,MAAM,GAAG,YAAY,EAC7B,SAAS,EAAE,YAAY,GAAG,aAAa,EACvC,SAAS,EAAE,MAAM,GAAG,YAAY,EAChC,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,GAChC,OAAO,CAAC,MAAM,CAAC,CAYjB;IAED;;;;;;;;;OASG;IACH,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;IACxF,yBAAyB,CAAC,QAAQ,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;IAuE7F;;;;OAIG;IACH,8BAA8B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1D,8BAA8B,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAAC;IA6B/D;;;;OAIG;IACH,uBAAuB,CACrB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,GAChC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,uBAAuB,CACrB,QAAQ,EAAE,YAAY,EACtB,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,GAChC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,MAAM,CAAA;KAAE,CAAC;IAWvD,oBAAoB,IAAI,MAAM,CAe7B;IAED,OAAO,CAAC,cAAc;CASvB"}
1
+ {"version":3,"file":"claude-adapter.d.ts","sourceRoot":"","sources":["../src/claude-adapter.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,70 @@
1
+ /**
2
+ * Claude Code adapter (2.1.260 hooks contract, verified against the Claude
3
+ * Code hooks reference, Sep 2026):
4
+ *
5
+ * - hooks are configured in `~/.claude/settings.json` (user scope) as
6
+ * `{ hooks: { Event: [ { matcher?, if?, hooks: [ { type: "command",
7
+ * command, timeout } ] } ] } }`; handler `timeout` is seconds;
8
+ * - `UserPromptSubmit` (+`prompt`): JSON stdout
9
+ * `{ hookSpecificOutput: { hookEventName: "UserPromptSubmit",
10
+ * additionalContext } }` is added to Claude's context (plain stdout is
11
+ * added too); no matcher support — fires on every prompt; default
12
+ * timeout 30s;
13
+ * - `SessionStart` (+`source`): matcher `^compact$` fires after auto or
14
+ * manual compaction and supports `additionalContext` — this is how state
15
+ * SURVIVES compaction;
16
+ * - `PostToolUse` (+`tool_name`, `tool_input`, `tool_response`): matcher
17
+ * `^Bash$` restricts to Bash results; stdout `{}` or a `systemMessage`
18
+ * when the response carried an invalid state patch.
19
+ *
20
+ * HONEST LIMITATION: history trimming from hooks is IMPOSSIBLE in Claude
21
+ * Code. The compact-adjacent events cannot inject context — the compaction
22
+ * hook supports only `decision: "block"` (forbid compaction) and the
23
+ * post-compaction hook has NO decision control (its `systemMessage` is
24
+ * discarded). So the model here is state-injection per prompt
25
+ * (`UserPromptSubmit`), survival through compaction
26
+ * (`SessionStart` matcher `^compact$`), patch persistence per Bash result
27
+ * (`PostToolUse`), and full read/write via the skillstate MCP tools
28
+ * (`state.get` / `state.patch`). Prompts stay O(T) with fresh state at
29
+ * every turn; true O(1) requires host-side trimming which the host does
30
+ * not expose.
31
+ *
32
+ * Every generated hook script is a SELF-CONTAINED CommonJS file (Node
33
+ * builtins only, no `@skillstate/*` import) that resolves the per-project
34
+ * state from `input.cwd` at runtime — one global `settings.json` hooks
35
+ * section + one script directory serve every project.
36
+ *
37
+ * @non-paper — no adapters exist in arXiv 2608.26263v3.
38
+ */
39
+ import * as path from 'node:path';
1
40
  import { PromptTransformer } from '@skillstate/core';
2
- import { atomicWriteFile, resolveStatePath, } from '@skillstate/core';
41
+ import { describeSchema, HISTORY_UNRELIABLE_NOTE, hookRuntimeSnippet, isPlainObject, mergeHookGroups, resolveTarget, saveGenerated, skillMdBody, STATE_PATCH_CONTRACT, } from '@skillstate/core';
42
+ export { resolveHostStateForCwd as resolveStateForCwd } from '@skillstate/core';
43
+ /** All {@link ClaudeHookEvent} values in generation order. */
44
+ export const CLAUDE_HOOK_EVENTS = [
45
+ 'user-prompt-submit',
46
+ 'session-start-compact',
47
+ 'post-tool-use',
48
+ ];
49
+ /** SessionStart matcher that fires after Claude Code compacts the conversation. */
50
+ export const CLAUDE_SESSION_START_MATCHER = '^compact$';
51
+ /** PostToolUse matcher restricted to Bash tool results. */
52
+ export const CLAUDE_POST_TOOL_USE_MATCHER = '^Bash$';
53
+ /**
54
+ * Hook `timeout` in seconds written into every generated hook entry — the
55
+ * UserPromptSubmit default, spelled out so the budget is explicit.
56
+ */
57
+ export const CLAUDE_HOOK_TIMEOUT_SECONDS = 30;
58
+ /**
59
+ * Claude Code platform adapter (@non-paper; see module doc for the 2.1.260
60
+ * hooks contract and the honest O(T) limitation).
61
+ */
3
62
  export class ClaudeAdapter {
4
63
  name = 'claude';
5
64
  transformer = new PromptTransformer({ platform: 'claude' });
6
65
  injectState(state, spec) {
7
66
  const stateJson = JSON.stringify(state);
8
- const schemaDesc = this.describeSchema(spec.schema);
67
+ const schemaDesc = describeSchema(spec.schema);
9
68
  return `# System
10
69
 
11
70
  You are ${spec.name}. ${spec.instructions}
@@ -22,17 +81,7 @@ ${stateJson}
22
81
 
23
82
  Based on your current state, provide your response with:
24
83
 
25
- 1. Step-by-step reasoning (will be discarded after execution)
26
- 2. A JSON block containing both your State Patch and your Action. The JSON block MUST have exactly these two keys:
27
-
28
- \`\`\`json
29
- {
30
- "state_patch": { "key": "new_value", "obsolete_key": null },
31
- "action": "your_action_here"
32
- }
33
- \`\`\`
34
-
35
- In \`state_patch\`, set keys to null to delete them. Only include fields you want to change. Omit fields to leave them unchanged.`;
84
+ ${STATE_PATCH_CONTRACT}`;
36
85
  }
37
86
  extractPatch(response) {
38
87
  return this.transformer.extractStatePatch(response);
@@ -41,283 +90,371 @@ In \`state_patch\`, set keys to null to delete them. Only include fields you wan
41
90
  return this.transformer.extractAction(response);
42
91
  }
43
92
  /**
44
- * @non-paper — adapter convenience (delegates to the transformer).
93
+ * @non-paper adapter convenience (delegates to the transformer).
45
94
  * Paper-exact callers use `PromptTransformer.formatPaper` (Appendix A.4).
46
95
  */
47
96
  formatPrompt(state, observation, spec) {
48
97
  return this.transformer.formatForClaude(spec, state, observation);
49
98
  }
50
- generateHookScript(eventType, statePathOrRef, schema) {
51
- const statePath = typeof statePathOrRef === 'string'
52
- ? statePathOrRef
53
- : resolveStatePath(statePathOrRef.root, statePathOrRef.name);
54
- const sp = JSON.stringify(statePath);
55
- if (eventType === 'PreToolUse') {
56
- return [
57
- '// Claude hook: PreToolUse',
58
- '// Reads skill state and injects it into the tool\'s additionalContext.',
59
- '// ADDITIVE: the host history is left untouched, so this alone does not',
60
- '// reproduce the paper O(1) footprint (see module doc).',
61
- 'const fs = require("fs");',
62
- 'const stateFilePath = ' + sp + ';',
63
- 'let state = {};',
64
- 'try {',
65
- ' if (fs.existsSync(stateFilePath)) {',
66
- ' state = JSON.parse(fs.readFileSync(stateFilePath, "utf-8"));',
67
- ' }',
68
- '} catch (e) { state = {}; }',
69
- 'const stateJson = JSON.stringify(state);',
70
- 'const output = {',
71
- ' hookSpecificOutput: {',
72
- ' additionalContext: "Current skill state (JSON): " + stateJson',
73
- ' }',
74
- '};',
75
- 'process.stdout.write(JSON.stringify(output));',
76
- ].join('\n');
99
+ /**
100
+ * Canonical absolute path of the hook script for `event` inside
101
+ * `scriptDir` (e.g. `~/.claude/hooks/skillstate/user-prompt-submit.cjs`).
102
+ * {@link generateHooksConfig} and {@link saveHookScript} share this
103
+ * convention so the settings.json commands and the on-disk scripts agree.
104
+ */
105
+ claudeHookScriptPath(scriptDir, event) {
106
+ return path.join(scriptDir, `${event}.cjs`);
107
+ }
108
+ /**
109
+ * Generate the hooks section for `~/.claude/settings.json` (2.1.260
110
+ * schema: `{ hooks: { Event: [ { matcher?, hooks: [ { type: "command",
111
+ * command, timeout } ] } ] } }`). The document carries ONLY the
112
+ * `hooks` key — {@link mergeHooksConfig} is what splices these groups
113
+ * into a live settings.json while preserving every other key:
114
+ *
115
+ * - `UserPromptSubmit` → inject the current state as additionalContext;
116
+ * - `SessionStart` (matcher `^compact$`) → re-inject after compaction;
117
+ * - `PostToolUse` (matcher `^Bash$`) → persist `state_patch` blocks from
118
+ * Bash tool outputs.
119
+ *
120
+ * Commands are absolute `node <script> <event>` lines pointing at the
121
+ * generated `.cjs` scripts in `options.scriptDir` (default: the state
122
+ * file's directory, else a `<stateDir>/hooks` placeholder). No matcher
123
+ * on UserPromptSubmit — the event has no matcher support and fires on
124
+ * every prompt.
125
+ */
126
+ generateHooksConfig(statePath, options) {
127
+ const scriptDir = options?.scriptDir ??
128
+ (statePath === undefined ? '<stateDir>/hooks' : path.dirname(resolveTarget(statePath)));
129
+ const command = (event) => options?.command ?? `node ${JSON.stringify(this.claudeHookScriptPath(scriptDir, event))} ${event}`;
130
+ const timeout = options?.timeoutSeconds ?? CLAUDE_HOOK_TIMEOUT_SECONDS;
131
+ const entry = (event) => ({
132
+ type: 'command',
133
+ command: command(event),
134
+ timeout,
135
+ });
136
+ const doc = {
137
+ hooks: {
138
+ UserPromptSubmit: [
139
+ {
140
+ hooks: [entry('user-prompt-submit')],
141
+ },
142
+ ],
143
+ SessionStart: [
144
+ {
145
+ matcher: CLAUDE_SESSION_START_MATCHER,
146
+ hooks: [
147
+ entry('session-start-compact'),
148
+ ],
149
+ },
150
+ ],
151
+ PostToolUse: [
152
+ {
153
+ matcher: CLAUDE_POST_TOOL_USE_MATCHER,
154
+ hooks: [entry('post-tool-use')],
155
+ },
156
+ ],
157
+ },
158
+ };
159
+ return `${JSON.stringify(doc, null, 2)}\n`;
160
+ }
161
+ /**
162
+ * Generate a self-contained CommonJS hook script for a Claude Code
163
+ * lifecycle event. The script reads ONE hook JSON document from stdin,
164
+ * resolves the state file from `input.cwd` (the session cwd) via the
165
+ * {@link resolveStateForCwd} semantics, and:
166
+ *
167
+ * - `user-prompt-submit`: emits
168
+ * `{ hookSpecificOutput: { hookEventName: "UserPromptSubmit",
169
+ * additionalContext } }` carrying the current state JSON;
170
+ * - `session-start-compact`: the same injection with
171
+ * `hookEventName: "SessionStart"` (state survives compaction; wire
172
+ * with the `^compact$` matcher);
173
+ * - `post-tool-use`: extracts a `state_patch` from the tool_response
174
+ * (fenced ```json block or raw JSON), applies the ⊕ null-deletion merge
175
+ * and writes the state file; stdout is `{}` or a `systemMessage` when
176
+ * the patch is invalid.
177
+ *
178
+ * `statePath` is accepted for `{ root, name }` confinement (traversal
179
+ * refs throw) and documented in the script header; the content itself is
180
+ * cwd-resolving and never bakes an absolute state path in.
181
+ */
182
+ generateHookScript(event, statePath) {
183
+ const resolved = statePath === undefined ? undefined : resolveTarget(statePath);
184
+ const header = `// State file (per-project resolver): ${resolved ?? '<cwd>/.skillstate/skillstate.json (global bucket when cwd === home)'}`;
185
+ if (event === 'post-tool-use') {
186
+ return this.buildPostToolUseScript(header);
77
187
  }
78
- // PostToolUse — schema-validated null-deletion merge. Malformed outputs
79
- // are rejected and never persisted (paper Limitations: malformed outputs
80
- // cannot corrupt Σt). Self-contained CommonJS (hook scripts run via
81
- // `node script.cjs`). The schema is embedded so unknown keys / wrong
82
- // types are rejected here instead of corrupting the persisted state.
83
- const fence = '`' + '`' + '`';
84
- const schemaJson = JSON.stringify(schema ?? {});
188
+ const hookEventName = event === 'session-start-compact' ? 'SessionStart' : 'UserPromptSubmit';
189
+ // A1 text is shared: both hosts append the SAME HISTORY_UNRELIABLE_NOTE
190
+ // (MCP tools + fenced state_patch channel) after the state JSON.
191
+ return this.buildInjectScriptTemplate({
192
+ header,
193
+ hookEventName,
194
+ contextSuffix: HISTORY_UNRELIABLE_NOTE,
195
+ });
196
+ }
197
+ /**
198
+ * Generate a SKILL.md for Claude Code's skill directory
199
+ * (`~/.claude/skills/<name>/SKILL.md`). The body instructs the agent to
200
+ * treat the hook-injected state as authoritative (history is not
201
+ * reliable), to orient via `state.summary` (full dump via `state.get`),
202
+ * and to persist via `state.patch` — the PostToolUse hook also merges any
203
+ * fenced ```json `state_patch` block printed by a Bash tool call.
204
+ */
205
+ generateSkillMd(spec, statePath) {
206
+ return skillMdBody({
207
+ hostLabel: 'Claude Code',
208
+ injectionPhrase: 'injected into your context via hooks',
209
+ spec,
210
+ statePath,
211
+ });
212
+ }
213
+ /**
214
+ * Merge the skillstate hook groups into an existing `settings.json`
215
+ * text. Preserves every other top-level key (env, permissions, model,
216
+ * …) and every existing (non-skillstate) hook. Idempotent: if any
217
+ * skillstate command is already wired, the ORIGINAL text is returned
218
+ * byte-unchanged. Malformed/empty input starts from a fresh hooks-only
219
+ * document (the CLI guards a live settings.json before calling).
220
+ *
221
+ * The mechanics live in the shared {@link mergeHookGroups}; this method
222
+ * supplies only the format specifics (generated settings.json groups and
223
+ * the `node <script> <event>` skillstate commands).
224
+ */
225
+ mergeHooksConfig(existingJson, options) {
226
+ const scriptDir = options?.scriptDir ?? '<stateDir>/hooks';
227
+ const command = (event) => `node ${JSON.stringify(this.claudeHookScriptPath(scriptDir, event))} ${event}`;
228
+ const generated = JSON.parse(this.generateHooksConfig(undefined, { ...options, scriptDir }));
229
+ return mergeHookGroups({
230
+ existingJson,
231
+ generatedGroups: generated.hooks,
232
+ commandsOf: new Set(CLAUDE_HOOK_EVENTS.map((event) => JSON.stringify(command(event)))),
233
+ });
234
+ }
235
+ /**
236
+ * Generate a hook script and persist it via the shared `saveGenerated`
237
+ * (atomic temp-rename write). `target` is the script destination (usually
238
+ * {@link ClaudeAdapter.claudeHookScriptPath}); `statePath` is forwarded
239
+ * to {@link generateHookScript}. Returns the absolute destination path.
240
+ */
241
+ async saveHookScript(event, target, statePath) {
242
+ return saveGenerated(target, this.generateHookScript(event, statePath));
243
+ }
244
+ /**
245
+ * Generate the hooks config document and persist it via the shared
246
+ * `saveGenerated`. Both the destination and the embedded state path
247
+ * accept raw strings or `{ root, name }` refs confined by
248
+ * `resolveStatePath`. Returns the absolute destination path.
249
+ */
250
+ async saveHooksConfig(target, statePath, options) {
251
+ return saveGenerated(target, this.generateHooksConfig(statePath, options));
252
+ }
253
+ /**
254
+ * Generate a SKILL.md and persist it via the shared `saveGenerated`.
255
+ * Returns the absolute destination path.
256
+ */
257
+ async saveSkillMd(target, spec, statePath) {
258
+ return saveGenerated(target, this.generateSkillMd(spec, statePath));
259
+ }
260
+ generateAppendPrompt() {
261
+ return `You are operating in state-based execution mode. Your state is maintained across steps.
262
+
263
+ After each step, you MUST respond with:
264
+
265
+ ${STATE_PATCH_CONTRACT}
266
+
267
+ - \`action\` indicates what you want to do next (e.g., "continue", "done", "deploy").
268
+ - Put anything you need to persist into \`state_patch\`.`;
269
+ }
270
+ /* ------------------------------------------------------------------ */
271
+ /* Internal helpers */
272
+ /* ------------------------------------------------------------------ */
273
+ /**
274
+ * Inject-script template (`UserPromptSubmit` / `SessionStart`): brand
275
+ * header + the shared hook-runtime snippet ({@link hookRuntimeSnippet}
276
+ * inlined via `fn.toString()`) + a stdin loop that emits
277
+ * `{ hookSpecificOutput: { hookEventName, additionalContext } }` with the
278
+ * current state JSON read from the SESSION cwd. Brand specifics stay in
279
+ * the adapter (comment lines only); the `contextSuffix` is the shared
280
+ * {@link HISTORY_UNRELIABLE_NOTE} from `@skillstate/core`.
281
+ */
282
+ buildInjectScriptTemplate(options) {
85
283
  return [
86
- '// Claude hook: PostToolUse',
87
- '// Extracts state_patch from the assistant\'s response, validates it against',
88
- '// the embedded schema, applies the null-deletion merge, and saves.',
284
+ '#!/usr/bin/env node',
285
+ `// skillstate Claude Code hook — ${options.hookEventName} (generated by @skillstate/claude).`,
286
+ '// Self-contained CommonJS: reads one hook JSON document on stdin,',
287
+ '// resolves the state from the SESSION cwd, and emits',
288
+ '// { hookSpecificOutput: { hookEventName, additionalContext } }.',
289
+ options.header,
290
+ "'use strict';",
89
291
  'const fs = require("fs");',
90
- 'const stateFilePath = ' + sp + ';',
91
- 'const schema = ' + schemaJson + ';',
292
+ 'const os = require("os");',
293
+ 'const path = require("path");',
92
294
  '',
93
- 'function isPlainObject(v) {',
94
- ' return typeof v === "object" && v !== null && !Array.isArray(v);',
95
- '}',
295
+ `const HOOK_EVENT_NAME = ${JSON.stringify(options.hookEventName)};`,
96
296
  '',
97
- '// ⊕ merge from the paper: null deletes a key, plain objects merge',
98
- '// recursively, everything else overwrites. Never mutates `base` —',
99
- '// builds and returns a copy.',
100
- 'function mergePatch(base, patch) {',
101
- ' function mergeInto(result, patchObj) {',
102
- ' for (const key of Object.keys(patchObj)) {',
103
- ' const value = patchObj[key];',
104
- ' if (value === null) {',
105
- ' delete result[key];',
106
- ' } else if (isPlainObject(value) && isPlainObject(result[key])) {',
107
- ' result[key] = mergeInto({ ...result[key] }, value);',
108
- ' } else {',
109
- ' result[key] = value;',
110
- ' }',
111
- ' }',
112
- ' return result;',
113
- ' }',
114
- ' return mergeInto({ ...base }, patch);',
115
- '}',
297
+ hookRuntimeSnippet(),
116
298
  '',
117
- '// Schema validation: unknown keys rejected; null is always valid (deletion).',
118
- 'function validatePatchAgainstSchema(patch) {',
119
- ' for (const key of Object.keys(patch)) {',
120
- ' const field = schema[key];',
121
- ' if (!field) {',
122
- ' return "Unknown key: " + key;',
123
- ' }',
124
- ' const value = patch[key];',
125
- ' if (value === null) continue;',
126
- ' const expected = field.type;',
127
- ' let ok = false;',
128
- ' if (expected === "string") ok = typeof value === "string";',
129
- ' else if (expected === "number") ok = typeof value === "number";',
130
- ' else if (expected === "boolean") ok = typeof value === "boolean";',
131
- ' else if (expected === "array") ok = Array.isArray(value);',
132
- ' else if (expected === "object") ok = isPlainObject(value);',
133
- ' if (!ok) {',
134
- ' return "Invalid type for field \'" + key + "\': expected " + expected +',
135
- ' ", got " + (Array.isArray(value) ? "array" : typeof value);',
136
- ' }',
137
- ' }',
138
- ' return null;',
139
- '}',
140
- '',
141
- 'let state = {};',
142
- 'try {',
143
- ' if (fs.existsSync(stateFilePath)) {',
144
- ' state = JSON.parse(fs.readFileSync(stateFilePath, "utf-8"));',
145
- ' }',
146
- '} catch (e) { state = {}; }',
147
- 'let input = "";',
299
+ 'let raw = "";',
148
300
  'process.stdin.setEncoding("utf-8");',
149
- 'process.stdin.on("data", (chunk) => { input += chunk; });',
301
+ 'process.stdin.on("data", (chunk) => { raw += chunk; });',
150
302
  'process.stdin.on("end", () => {',
151
- ' const output = {};',
303
+ ' let cwd = process.cwd();',
152
304
  ' try {',
153
- ' const parsed = JSON.parse(input);',
154
- ' const content = parsed.tool_response || parsed.content || "";',
155
- ' const re = /' + fence + 'json\\s*\\n?([\\s\\S]*?)\\n?\\s*' + fence + '/;',
156
- ' const match = content.match(re);',
157
- ' if (match) {',
158
- ' // Guarded parse: malformed JSON inside the fence leaves state untouched.',
159
- ' let json;',
160
- ' try {',
161
- ' json = JSON.parse(match[1]);',
162
- ' } catch (parseError) {',
163
- ' output.error = "Malformed JSON in state patch block: " + parseError.message;',
164
- ' process.stdout.write(JSON.stringify(output));',
165
- ' return;',
166
- ' }',
167
- ' if (json.state_patch && typeof json.state_patch === "object" && !Array.isArray(json.state_patch)) {',
168
- ' const validationError = validatePatchAgainstSchema(json.state_patch);',
169
- ' if (validationError) {',
170
- ' // Reject: report the error, never write state.',
171
- ' output.error = validationError;',
172
- ' process.stdout.write(JSON.stringify(output));',
173
- ' return;',
174
- ' }',
175
- ' state = mergePatch(state, json.state_patch);',
176
- ' fs.writeFileSync(stateFilePath, JSON.stringify(state, null, 2));',
177
- ' }',
305
+ ' const input = JSON.parse(raw);',
306
+ ' if (typeof input.cwd === "string" && input.cwd.length > 0) {',
307
+ ' cwd = input.cwd;',
178
308
  ' }',
179
- ' } catch (e) {',
180
- ' // Malformed stdin JSON or unexpected failure: state stays untouched.',
181
- ' output.error = "Failed to process PostToolUse input: " + e.message;',
182
- ' }',
309
+ ' } catch (error) {}',
310
+ ' const state = readStateEnvelope(',
311
+ ' resolveStatePathForCwd(path.resolve(cwd), path.resolve(os.homedir())),',
312
+ ' (p) => fs.readFileSync(p, "utf-8"),',
313
+ ' );',
314
+ ' const output = {',
315
+ ' hookSpecificOutput: {',
316
+ ' hookEventName: HOOK_EVENT_NAME,',
317
+ ' additionalContext: "Current skill state (JSON): " + JSON.stringify(state)',
318
+ ` + ${JSON.stringify(options.contextSuffix)},`,
319
+ ' },',
320
+ ' };',
183
321
  ' process.stdout.write(JSON.stringify(output));',
184
322
  '});',
323
+ '',
185
324
  ].join('\n');
186
325
  }
187
- /**
188
- * @non-paper additive helper: generate a hook script and persist it via
189
- * `atomicWriteFile` (tmp + fsync + rename). Both the destination and the
190
- * embedded state path accept raw strings or
191
- * `{ root, name }` refs confined by `resolveStatePath`. Returns the
192
- * absolute destination path.
193
- */
194
- async saveHookScript(target, eventType, statePath, schema) {
195
- const dest = typeof target === 'string'
196
- ? target
197
- : resolveStatePath(target.root, target.name);
198
- const resolvedState = typeof statePath === 'string'
199
- ? statePath
200
- : resolveStatePath(statePath.root, statePath.name);
201
- const script = this.generateHookScript(eventType, resolvedState, schema);
202
- await atomicWriteFile(dest, script);
203
- return dest;
204
- }
205
- generateCompactHookScript(statePathOrRef, schema) {
206
- const statePath = typeof statePathOrRef === 'string'
207
- ? statePathOrRef
208
- : resolveStatePath(statePathOrRef.root, statePathOrRef.name);
209
- const sp = JSON.stringify(statePath);
210
- const schemaJson = JSON.stringify(schema ?? {});
211
- const lastCompactPath = JSON.stringify(statePath + '.last-compact.json');
326
+ /** PostToolUse script: extract state_patch, ⊕ merge, persist. */
327
+ buildPostToolUseScript(header) {
328
+ const fence = '```';
212
329
  return [
213
- '// Claude hook: PreCompact',
214
- '// Injects the current skill state into the compaction summary.',
215
- '// Tracks diff since last compact for incremental context.',
330
+ '#!/usr/bin/env node',
331
+ '// skillstate Claude Code hook — PostToolUse (generated by @skillstate/claude).',
332
+ '// Self-contained CommonJS: reads one hook JSON document on stdin,',
333
+ '// extracts state_patch from the tool_response (fenced ```json block or',
334
+ '// raw JSON), applies the null-deletion merge and writes the state file.',
335
+ '// stdout is "{}" or a systemMessage when the patch is invalid.',
336
+ header,
337
+ "'use strict';",
216
338
  'const fs = require("fs");',
217
- 'const stateFilePath = ' + sp + ';',
218
- 'const lastCompactFilePath = ' + lastCompactPath + ';',
219
- 'const schema = ' + schemaJson + ';',
220
- '',
221
- 'function readJsonSafe(filePath) {',
222
- ' try {',
223
- ' if (fs.existsSync(filePath)) {',
224
- ' return JSON.parse(fs.readFileSync(filePath, "utf-8"));',
225
- ' }',
226
- ' } catch {}',
227
- ' return {};',
228
- '}',
339
+ 'const os = require("os");',
340
+ 'const path = require("path");',
229
341
  '',
230
- 'const current = readJsonSafe(stateFilePath);',
231
- 'const lastCompact = readJsonSafe(lastCompactFilePath);',
342
+ `const FENCE = ${JSON.stringify(fence)};`,
232
343
  '',
233
- '// Compute diff: keys added, changed, or deleted since last compact.',
234
- 'const diff = {};',
235
- 'const allKeys = new Set([...Object.keys(current), ...Object.keys(lastCompact)]);',
236
- 'for (const key of allKeys) {',
237
- ' const cur = current[key];',
238
- ' const prev = lastCompact[key];',
239
- ' if (cur === undefined) {',
240
- ' diff[key] = "(deleted)";',
241
- ' } else if (prev === undefined) {',
242
- ' diff[key] = cur;',
243
- ' } else if (JSON.stringify(cur) !== JSON.stringify(prev)) {',
244
- ' diff[key] = { from: prev, to: cur };',
245
- ' }',
246
- '}',
247
- '',
248
- 'const contextParts = [',
249
- ' "Current skill state (JSON): " + JSON.stringify(current),',
250
- '];',
251
- 'if (Object.keys(diff).length > 0) {',
252
- ' contextParts.push("Changes since last compact: " + JSON.stringify(diff));',
253
- '}',
344
+ hookRuntimeSnippet(),
254
345
  '',
255
- 'const output = {',
256
- ' hookSpecificOutput: {',
257
- ' additionalContext: contextParts.join("\\n")',
346
+ 'let raw = "";',
347
+ 'process.stdin.setEncoding("utf-8");',
348
+ 'process.stdin.on("data", (chunk) => { raw += chunk; });',
349
+ 'process.stdin.on("end", () => {',
350
+ ' const output = {};',
351
+ ' try {',
352
+ ' const input = JSON.parse(raw);',
353
+ ' let cwd = process.cwd();',
354
+ ' if (typeof input.cwd === "string" && input.cwd.length > 0) {',
355
+ ' cwd = input.cwd;',
356
+ ' }',
357
+ ' const statePath = resolveStatePathForCwd(path.resolve(cwd), path.resolve(os.homedir()));',
358
+ ' const response = input.tool_response;',
359
+ ' let result;',
360
+ ' if (isPlainObject(response) && isPlainObject(response.state_patch)) {',
361
+ ' result = { patch: response.state_patch };',
362
+ ' } else {',
363
+ ' const text = readResponseText(response);',
364
+ ' result = findFencedPatch(text);',
365
+ ' if (result.absent) result = findRawPatch(text);',
366
+ ' }',
367
+ ' if (result.patch !== undefined) {',
368
+ ' const merged = mergePatch(',
369
+ ' readStateEnvelope(statePath, (p) => fs.readFileSync(p, "utf-8")),',
370
+ ' result.patch,',
371
+ ' );',
372
+ ' try {',
373
+ ' fs.mkdirSync(path.dirname(statePath), { recursive: true });',
374
+ ' saveStateEnvelope(statePath, merged, (p, data) => fs.writeFileSync(p, data));',
375
+ ' } catch (writeError) {',
376
+ " output.systemMessage = 'skillstate: failed to persist state (' + writeError.message + ')';",
377
+ ' }',
378
+ ' process.stdout.write(JSON.stringify(output));',
379
+ ' return;',
380
+ ' }',
381
+ ' if (result.invalid) {',
382
+ ' output.systemMessage =',
383
+ ' "skillstate: ignored an invalid state patch (expected a " + FENCE + "json block with a state_patch object)";',
384
+ ' }',
385
+ ' } catch (error) {',
386
+ ' output.systemMessage = "skillstate: failed to process PostToolUse input: " + error.message;',
258
387
  ' }',
259
- '};',
260
- '',
261
- '// Save current state as the new compact snapshot.',
262
- 'try {',
263
- ' fs.writeFileSync(lastCompactFilePath, JSON.stringify(current, null, 2));',
264
- '} catch {}',
388
+ ' process.stdout.write(JSON.stringify(output));',
389
+ '});',
265
390
  '',
266
- 'process.stdout.write(JSON.stringify(output));',
267
391
  ].join('\n');
268
392
  }
269
- generateSessionStartHookScript(statePathOrRef) {
270
- const statePath = typeof statePathOrRef === 'string'
271
- ? statePathOrRef
272
- : resolveStatePath(statePathOrRef.root, statePathOrRef.name);
273
- const sp = JSON.stringify(statePath);
274
- return [
275
- '// Claude hook: SessionStart (source: compact)',
276
- '// Re-injects skill state after compaction so the model retains',
277
- '// execution context even though history was compressed.',
278
- 'const fs = require("fs");',
279
- 'const stateFilePath = ' + sp + ';',
280
- 'let state = {};',
281
- 'try {',
282
- ' if (fs.existsSync(stateFilePath)) {',
283
- ' state = JSON.parse(fs.readFileSync(stateFilePath, "utf-8"));',
284
- ' }',
285
- '} catch {}',
286
- 'const output = {',
287
- ' hookSpecificOutput: {',
288
- ' additionalContext: "Skill state restored after compaction: " + JSON.stringify(state)',
289
- ' }',
290
- '};',
291
- 'process.stdout.write(JSON.stringify(output));',
292
- ].join('\n');
393
+ }
394
+ /**
395
+ * Surgically remove every skillstate hook handler from an existing
396
+ * `settings.json` text (the uninstall path — restoring a backup would
397
+ * lose live settings, so groups are edited in place):
398
+ *
399
+ * - a handler is skillstate when its command points at a generated
400
+ * `<event>.cjs` script (matched by basename, independent of where the
401
+ * script dir lived);
402
+ * - groups whose handlers are ALL skillstate are dropped; MIXED groups
403
+ * keep their foreign handlers and lose only the skillstate ones;
404
+ * - event arrays left empty are removed from the `hooks` object;
405
+ * - every other top-level key (env, permissions, model, …) survives.
406
+ *
407
+ * Returns the original text untouched (`changed: false`) when it is
408
+ * malformed, has no hooks object, or carries no skillstate handlers.
409
+ */
410
+ export function removeSkillstateHookGroups(existingJson) {
411
+ let doc;
412
+ try {
413
+ doc = JSON.parse(existingJson);
293
414
  }
294
- generateAllHooksScripts(statePathOrRef, schema) {
295
- return {
296
- preCompact: this.generateCompactHookScript(statePathOrRef, schema),
297
- sessionStartCompact: this.generateSessionStartHookScript(statePathOrRef),
298
- };
415
+ catch {
416
+ return { text: existingJson, changed: false };
299
417
  }
300
- generateAppendPrompt() {
301
- return `You are operating in state-based execution mode. Your state is maintained across steps.
302
-
303
- After each step, you MUST respond with a JSON block containing your State Patch and your Action. The JSON block MUST have exactly these two keys:
304
-
305
- \`\`\`json
306
- {
307
- "state_patch": { "field_to_update": "new_value", "obsolete_field": null },
308
- "action": "next_action_name"
309
- }
310
- \`\`\`
311
-
312
- - In \`state_patch\`, set keys to null to delete them. Only include fields you want to change. Omit fields to leave them unchanged.
313
- - \`action\` indicates what you want to do next (e.g., "continue", "done", "deploy").
314
- - Reasoning is discarded after execution — put anything you need to persist into \`state_patch\`.`;
418
+ if (!isPlainObject(doc) || !isPlainObject(doc['hooks'])) {
419
+ return { text: existingJson, changed: false };
420
+ }
421
+ const scriptBasenames = CLAUDE_HOOK_EVENTS.map((event) => `${event}.cjs`);
422
+ const isSkillstateCommand = (command) => typeof command === 'string' && scriptBasenames.some((b) => command.includes(b));
423
+ const hooks = doc['hooks'];
424
+ let changed = false;
425
+ for (const event of Object.keys(hooks)) {
426
+ const groups = hooks[event];
427
+ if (!Array.isArray(groups))
428
+ continue;
429
+ const keptGroups = [];
430
+ let eventChanged = false;
431
+ for (const group of groups) {
432
+ if (!isPlainObject(group) || !Array.isArray(group['hooks'])) {
433
+ keptGroups.push(group);
434
+ continue;
435
+ }
436
+ const handlers = group['hooks'];
437
+ const keptHandlers = handlers.filter((handler) => !(isPlainObject(handler) && isSkillstateCommand(handler['command'])));
438
+ if (keptHandlers.length === handlers.length) {
439
+ keptGroups.push(group);
440
+ continue;
441
+ }
442
+ eventChanged = true;
443
+ if (keptHandlers.length > 0) {
444
+ keptGroups.push({ ...group, hooks: keptHandlers });
445
+ }
446
+ }
447
+ if (keptGroups.length === 0) {
448
+ delete hooks[event];
449
+ }
450
+ else if (eventChanged) {
451
+ hooks[event] = keptGroups;
452
+ }
453
+ changed = changed || eventChanged;
315
454
  }
316
- describeSchema(schema) {
317
- const fields = Object.entries(schema)
318
- .map(([name, field]) => `- ${name} (${field.type}): ${field.description ?? 'no description'}`)
319
- .join('\n');
320
- return `## Schema\n${fields}`;
455
+ if (!changed) {
456
+ return { text: existingJson, changed: false };
321
457
  }
458
+ return { text: `${JSON.stringify(doc, null, 2)}\n`, changed: true };
322
459
  }
323
460
  //# sourceMappingURL=claude-adapter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"claude-adapter.js","sourceRoot":"","sources":["../src/claude-adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claude-adapter.js","sourceRoot":"","sources":["../src/claude-adapter.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skillstate/claude",
3
- "version": "2.0.6",
3
+ "version": "2.1.0",
4
4
  "description": "Claude Code platform adapter for the skillstate runtime.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",