@skillstate/core 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.
@@ -0,0 +1,61 @@
1
+ /**
2
+ * @non-paper Wave-5 shared adapter plumbing — the SINGLE SOURCE OF TRUTH
3
+ * for the state-path resolution, atomic persistence, and hooks-merge
4
+ * mechanics that were duplicated across the platform adapters (claude,
5
+ * codex). Adapters stay EVENT TABLES + brand constants + script/config
6
+ * generators; everything below is host-agnostic:
7
+ *
8
+ * - {@link resolveTarget}: the `string | StatePathRef` resolution every
9
+ * adapter save/generate methods shared (throws on `..` traversal);
10
+ * - {@link saveGenerated}: resolve + `atomicWriteFile` + return the dest —
11
+ * the body of every adapter `save` method;
12
+ * - {@link mergeHookGroups}: the hooks.json / settings.json merge —
13
+ * idempotent by skillstate commands, appends fresh groups, preserves
14
+ * every foreign group and top-level key. Format specifics (which groups
15
+ * to generate, which commands are "ours") are passed in by the adapter.
16
+ */
17
+ import type { StatePathRef } from './atomic-write.js';
18
+ /**
19
+ * Resolve a `string | StatePathRef` target via `resolveStatePath` — the
20
+ * exact logic every adapter's private `resolve` helper shared. Raw strings
21
+ * pass through; `{ root, name }` refs are confined to `root` (traversal
22
+ * throws).
23
+ */
24
+ export declare function resolveTarget(target: string | StatePathRef): string;
25
+ /**
26
+ * Persist adapter-generated content to `target` via `atomicWriteFile`
27
+ * (temp sibling + fsync + rename) and return the absolute destination
28
+ * path. The shared body of the adapter `save*` methods.
29
+ */
30
+ export declare function saveGenerated(target: string | StatePathRef, content: string): Promise<string>;
31
+ /** Parameters for {@link mergeHookGroups} (the adapter-provided specifics). */
32
+ export interface MergeHookGroupsParams {
33
+ /** The existing hooks document text (hooks.json / settings.json). */
34
+ existingJson: string;
35
+ /** The adapter-generated `{ Event: [group, …] }` groups to append. */
36
+ generatedGroups: Record<string, unknown[]>;
37
+ /**
38
+ * JSON-stringified skillstate commands (one per generated event script)
39
+ * — a handler whose stringified `command` is in this set marks the
40
+ * document as already wired.
41
+ */
42
+ commandsOf: ReadonlySet<string>;
43
+ }
44
+ /**
45
+ * Merge the skillstate hook groups into an existing hooks document — the
46
+ * shared mechanics of the claude and codex `mergeHooksConfig` methods:
47
+ *
48
+ * - malformed/empty/non-object input starts from a fresh document (the
49
+ * CLI guards a live config before calling);
50
+ * - idempotent: if ANY skillstate command is already wired, the ORIGINAL
51
+ * text is returned byte-unchanged (no re-serialization, no duplicate
52
+ * groups, no surprise reformatting of a hand-written file);
53
+ * - otherwise every generated group is APPENDED per event: existing
54
+ * (non-skillstate) groups and every other top-level key survive, and a
55
+ * non-array event value is replaced by the fresh group.
56
+ *
57
+ * Returns the merged document re-serialized (2-space indent, newline-
58
+ * terminated) — or the untouched input on the already-wired path.
59
+ */
60
+ export declare function mergeHookGroups({ existingJson, generatedGroups, commandsOf, }: MergeHookGroupsParams): string;
61
+ //# sourceMappingURL=adapter-shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-shared.d.ts","sourceRoot":"","sources":["../src/adapter-shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,MAAM,CAInE;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,GAAG,YAAY,EAC7B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED,+EAA+E;AAC/E,MAAM,WAAW,qBAAqB;IACpC,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3C;;;;OAIG;IACH,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACjC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,EAC9B,YAAY,EACZ,eAAe,EACf,UAAU,GACX,EAAE,qBAAqB,GAAG,MAAM,CAoChC"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @non-paper Wave-5 shared adapter plumbing — the SINGLE SOURCE OF TRUTH
3
+ * for the state-path resolution, atomic persistence, and hooks-merge
4
+ * mechanics that were duplicated across the platform adapters (claude,
5
+ * codex). Adapters stay EVENT TABLES + brand constants + script/config
6
+ * generators; everything below is host-agnostic:
7
+ *
8
+ * - {@link resolveTarget}: the `string | StatePathRef` resolution every
9
+ * adapter save/generate methods shared (throws on `..` traversal);
10
+ * - {@link saveGenerated}: resolve + `atomicWriteFile` + return the dest —
11
+ * the body of every adapter `save` method;
12
+ * - {@link mergeHookGroups}: the hooks.json / settings.json merge —
13
+ * idempotent by skillstate commands, appends fresh groups, preserves
14
+ * every foreign group and top-level key. Format specifics (which groups
15
+ * to generate, which commands are "ours") are passed in by the adapter.
16
+ */
17
+ import { atomicWriteFile, resolveStatePath } from './atomic-write.js';
18
+ import { isPlainObject } from './hook-runtime.js';
19
+ /**
20
+ * Resolve a `string | StatePathRef` target via `resolveStatePath` — the
21
+ * exact logic every adapter's private `resolve` helper shared. Raw strings
22
+ * pass through; `{ root, name }` refs are confined to `root` (traversal
23
+ * throws).
24
+ */
25
+ export function resolveTarget(target) {
26
+ return typeof target === 'string'
27
+ ? target
28
+ : resolveStatePath(target.root, target.name);
29
+ }
30
+ /**
31
+ * Persist adapter-generated content to `target` via `atomicWriteFile`
32
+ * (temp sibling + fsync + rename) and return the absolute destination
33
+ * path. The shared body of the adapter `save*` methods.
34
+ */
35
+ export async function saveGenerated(target, content) {
36
+ const dest = resolveTarget(target);
37
+ await atomicWriteFile(dest, content);
38
+ return dest;
39
+ }
40
+ /**
41
+ * Merge the skillstate hook groups into an existing hooks document — the
42
+ * shared mechanics of the claude and codex `mergeHooksConfig` methods:
43
+ *
44
+ * - malformed/empty/non-object input starts from a fresh document (the
45
+ * CLI guards a live config before calling);
46
+ * - idempotent: if ANY skillstate command is already wired, the ORIGINAL
47
+ * text is returned byte-unchanged (no re-serialization, no duplicate
48
+ * groups, no surprise reformatting of a hand-written file);
49
+ * - otherwise every generated group is APPENDED per event: existing
50
+ * (non-skillstate) groups and every other top-level key survive, and a
51
+ * non-array event value is replaced by the fresh group.
52
+ *
53
+ * Returns the merged document re-serialized (2-space indent, newline-
54
+ * terminated) — or the untouched input on the already-wired path.
55
+ */
56
+ export function mergeHookGroups({ existingJson, generatedGroups, commandsOf, }) {
57
+ let doc = {};
58
+ try {
59
+ doc = JSON.parse(existingJson);
60
+ }
61
+ catch {
62
+ // Missing or malformed input: start from a fresh document.
63
+ }
64
+ if (!isPlainObject(doc)) {
65
+ doc = {};
66
+ }
67
+ if (!isPlainObject(doc['hooks'])) {
68
+ doc['hooks'] = {};
69
+ }
70
+ const hooks = doc['hooks'];
71
+ let alreadyWired = false;
72
+ for (const groups of Object.values(hooks)) {
73
+ if (!Array.isArray(groups))
74
+ continue;
75
+ for (const group of groups) {
76
+ if (!isPlainObject(group) || !Array.isArray(group['hooks']))
77
+ continue;
78
+ for (const handler of group['hooks']) {
79
+ if (isPlainObject(handler) && commandsOf.has(JSON.stringify(handler['command']))) {
80
+ alreadyWired = true;
81
+ }
82
+ }
83
+ }
84
+ }
85
+ if (alreadyWired) {
86
+ return existingJson;
87
+ }
88
+ for (const [event, groups] of Object.entries(generatedGroups)) {
89
+ const existing = Array.isArray(hooks[event])
90
+ ? hooks[event]
91
+ : [];
92
+ hooks[event] = [...existing, ...groups];
93
+ }
94
+ return `${JSON.stringify(doc, null, 2)}\n`;
95
+ }
96
+ //# sourceMappingURL=adapter-shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-shared.js","sourceRoot":"","sources":["../src/adapter-shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAEtE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,MAA6B;IACzD,OAAO,OAAO,MAAM,KAAK,QAAQ;QAC/B,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;AACjD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAA6B,EAC7B,OAAe;IAEf,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC;AACd,CAAC;AAgBD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,YAAY,EACZ,eAAe,EACf,UAAU,GACY;IACtB,IAAI,GAAG,GAA4B,EAAE,CAAC;IACtC,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAe,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,2DAA2D;IAC7D,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,GAAG,GAAG,EAAE,CAAC;IACX,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACjC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IACpB,CAAC;IACD,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAA4B,CAAC;IACtD,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,SAAS;QACrC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAAE,SAAS;YACtE,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;gBACrC,IAAI,aAAa,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;oBACjF,YAAY,GAAG,IAAI,CAAC;gBACtB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;QAC9D,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1C,CAAC,CAAE,KAAK,CAAC,KAAK,CAAe;YAC7B,CAAC,CAAC,EAAE,CAAC;QACP,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,QAAQ,EAAE,GAAG,MAAM,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * @non-paper Wave-5 hook runtime — the SINGLE SOURCE OF TRUTH for every
3
+ * piece of logic embedded into self-contained generated hook scripts
4
+ * (Claude Code `.cjs` hooks, Codex `.cjs` hooks) and reused directly by
5
+ * the OpenCode plugin.
6
+ *
7
+ * CONSTRAINT: the generated scripts cannot import `@skillstate/*`, so the
8
+ * adapters inline these functions into the emitted `.cjs` via
9
+ * `fn.toString()` (see {@link hookRuntimeSnippet}). That means every
10
+ * function body below must be PLAIN JavaScript:
11
+ *
12
+ * - no imports and no `require` — dependencies are passed as parameters
13
+ * (`readFile`, `writeFile`, `home`), so the caller wires the real
14
+ * `node:fs`/`node:os`/`node:path` (or test mocks) at the call site;
15
+ * - type annotations live ONLY in the signatures — both `tsc` (dist) and
16
+ * the vitest/esbuild transform erase them, so `fn.toString()` yields a
17
+ * valid CJS snippet;
18
+ * - no references to module-scope helpers — each function is either fully
19
+ * self-contained or calls only its sibling functions from this module
20
+ * (which the snippet inlines together).
21
+ *
22
+ * The parity suite (`tests/core/hook-runtime-parity.test.ts`) evals the
23
+ * snippets extracted from the generated scripts and asserts byte-identical
24
+ * behavior against these originals, so the "embedded copy" can no longer
25
+ * drift from the source of truth.
26
+ */
27
+ /** True for plain (non-null, non-array) objects. */
28
+ export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
29
+ /**
30
+ * Resolve the per-project state file for a working directory — the pure,
31
+ * dependency-free mirror of `resolveHostStateForCwd`
32
+ * (`<cwd>/.skillstate/skillstate.json`; the global bucket
33
+ * `<home>/.skillstate/global/skillstate.json` when cwd equals home).
34
+ *
35
+ * String arithmetic only (POSIX): absolute paths are normalized like
36
+ * `path.resolve` (empty/`.` segments dropped, `..` popped, trailing
37
+ * slashes trimmed); relative inputs stay relative because there is no
38
+ * `process` access. Callers that may see relative paths resolve them
39
+ * first (`path.resolve(cwd)`) — the generated hook scripts do exactly
40
+ * that. `home` must be provided to detect the global bucket; when it is
41
+ * omitted the project path is returned.
42
+ */
43
+ export declare function resolveStatePathForCwd(cwd: string, home?: string): string;
44
+ /**
45
+ * Read the state file through the injected `readFile` (real `fs` in
46
+ * generated scripts, mocks in tests). The on-disk envelope is
47
+ * `{ version: 1, state }`; a bare object is tolerated and treated as the
48
+ * state itself; anything else (missing file, corrupt JSON, arrays,
49
+ * scalars) yields `{}` — best-effort, never throws.
50
+ */
51
+ export declare function readStateEnvelope(statePath: string, readFile: (p: string) => string): unknown;
52
+ /**
53
+ * Persist the state through the injected `writeFile` as the
54
+ * `{ version: 1, state }` envelope (pretty-printed, newline-terminated).
55
+ * Throws on failure — the caller decides whether to swallow it (OpenCode
56
+ * plugin) or surface a `systemMessage` (PostToolUse hooks).
57
+ */
58
+ export declare function saveStateEnvelope(statePath: string, state: object, writeFile: (p: string, data: string) => void): void;
59
+ /**
60
+ * Paper ⊕ merge: `null` deletes a key, nested plain objects merge
61
+ * recursively, everything else replaces. Pure — neither `state` nor
62
+ * `patch` is mutated.
63
+ */
64
+ export declare function mergePatch(state: Record<string, unknown>, patch: Record<string, unknown>): Record<string, unknown>;
65
+ /**
66
+ * Coerce a tool response into text: strings pass through, plain objects
67
+ * expose their `content` then `text` string field, other objects are
68
+ * JSON-stringified, null/undefined becomes `""`, everything else is
69
+ * `String()`-ed.
70
+ */
71
+ export declare function readResponseText(response: unknown): string;
72
+ /** Outcome of the patch extractors: a patch, an invalid attempt, or nothing. */
73
+ export type PatchLookup = {
74
+ patch: Record<string, unknown>;
75
+ } | {
76
+ invalid: true;
77
+ } | {
78
+ absent: true;
79
+ };
80
+ /**
81
+ * Look for a fenced ```json block: `{ patch }` when it parses and carries
82
+ * an object-shaped `state_patch`, `{ invalid: true }` when a block exists
83
+ * but is malformed (an open fence that never closes — truncated output —
84
+ * is still a patch attempt and classifies as invalid), `{ absent: true }`
85
+ * when there is no block at all.
86
+ */
87
+ export declare function findFencedPatch(text: string): PatchLookup;
88
+ /**
89
+ * Fallback: a raw JSON object with `state_patch` anywhere in the text
90
+ * (first `{` … last `}`). Ordinary JSON output without a `state_patch`
91
+ * key is simply not a patch (`{ absent: true }`); a `state_patch` key
92
+ * holding a non-object is an invalid attempt.
93
+ */
94
+ export declare function findRawPatch(text: string): PatchLookup;
95
+ /**
96
+ * Assemble the CJS snippet embedded into every generated hook script:
97
+ * all sibling functions of this module, source-verbatim via
98
+ * `fn.toString()`. The adapters splice this block after their `require`
99
+ * preamble, which keeps the embedded logic byte-identical across hosts
100
+ * and impossible to drift from this module.
101
+ */
102
+ export declare function hookRuntimeSnippet(): string;
103
+ //# sourceMappingURL=hook-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-runtime.d.ts","sourceRoot":"","sources":["../src/hook-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,oDAAoD;AACpD,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE9E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAyBzE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,GAC9B,OAAO,CAaT;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,GAC3C,IAAI,CAEN;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAazB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,CAQ1D;AAED,gFAAgF;AAChF,MAAM,MAAM,WAAW,GACnB;IAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAClC;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,MAAM,EAAE,IAAI,CAAA;CAAE,CAAC;AAErB;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAczD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CA4BtD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAa3C"}
@@ -0,0 +1,224 @@
1
+ /**
2
+ * @non-paper Wave-5 hook runtime — the SINGLE SOURCE OF TRUTH for every
3
+ * piece of logic embedded into self-contained generated hook scripts
4
+ * (Claude Code `.cjs` hooks, Codex `.cjs` hooks) and reused directly by
5
+ * the OpenCode plugin.
6
+ *
7
+ * CONSTRAINT: the generated scripts cannot import `@skillstate/*`, so the
8
+ * adapters inline these functions into the emitted `.cjs` via
9
+ * `fn.toString()` (see {@link hookRuntimeSnippet}). That means every
10
+ * function body below must be PLAIN JavaScript:
11
+ *
12
+ * - no imports and no `require` — dependencies are passed as parameters
13
+ * (`readFile`, `writeFile`, `home`), so the caller wires the real
14
+ * `node:fs`/`node:os`/`node:path` (or test mocks) at the call site;
15
+ * - type annotations live ONLY in the signatures — both `tsc` (dist) and
16
+ * the vitest/esbuild transform erase them, so `fn.toString()` yields a
17
+ * valid CJS snippet;
18
+ * - no references to module-scope helpers — each function is either fully
19
+ * self-contained or calls only its sibling functions from this module
20
+ * (which the snippet inlines together).
21
+ *
22
+ * The parity suite (`tests/core/hook-runtime-parity.test.ts`) evals the
23
+ * snippets extracted from the generated scripts and asserts byte-identical
24
+ * behavior against these originals, so the "embedded copy" can no longer
25
+ * drift from the source of truth.
26
+ */
27
+ /** True for plain (non-null, non-array) objects. */
28
+ export function isPlainObject(value) {
29
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
30
+ }
31
+ /**
32
+ * Resolve the per-project state file for a working directory — the pure,
33
+ * dependency-free mirror of `resolveHostStateForCwd`
34
+ * (`<cwd>/.skillstate/skillstate.json`; the global bucket
35
+ * `<home>/.skillstate/global/skillstate.json` when cwd equals home).
36
+ *
37
+ * String arithmetic only (POSIX): absolute paths are normalized like
38
+ * `path.resolve` (empty/`.` segments dropped, `..` popped, trailing
39
+ * slashes trimmed); relative inputs stay relative because there is no
40
+ * `process` access. Callers that may see relative paths resolve them
41
+ * first (`path.resolve(cwd)`) — the generated hook scripts do exactly
42
+ * that. `home` must be provided to detect the global bucket; when it is
43
+ * omitted the project path is returned.
44
+ */
45
+ export function resolveStatePathForCwd(cwd, home) {
46
+ const normalize = (p) => {
47
+ const isAbsolute = p.startsWith('/');
48
+ const segments = [];
49
+ for (const segment of p.split('/')) {
50
+ if (segment === '' || segment === '.')
51
+ continue;
52
+ if (segment === '..') {
53
+ if (segments.length > 0 && segments[segments.length - 1] !== '..') {
54
+ segments.pop();
55
+ }
56
+ else if (!isAbsolute) {
57
+ segments.push('..');
58
+ }
59
+ continue;
60
+ }
61
+ segments.push(segment);
62
+ }
63
+ return (isAbsolute ? '/' : '') + segments.join('/');
64
+ };
65
+ const rootless = (p) => (p === '/' ? '' : p);
66
+ const resolvedCwd = normalize(cwd);
67
+ const resolvedHome = home === undefined || home === null ? '' : normalize(home);
68
+ if (resolvedCwd === resolvedHome) {
69
+ return `${rootless(resolvedHome)}/.skillstate/global/skillstate.json`;
70
+ }
71
+ return `${rootless(resolvedCwd)}/.skillstate/skillstate.json`;
72
+ }
73
+ /**
74
+ * Read the state file through the injected `readFile` (real `fs` in
75
+ * generated scripts, mocks in tests). The on-disk envelope is
76
+ * `{ version: 1, state }`; a bare object is tolerated and treated as the
77
+ * state itself; anything else (missing file, corrupt JSON, arrays,
78
+ * scalars) yields `{}` — best-effort, never throws.
79
+ */
80
+ export function readStateEnvelope(statePath, readFile) {
81
+ try {
82
+ const parsed = JSON.parse(readFile(statePath));
83
+ if (isPlainObject(parsed)) {
84
+ if (isPlainObject(parsed.state)) {
85
+ return parsed.state;
86
+ }
87
+ return parsed;
88
+ }
89
+ }
90
+ catch {
91
+ // Missing or corrupt state file — fall back to the empty state.
92
+ }
93
+ return {};
94
+ }
95
+ /**
96
+ * Persist the state through the injected `writeFile` as the
97
+ * `{ version: 1, state }` envelope (pretty-printed, newline-terminated).
98
+ * Throws on failure — the caller decides whether to swallow it (OpenCode
99
+ * plugin) or surface a `systemMessage` (PostToolUse hooks).
100
+ */
101
+ export function saveStateEnvelope(statePath, state, writeFile) {
102
+ writeFile(statePath, `${JSON.stringify({ version: 1, state }, null, 2)}\n`);
103
+ }
104
+ /**
105
+ * Paper ⊕ merge: `null` deletes a key, nested plain objects merge
106
+ * recursively, everything else replaces. Pure — neither `state` nor
107
+ * `patch` is mutated.
108
+ */
109
+ export function mergePatch(state, patch) {
110
+ const result = { ...state };
111
+ for (const key of Object.keys(patch)) {
112
+ const value = patch[key];
113
+ if (value === null) {
114
+ delete result[key];
115
+ }
116
+ else if (isPlainObject(value) && isPlainObject(result[key])) {
117
+ result[key] = mergePatch(result[key], value);
118
+ }
119
+ else {
120
+ result[key] = value;
121
+ }
122
+ }
123
+ return result;
124
+ }
125
+ /**
126
+ * Coerce a tool response into text: strings pass through, plain objects
127
+ * expose their `content` then `text` string field, other objects are
128
+ * JSON-stringified, null/undefined becomes `""`, everything else is
129
+ * `String()`-ed.
130
+ */
131
+ export function readResponseText(response) {
132
+ if (typeof response === 'string')
133
+ return response;
134
+ if (isPlainObject(response)) {
135
+ if (typeof response['content'] === 'string')
136
+ return response['content'];
137
+ if (typeof response['text'] === 'string')
138
+ return response['text'];
139
+ return JSON.stringify(response);
140
+ }
141
+ return response === null || response === undefined ? '' : String(response);
142
+ }
143
+ /**
144
+ * Look for a fenced ```json block: `{ patch }` when it parses and carries
145
+ * an object-shaped `state_patch`, `{ invalid: true }` when a block exists
146
+ * but is malformed (an open fence that never closes — truncated output —
147
+ * is still a patch attempt and classifies as invalid), `{ absent: true }`
148
+ * when there is no block at all.
149
+ */
150
+ export function findFencedPatch(text) {
151
+ const match = text.match(/```json\s*\n?([\s\S]*?)\n?\s*```/) ||
152
+ text.match(/```json\s*\n?([\s\S]+)$/);
153
+ if (!match)
154
+ return { absent: true };
155
+ try {
156
+ const parsed = JSON.parse(match[1]);
157
+ if (isPlainObject(parsed) && isPlainObject(parsed['state_patch'])) {
158
+ return { patch: parsed['state_patch'] };
159
+ }
160
+ }
161
+ catch {
162
+ // Malformed fenced JSON — report an invalid patch attempt.
163
+ }
164
+ return { invalid: true };
165
+ }
166
+ /**
167
+ * Fallback: a raw JSON object with `state_patch` anywhere in the text
168
+ * (first `{` … last `}`). Ordinary JSON output without a `state_patch`
169
+ * key is simply not a patch (`{ absent: true }`); a `state_patch` key
170
+ * holding a non-object is an invalid attempt.
171
+ */
172
+ export function findRawPatch(text) {
173
+ const trimmed = text.trim();
174
+ const candidates = [];
175
+ try {
176
+ candidates.push(JSON.parse(trimmed));
177
+ }
178
+ catch {
179
+ // Not a whole-text JSON object — try the braced slice below.
180
+ }
181
+ const first = trimmed.indexOf('{');
182
+ const last = trimmed.lastIndexOf('}');
183
+ if (first !== -1 && last > first) {
184
+ try {
185
+ candidates.push(JSON.parse(trimmed.slice(first, last + 1)));
186
+ }
187
+ catch {
188
+ // The braced slice is not JSON either — no candidates left.
189
+ }
190
+ }
191
+ for (const candidate of candidates) {
192
+ if (isPlainObject(candidate)) {
193
+ if (isPlainObject(candidate['state_patch'])) {
194
+ return { patch: candidate['state_patch'] };
195
+ }
196
+ if (Object.prototype.hasOwnProperty.call(candidate, 'state_patch')) {
197
+ return { invalid: true };
198
+ }
199
+ }
200
+ }
201
+ return { absent: true };
202
+ }
203
+ /**
204
+ * Assemble the CJS snippet embedded into every generated hook script:
205
+ * all sibling functions of this module, source-verbatim via
206
+ * `fn.toString()`. The adapters splice this block after their `require`
207
+ * preamble, which keeps the embedded logic byte-identical across hosts
208
+ * and impossible to drift from this module.
209
+ */
210
+ export function hookRuntimeSnippet() {
211
+ return [
212
+ isPlainObject,
213
+ resolveStatePathForCwd,
214
+ readStateEnvelope,
215
+ saveStateEnvelope,
216
+ mergePatch,
217
+ readResponseText,
218
+ findFencedPatch,
219
+ findRawPatch,
220
+ ]
221
+ .map((fn) => fn.toString())
222
+ .join('\n\n');
223
+ }
224
+ //# sourceMappingURL=hook-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-runtime.js","sourceRoot":"","sources":["../src/hook-runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Resolve the per-project state file for a working directory —
3
+ * `<cwd>/.skillstate/skillstate.json`, or the global bucket
4
+ * `<home>/.skillstate/global/skillstate.json` when cwd equals home
5
+ * (`home` defaults to `os.homedir()`).
6
+ */
7
+ export declare function resolveHostStateForCwd(cwd: string, home?: string): string;
8
+ //# sourceMappingURL=host-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-state.d.ts","sourceRoot":"","sources":["../src/host-state.ts"],"names":[],"mappings":"AAiBA;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAOzE"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @non-paper Wave-4 DX helper — the canonical per-project state resolver
3
+ * shared by every host adapter (OpenCode plugin, Codex hooks/fork-trim,
4
+ * Claude Code hooks).
5
+ *
6
+ * Semantics: the state file for a working directory is
7
+ * `<cwd>/.skillstate/skillstate.json`; a session opened directly in the
8
+ * user's home resolves to the global bucket
9
+ * `<home>/.skillstate/global/skillstate.json`. Pure path arithmetic — no
10
+ * filesystem access. Host-embedded hook scripts (self-contained `.cjs`)
11
+ * keep a byte-equivalent copy of this logic because they must run without
12
+ * importing `@skillstate/*`; this function is the single source of truth
13
+ * the copies mirror.
14
+ */
15
+ import * as os from 'node:os';
16
+ import * as path from 'node:path';
17
+ /**
18
+ * Resolve the per-project state file for a working directory —
19
+ * `<cwd>/.skillstate/skillstate.json`, or the global bucket
20
+ * `<home>/.skillstate/global/skillstate.json` when cwd equals home
21
+ * (`home` defaults to `os.homedir()`).
22
+ */
23
+ export function resolveHostStateForCwd(cwd, home) {
24
+ const resolvedCwd = path.resolve(cwd);
25
+ const resolvedHome = path.resolve(home ?? os.homedir());
26
+ if (resolvedCwd === resolvedHome) {
27
+ return path.join(resolvedHome, '.skillstate', 'global', 'skillstate.json');
28
+ }
29
+ return path.join(resolvedCwd, '.skillstate', 'skillstate.json');
30
+ }
31
+ //# sourceMappingURL=host-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-state.js","sourceRoot":"","sources":["../src/host-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAW,EAAE,IAAa;IAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;IACxD,IAAI,WAAW,KAAK,YAAY,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,EAAE,iBAAiB,CAAC,CAAC;AAClE,CAAC"}
package/dist/index.d.ts CHANGED
@@ -15,6 +15,10 @@ export * from './events.js';
15
15
  export * from './logger.js';
16
16
  export * from './provider.js';
17
17
  export * from './config.js';
18
+ export * from './host-state.js';
19
+ export * from './hook-runtime.js';
20
+ export * from './adapter-shared.js';
21
+ export * from './prompt-contract.js';
18
22
  export * from './shutdown.js';
19
23
  export * from './schemas/index.js';
20
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AAErC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAElC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAE5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AAErC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAElC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAE5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,qBAAqB,CAAC;AAEpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -23,6 +23,15 @@ export * from './logger.js';
23
23
  // @non-paper Wave-4 DX helpers (additive, opt-in).
24
24
  export * from './provider.js';
25
25
  export * from './config.js';
26
+ export * from './host-state.js';
27
+ // @non-paper Wave-5 hook runtime (single source of truth for generated
28
+ // hook scripts and the OpenCode plugin).
29
+ export * from './hook-runtime.js';
30
+ // @non-paper Wave-5 shared adapter plumbing (resolve/save/merge helpers
31
+ // reused by the claude/codex adapters).
32
+ export * from './adapter-shared.js';
33
+ // @non-paper Wave-5 deduplicated prompt texts (shared adapter vocabulary).
34
+ export * from './prompt-contract.js';
26
35
  export * from './shutdown.js';
27
36
  export * from './schemas/index.js';
28
37
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,EAAE;AACF,0EAA0E;AAC1E,6EAA6E;AAC7E,qDAAqD;AACrD,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,qEAAqE;AACrE,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,0EAA0E;AAC1E,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,mDAAmD;AACnD,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,EAAE;AACF,0EAA0E;AAC1E,6EAA6E;AAC7E,qDAAqD;AACrD,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,qEAAqE;AACrE,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,0EAA0E;AAC1E,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,mDAAmD;AACnD,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,uEAAuE;AACvE,yCAAyC;AACzC,cAAc,mBAAmB,CAAC;AAClC,wEAAwE;AACxE,wCAAwC;AACxC,cAAc,qBAAqB,CAAC;AACpC,2EAA2E;AAC3E,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * @non-paper Canonical prompt texts — the SINGLE SOURCE OF TRUTH for the
3
+ * {state_patch, action} JSON contract, the history-unreliability hint, the
4
+ * schema renderer, and the SKILL.md body shared by every platform adapter.
5
+ *
6
+ * PROMPT-FIDELITY BOUNDARY: `PromptTransformer.formatPaper` (Appendix A.4)
7
+ * is byte-verbatim paper text and deliberately does NOT use these
8
+ * constants — its inline `{ "state_patch": { <dict: ...> }, "action": ... }`
9
+ * directive differs from the fenced example below by design. Everything
10
+ * here is the @non-paper adapter vocabulary, deduplicated across
11
+ * claude/codex/opencode adapters and the prompt transformer.
12
+ */
13
+ import type { ProceduralSpec, StateSchema } from './types.js';
14
+ /**
15
+ * The two-key response directive (without the fenced example). Adapters
16
+ * prepend their own lead-in ("Based on your current state, provide your
17
+ * response with:" etc.) and append the numbered items via
18
+ * {@link STATE_PATCH_CONTRACT}.
19
+ */
20
+ export declare const STATE_PATCH_CONTRACT_HEADER = "A JSON block containing both your State Patch and your Action. The JSON block MUST have exactly these two keys:";
21
+ /** Canonical fenced ```json example block for the two-key contract. */
22
+ export declare const STATE_PATCH_EXAMPLE_JSON: string;
23
+ /** Canonical sparse-patch rules: null deletes, omissions leave state unchanged. */
24
+ export declare const STATE_PATCH_RULES = "In `state_patch`, set keys to null to delete them. Only include fields you want to change. Omit fields to leave them unchanged.";
25
+ /**
26
+ * The reasoning-is-discarded persistence bullet (paper §3.2, §4): any fact
27
+ * that must survive belongs in `state_patch`, never in the conversation.
28
+ */
29
+ export declare const REASONING_DISCARDED_NOTE = "Reasoning is discarded after execution \u2014 put anything you need to persist into `state_patch`.";
30
+ /**
31
+ * The full numbered response contract: reasoning is discarded (paper §3.2),
32
+ * the JSON block carries exactly the two keys, and the patch follows the
33
+ * sparse ⊕ semantics. Includes the example block and the rules — no lead-in.
34
+ */
35
+ export declare const STATE_PATCH_CONTRACT: string;
36
+ /**
37
+ * The single history-unreliability hint appended to the additionalContext
38
+ * of every inject-style hook script (claude + codex alike). Names the MCP
39
+ * tools AND the fenced ```json state_patch channel — one text for all
40
+ * hosts, so the Bash-carried patch option can no longer drift away.
41
+ */
42
+ export declare const HISTORY_UNRELIABLE_NOTE = "\nHistory is not reliable. Persist anything you need via the skillstate MCP tools (state.summary / state.patch) or a fenced ```json state_patch block.";
43
+ /**
44
+ * Render a state schema as the shared `## Schema` markdown block used by
45
+ * every prompt formatter and adapter `injectState`. Fields without a
46
+ * description fall back to "no description".
47
+ */
48
+ export declare function describeSchema(schema: StateSchema): string;
49
+ /** Options for {@link skillMdBody}. */
50
+ export interface SkillMdBodyOptions {
51
+ /** Brand label woven into the hooks intro ("Claude Code", "Codex"). */
52
+ hostLabel: string;
53
+ /**
54
+ * How the injected state reaches the model, as a predicate:
55
+ * "injected into your context via hooks" (claude) /
56
+ * "provided as developer context" (codex).
57
+ */
58
+ injectionPhrase: string;
59
+ /** The skill spec — name/instructions/version fill the frontmatter. */
60
+ spec: ProceduralSpec;
61
+ /** State path written into the frontmatter and the body (default `./.skillstate/skillstate.json`). */
62
+ statePath?: string;
63
+ }
64
+ /**
65
+ * Generate the whole SKILL.md document shared by the hook-wiring adapters
66
+ * (claude, codex): identical frontmatter, Execution Context, and Process
67
+ * sections; the ONLY brand-specific parts are `hostLabel` (hooks intro)
68
+ * and `injectionPhrase` (how the state reaches the model). OpenCode keeps
69
+ * its own body — its history is trimmed by the plugin, not by hooks, so
70
+ * its Execution Context and Process genuinely differ.
71
+ */
72
+ export declare function skillMdBody(options: SkillMdBodyOptions): string;
73
+ //# sourceMappingURL=prompt-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-contract.d.ts","sourceRoot":"","sources":["../src/prompt-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9D;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,oHAC2E,CAAC;AAEpH,uEAAuE;AACvE,eAAO,MAAM,wBAAwB,QAOzB,CAAC;AAEb,mFAAmF;AACnF,eAAO,MAAM,iBAAiB,oIACqG,CAAC;AAEpI;;;GAGG;AACH,eAAO,MAAM,wBAAwB,uGAC4D,CAAC;AAElG;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,QAOrB,CAAC;AAEb;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,2JACsH,CAAC;AAE3J;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAQ1D;AAED,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB,uEAAuE;IACvE,IAAI,EAAE,cAAc,CAAC;IACrB,sGAAsG;IACtG,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAmD/D"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * The two-key response directive (without the fenced example). Adapters
3
+ * prepend their own lead-in ("Based on your current state, provide your
4
+ * response with:" etc.) and append the numbered items via
5
+ * {@link STATE_PATCH_CONTRACT}.
6
+ */
7
+ export const STATE_PATCH_CONTRACT_HEADER = 'A JSON block containing both your State Patch and your Action. The JSON block MUST have exactly these two keys:';
8
+ /** Canonical fenced ```json example block for the two-key contract. */
9
+ export const STATE_PATCH_EXAMPLE_JSON = [
10
+ '```json',
11
+ '{',
12
+ ' "state_patch": { "key": "new_value", "obsolete_key": null },',
13
+ ' "action": "your_action_here"',
14
+ '}',
15
+ '```',
16
+ ].join('\n');
17
+ /** Canonical sparse-patch rules: null deletes, omissions leave state unchanged. */
18
+ export const STATE_PATCH_RULES = 'In `state_patch`, set keys to null to delete them. Only include fields you want to change. Omit fields to leave them unchanged.';
19
+ /**
20
+ * The reasoning-is-discarded persistence bullet (paper §3.2, §4): any fact
21
+ * that must survive belongs in `state_patch`, never in the conversation.
22
+ */
23
+ export const REASONING_DISCARDED_NOTE = 'Reasoning is discarded after execution — put anything you need to persist into `state_patch`.';
24
+ /**
25
+ * The full numbered response contract: reasoning is discarded (paper §3.2),
26
+ * the JSON block carries exactly the two keys, and the patch follows the
27
+ * sparse ⊕ semantics. Includes the example block and the rules — no lead-in.
28
+ */
29
+ export const STATE_PATCH_CONTRACT = [
30
+ '1. Step-by-step reasoning (will be discarded after execution)',
31
+ `2. ${STATE_PATCH_CONTRACT_HEADER}`,
32
+ '',
33
+ STATE_PATCH_EXAMPLE_JSON,
34
+ '',
35
+ STATE_PATCH_RULES,
36
+ ].join('\n');
37
+ /**
38
+ * The single history-unreliability hint appended to the additionalContext
39
+ * of every inject-style hook script (claude + codex alike). Names the MCP
40
+ * tools AND the fenced ```json state_patch channel — one text for all
41
+ * hosts, so the Bash-carried patch option can no longer drift away.
42
+ */
43
+ export const HISTORY_UNRELIABLE_NOTE = '\nHistory is not reliable. Persist anything you need via the skillstate MCP tools (state.summary / state.patch) or a fenced ```json state_patch block.';
44
+ /**
45
+ * Render a state schema as the shared `## Schema` markdown block used by
46
+ * every prompt formatter and adapter `injectState`. Fields without a
47
+ * description fall back to "no description".
48
+ */
49
+ export function describeSchema(schema) {
50
+ const fields = Object.entries(schema)
51
+ .map(([name, field]) => `- ${name} (${field.type}): ${field.description ?? 'no description'}`)
52
+ .join('\n');
53
+ return `## Schema\n${fields}`;
54
+ }
55
+ /**
56
+ * Generate the whole SKILL.md document shared by the hook-wiring adapters
57
+ * (claude, codex): identical frontmatter, Execution Context, and Process
58
+ * sections; the ONLY brand-specific parts are `hostLabel` (hooks intro)
59
+ * and `injectionPhrase` (how the state reaches the model). OpenCode keeps
60
+ * its own body — its history is trimmed by the plugin, not by hooks, so
61
+ * its Execution Context and Process genuinely differ.
62
+ */
63
+ export function skillMdBody(options) {
64
+ const resolvedStatePath = options.statePath ?? './.skillstate/skillstate.json';
65
+ return [
66
+ '---',
67
+ `name: ${JSON.stringify(options.spec.name)}`,
68
+ `description: ${JSON.stringify(options.spec.instructions)}`,
69
+ `version: ${options.spec.version}`,
70
+ 'execution_context:',
71
+ ` state_path: ${resolvedStatePath}`,
72
+ ' format: json',
73
+ '---',
74
+ '',
75
+ `# ${options.spec.name}`,
76
+ '',
77
+ options.spec.instructions,
78
+ '',
79
+ '## Execution Context',
80
+ '',
81
+ `Your execution state lives at \`${resolvedStatePath}\` (per project; a`,
82
+ 'session started in $HOME uses `~/.skillstate/global/skillstate.json`).',
83
+ `The skillstate ${options.hostLabel} hooks:`,
84
+ '',
85
+ `- the CURRENT state is ${options.injectionPhrase} on every prompt submit`,
86
+ ' (`UserPromptSubmit`) and is re-injected after compaction',
87
+ ' (`SessionStart` matcher `^compact$`);',
88
+ '- watch every Bash tool result and merge a fenced ```json block carrying',
89
+ ' a `state_patch` into the state file (`PostToolUse`).',
90
+ '',
91
+ 'The injected state is authoritative — history is not reliable. Never',
92
+ 'reconstruct execution context from the conversation.',
93
+ '',
94
+ '## Process',
95
+ '',
96
+ '1. Orient yourself: read the injected state, or call the skillstate MCP',
97
+ ' tools `state.summary` (compact) / `state.get` (full dump).',
98
+ '2. Observe the result of your last action.',
99
+ '3. Reason about what to do next, given the state and the observation.',
100
+ '4. Persist progress with the skillstate MCP tool `state.patch` (sparse',
101
+ ' patch; set a key to `null` to delete it; dry-run first with',
102
+ ' `state.validate` when unsure; `state.diff` shows what changed since',
103
+ ' your last look), and/or emit a fenced JSON block with exactly two',
104
+ ' keys inside a Bash tool call so the `PostToolUse` hook merges it:',
105
+ '',
106
+ STATE_PATCH_EXAMPLE_JSON,
107
+ '',
108
+ `- ${STATE_PATCH_RULES}`,
109
+ '- Put anything you need to survive into `state_patch`; never rely on',
110
+ ' the conversation remembering it.',
111
+ '- `action` names what you will do next (e.g. "continue", "done").',
112
+ '',
113
+ ].join('\n');
114
+ }
115
+ //# sourceMappingURL=prompt-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-contract.js","sourceRoot":"","sources":["../src/prompt-contract.ts"],"names":[],"mappings":"AAcA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,2BAA2B,GACtC,iHAAiH,CAAC;AAEpH,uEAAuE;AACvE,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,SAAS;IACT,GAAG;IACH,gEAAgE;IAChE,gCAAgC;IAChC,GAAG;IACH,KAAK;CACN,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,mFAAmF;AACnF,MAAM,CAAC,MAAM,iBAAiB,GAC5B,iIAAiI,CAAC;AAEpI;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GACnC,+FAA+F,CAAC;AAElG;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,+DAA+D;IAC/D,MAAM,2BAA2B,EAAE;IACnC,EAAE;IACF,wBAAwB;IACxB,EAAE;IACF,iBAAiB;CAClB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAClC,wJAAwJ,CAAC;AAE3J;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,MAAmB;IAChD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;SAClC,GAAG,CACF,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAChB,KAAK,IAAI,KAAK,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC,WAAW,IAAI,gBAAgB,EAAE,CACxE;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,OAAO,cAAc,MAAM,EAAE,CAAC;AAChC,CAAC;AAkBD;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,OAA2B;IACrD,MAAM,iBAAiB,GAAG,OAAO,CAAC,SAAS,IAAI,+BAA+B,CAAC;IAC/E,OAAO;QACL,KAAK;QACL,SAAS,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAC5C,gBAAgB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE;QAC3D,YAAY,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE;QAClC,oBAAoB;QACpB,iBAAiB,iBAAiB,EAAE;QACpC,gBAAgB;QAChB,KAAK;QACL,EAAE;QACF,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE;QACxB,EAAE;QACF,OAAO,CAAC,IAAI,CAAC,YAAY;QACzB,EAAE;QACF,sBAAsB;QACtB,EAAE;QACF,mCAAmC,iBAAiB,oBAAoB;QACxE,wEAAwE;QACxE,kBAAkB,OAAO,CAAC,SAAS,SAAS;QAC5C,EAAE;QACF,0BAA0B,OAAO,CAAC,eAAe,yBAAyB;QAC1E,4DAA4D;QAC5D,yCAAyC;QACzC,0EAA0E;QAC1E,wDAAwD;QACxD,EAAE;QACF,sEAAsE;QACtE,sDAAsD;QACtD,EAAE;QACF,YAAY;QACZ,EAAE;QACF,yEAAyE;QACzE,+DAA+D;QAC/D,4CAA4C;QAC5C,uEAAuE;QACvE,wEAAwE;QACxE,gEAAgE;QAChE,wEAAwE;QACxE,sEAAsE;QACtE,sEAAsE;QACtE,EAAE;QACF,wBAAwB;QACxB,EAAE;QACF,KAAK,iBAAiB,EAAE;QACxB,sEAAsE;QACtE,oCAAoC;QACpC,mEAAmE;QACnE,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -98,9 +98,5 @@ export declare class PromptTransformer {
98
98
  serializeState(state: SkillState, options?: {
99
99
  pretty?: boolean;
100
100
  }, schema?: StateSchema): string;
101
- /**
102
- * Describe the schema fields for inclusion in prompts.
103
- */
104
- private describeSchema;
105
101
  }
106
102
  //# sourceMappingURL=prompt-transformer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-transformer.d.ts","sourceRoot":"","sources":["../src/prompt-transformer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EACV,WAAW,EACX,UAAU,EACV,WAAW,EACZ,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;CAC9C;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAC1B,UAAU,GACV,gBAAgB,GAChB,qBAAqB,GACrB,gBAAgB,CAAC;AAErB;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAC3B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC/C;IACE,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAMN;;;;;;;GAOG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAoC;IAEpD,YAAY,OAAO,CAAC,EAAE,wBAAwB,EAE7C;IAED;;;;;OAKG;IACH,YAAY,CACV,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,WAAW,EACxB,QAAQ,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,GAC3C,MAAM,CASR;IAED;;;;;OAKG;IACH,eAAe,CACb,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,WAAW,GACvB,MAAM,CAmCR;IAED;;;;OAIG;IACH,iBAAiB,CACf,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,WAAW,GACvB,MAAM,CAyBR;IAED;;;;;;;;;OASG;IACH,WAAW,CACT,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,WAAW,GACvB,MAAM,CAmBR;IAED;;;;;OAKG;IACH,OAAO,CAAC,aAAa;IAqCrB;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAGrD;IAED;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG7C;IAED;;;;;;;OAOG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB,CA2CnD;IAMD;;;;;OAKG;IACH,cAAc,CACZ,KAAK,EAAE,UAAU,EACjB,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,EAC9B,MAAM,CAAC,EAAE,WAAW,GACnB,MAAM,CAcR;IAED;;OAEG;IACH,OAAO,CAAC,cAAc;CAMvB"}
1
+ {"version":3,"file":"prompt-transformer.d.ts","sourceRoot":"","sources":["../src/prompt-transformer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EACV,WAAW,EACX,UAAU,EACV,WAAW,EACZ,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;CAC9C;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAC1B,UAAU,GACV,gBAAgB,GAChB,qBAAqB,GACrB,gBAAgB,CAAC;AAErB;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAC3B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC/C;IACE,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAMN;;;;;;;GAOG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAoC;IAEpD,YAAY,OAAO,CAAC,EAAE,wBAAwB,EAE7C;IAED;;;;;OAKG;IACH,YAAY,CACV,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,WAAW,EACxB,QAAQ,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,GAC3C,MAAM,CASR;IAED;;;;;OAKG;IACH,eAAe,CACb,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,WAAW,GACvB,MAAM,CAyBR;IAED;;;;OAIG;IACH,iBAAiB,CACf,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,WAAW,GACvB,MAAM,CAkBR;IAED;;;;;;;;;OASG;IACH,WAAW,CACT,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,WAAW,GACvB,MAAM,CAmBR;IAED;;;;;OAKG;IACH,OAAO,CAAC,aAAa;IA2BrB;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAGrD;IAED;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG7C;IAED;;;;;;;OAOG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB,CA2CnD;IAMD;;;;;OAKG;IACH,cAAc,CACZ,KAAK,EAAE,UAAU,EACjB,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,EAC9B,MAAM,CAAC,EAAE,WAAW,GACnB,MAAM,CAcR;CACF"}
@@ -1,3 +1,4 @@
1
+ import { STATE_PATCH_CONTRACT, describeSchema } from './prompt-contract.js';
1
2
  function isPlainObject(value) {
2
3
  return typeof value === 'object' && value !== null && !Array.isArray(value);
3
4
  }
@@ -38,7 +39,7 @@ export class PromptTransformer {
38
39
  */
39
40
  formatForClaude(spec, state, observation) {
40
41
  const stateJson = this.serializeState(state, undefined, spec.schema);
41
- const schemaDesc = this.describeSchema(spec.schema);
42
+ const schemaDesc = describeSchema(spec.schema);
42
43
  return `# System
43
44
 
44
45
  You are ${spec.name}. ${spec.instructions}
@@ -59,17 +60,7 @@ ${observation.content}
59
60
 
60
61
  Based on the observation and your current state, provide your response with:
61
62
 
62
- 1. Step-by-step reasoning (will be discarded after execution)
63
- 2. A JSON block containing both your State Patch and your Action. The JSON block MUST have exactly these two keys:
64
-
65
- \`\`\`json
66
- {
67
- "state_patch": { "key": "new_value", "obsolete_key": null },
68
- "action": "your_action_here"
69
- }
70
- \`\`\`
71
-
72
- In \`state_patch\`, set keys to null to delete them. Only include fields you want to change. Omit fields to leave them unchanged.`;
63
+ ${STATE_PATCH_CONTRACT}`;
73
64
  }
74
65
  /**
75
66
  * OpenCode-specific prompt format adapted for the opencode skill system.
@@ -78,7 +69,7 @@ In \`state_patch\`, set keys to null to delete them. Only include fields you wan
78
69
  */
79
70
  formatForOpenCode(spec, state, observation) {
80
71
  const stateJson = this.serializeState(state, undefined, spec.schema);
81
- const schemaDesc = this.describeSchema(spec.schema);
72
+ const schemaDesc = describeSchema(spec.schema);
82
73
  return `<skill name="${spec.id}">
83
74
  <instructions>${spec.instructions}</instructions>
84
75
  ${schemaDesc}
@@ -90,16 +81,9 @@ ${observation.content}
90
81
  </observation>
91
82
  </skill>
92
83
 
93
- Respond with step-by-step reasoning followed by a JSON block containing both your State Patch and your Action. The JSON block MUST have exactly these two keys:
94
-
95
- \`\`\`json
96
- {
97
- "state_patch": { "key": "new_value", "obsolete_key": null },
98
- "action": "action_name"
99
- }
100
- \`\`\`
84
+ Respond with:
101
85
 
102
- In \`state_patch\`, set keys to null to delete them. Only include fields you want to change. Omit fields to leave them unchanged.`;
86
+ ${STATE_PATCH_CONTRACT}`;
103
87
  }
104
88
  /**
105
89
  * Paper-exact prompt format — byte-verbatim Appendix A.4.
@@ -138,7 +122,7 @@ Provide your response with:
138
122
  */
139
123
  formatGeneric(spec, state, observation) {
140
124
  const stateJson = this.serializeState(state, undefined, spec.schema);
141
- const schemaDesc = this.describeSchema(spec.schema);
125
+ const schemaDesc = describeSchema(spec.schema);
142
126
  return `${spec.instructions}
143
127
 
144
128
  ${schemaDesc}
@@ -155,17 +139,7 @@ ${observation.content}
155
139
 
156
140
  Provide your response with:
157
141
 
158
- 1. Step-by-step reasoning (will be discarded after execution)
159
- 2. A JSON block containing both your State Patch and your Action. The JSON block MUST have exactly these two keys:
160
-
161
- \`\`\`json
162
- {
163
- "state_patch": { "key": "value", "obsolete_key": null },
164
- "action": "action_name"
165
- }
166
- \`\`\`
167
-
168
- In \`state_patch\`, set keys to null to delete them.`;
142
+ ${STATE_PATCH_CONTRACT}`;
169
143
  }
170
144
  /**
171
145
  * Extract the state_patch from an LLM response containing a fenced JSON block.
@@ -252,14 +226,5 @@ In \`state_patch\`, set keys to null to delete them.`;
252
226
  }
253
227
  return JSON.stringify(toSerialize);
254
228
  }
255
- /**
256
- * Describe the schema fields for inclusion in prompts.
257
- */
258
- describeSchema(schema) {
259
- const fields = Object.entries(schema)
260
- .map(([name, field]) => `- ${name} (${field.type}): ${field.description ?? 'no description'}`)
261
- .join('\n');
262
- return `## Schema\n${fields}`;
263
- }
264
229
  }
265
230
  //# sourceMappingURL=prompt-transformer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-transformer.js","sourceRoot":"","sources":["../src/prompt-transformer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prompt-transformer.js","sourceRoot":"","sources":["../src/prompt-transformer.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"state-manager.d.ts","sourceRoot":"","sources":["../src/state-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,WAAW,EAEX,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAMpB,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,WAAW,EACnB,SAAS,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAC9B,UAAU,CAWZ;AAcD,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,GAAG,UAAU,CAkB3E;AAgDD,wBAAgB,aAAa,CAC3B,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,UAAU,GAChB,gBAAgB,CAkBlB;AAMD,wBAAgB,cAAc,CAC5B,KAAK,EAAE,UAAU,EACjB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,MAAM,CAKR;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAEzD;AAMD,qBAAa,YAAY;IACvB,MAAM,CAAC,kBAAkB,4BAAsB;IAC/C,MAAM,CAAC,UAAU,oBAAc;IAC/B,MAAM,CAAC,aAAa,uBAAiB;IACrC,MAAM,CAAC,cAAc,wBAAkB;IACvC,MAAM,CAAC,gBAAgB,0BAAoB;CAC5C;AAMD,wBAAgB,kBAAkB;;;;;;EAQjC"}
1
+ {"version":3,"file":"state-manager.d.ts","sourceRoot":"","sources":["../src/state-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,WAAW,EAEX,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAOpB,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,WAAW,EACnB,SAAS,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAC9B,UAAU,CAWZ;AAkBD,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,GAAG,UAAU,CAE3E;AAyBD,wBAAgB,aAAa,CAC3B,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,UAAU,GAChB,gBAAgB,CAkBlB;AAMD,wBAAgB,cAAc,CAC5B,KAAK,EAAE,UAAU,EACjB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,MAAM,CAKR;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAEzD;AAMD,qBAAa,YAAY;IACvB,MAAM,CAAC,kBAAkB,4BAAsB;IAC/C,MAAM,CAAC,UAAU,oBAAc;IAC/B,MAAM,CAAC,aAAa,uBAAiB;IACrC,MAAM,CAAC,cAAc,wBAAkB;IACvC,MAAM,CAAC,gBAAgB,0BAAoB;CAC5C;AAMD,wBAAgB,kBAAkB;;;;;;EAQjC"}
@@ -1,3 +1,4 @@
1
+ import { mergePatch } from './hook-runtime.js';
1
2
  // ---------------------------------------------------------------------------
2
3
  // 1. createInitialState — Σ₀ from schema defaults + optional overrides
3
4
  // ---------------------------------------------------------------------------
@@ -19,41 +20,16 @@ export function createInitialState(schema, overrides) {
19
20
  // - null values DELETE the key entirely
20
21
  // - Nested dicts are merged recursively
21
22
  // - Original state is NOT mutated
23
+ //
24
+ // Delegates to the hook-runtime {@link mergePatch} — the single ⊕
25
+ // implementation shared with the generated hook scripts and the
26
+ // OpenCode plugin (one merge semantics everywhere).
22
27
  // ---------------------------------------------------------------------------
23
28
  function isPlainObject(value) {
24
29
  return typeof value === 'object' && value !== null && !Array.isArray(value);
25
30
  }
26
31
  export function mergeState(state, patch) {
27
- const result = { ...state };
28
- for (const [key, value] of Object.entries(patch)) {
29
- if (value === null) {
30
- delete result[key];
31
- }
32
- else if (isPlainObject(value) && isPlainObject(result[key])) {
33
- // Recursive merge for nested objects — apply null-deletion inside too
34
- result[key] = mergeNestedObjects(result[key], value);
35
- }
36
- else {
37
- result[key] = value;
38
- }
39
- }
40
- return result;
41
- }
42
- /** Deep merge two plain objects with null-deletion semantics. */
43
- function mergeNestedObjects(base, patch) {
44
- const result = { ...base };
45
- for (const [key, value] of Object.entries(patch)) {
46
- if (value === null) {
47
- delete result[key];
48
- }
49
- else if (isPlainObject(value) && isPlainObject(result[key])) {
50
- result[key] = mergeNestedObjects(result[key], value);
51
- }
52
- else {
53
- result[key] = value;
54
- }
55
- }
56
- return result;
32
+ return mergePatch(state, patch);
57
33
  }
58
34
  // ---------------------------------------------------------------------------
59
35
  // 3. validatePatch — reject unknown keys, wrong types; accept null for deletion
@@ -1 +1 @@
1
- {"version":3,"file":"state-manager.js","sourceRoot":"","sources":["../src/state-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"state-manager.js","sourceRoot":"","sources":["../src/state-manager.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skillstate/core",
3
- "version": "2.0.6",
3
+ "version": "2.1.0",
4
4
  "description": "Paper-exact skillstate runtime core (A.4 byte-verbatim formatPaper, §4.3 token tracker).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",