@vincemakes/kiso-core 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/governance/delivery.d.ts +15 -4
- package/dist/governance/delivery.js +15 -4
- package/dist/kernel/compaction.d.ts +3 -1
- package/dist/kernel/compaction.js +30 -3
- package/dist/kernel/event-log.d.ts +6 -1
- package/dist/kernel/event-log.js +7 -2
- package/dist/kernel/loop.d.ts +17 -7
- package/dist/kernel/loop.js +2 -2
- package/dist/kernel/mode.d.ts +10 -12
- package/dist/kernel/mode.js +10 -7
- package/dist/kernel/permission.d.ts +12 -3
- package/dist/kernel/permission.js +12 -3
- package/dist/kernel/project.d.ts +4 -2
- package/dist/kernel/project.js +4 -2
- package/dist/protocol/adapter.d.ts +3 -3
- package/dist/protocol/adapter.js +3 -3
- package/dist/protocol/events.d.ts +30 -12
- package/dist/protocol/extension.d.ts +1 -1
- package/dist/protocol/messages.d.ts +12 -3
- package/dist/protocol/messages.js +6 -1
- package/dist/tools/tool.d.ts +31 -19
- package/dist/tools/tool.js +9 -3
- package/package.json +2 -2
|
@@ -8,10 +8,21 @@
|
|
|
8
8
|
* the same events the loop yielded, so the verdict is replayable and the
|
|
9
9
|
* model's narration never participates in its own grading.
|
|
10
10
|
*
|
|
11
|
-
* Producers are
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* Producers are named by the CALLER, in `DeliveryConfig.producers` — the
|
|
12
|
+
* hand-maintained set is the ONLY source of delivery truth. SC-1b removed
|
|
13
|
+
* `Tool.delivers`, the flag this note used to describe as the eventual
|
|
14
|
+
* replacement: it was declared on the contract and read by nothing, here
|
|
15
|
+
* or anywhere. Should a tool's own declaration ever supersede the caller's
|
|
16
|
+
* set, it enters as a new field with a wiring and a gate, never as a
|
|
17
|
+
* standing promise the code has not kept.
|
|
18
|
+
*
|
|
19
|
+
* The verdict counts producer calls that COMPLETED (non-error results).
|
|
20
|
+
* `claimedInText` is computed and REPORTED but does not enter `passed` —
|
|
21
|
+
* a caller that wants "claimed but not delivered" to fail combines the two
|
|
22
|
+
* itself (the evals fixture does). With `required: false`, text claiming
|
|
23
|
+
* delivery over zero producer calls passes here. The canonical lie —
|
|
24
|
+
* "generated-document" with zero producer calls and a clean completed
|
|
25
|
+
* terminal — is caught by that combination.
|
|
15
26
|
*
|
|
16
27
|
* In M3.5 the emission side (artifact URLs extracted from results) joins;
|
|
17
28
|
* today a completed producer IS the emission.
|
|
@@ -8,10 +8,21 @@
|
|
|
8
8
|
* the same events the loop yielded, so the verdict is replayable and the
|
|
9
9
|
* model's narration never participates in its own grading.
|
|
10
10
|
*
|
|
11
|
-
* Producers are
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* Producers are named by the CALLER, in `DeliveryConfig.producers` — the
|
|
12
|
+
* hand-maintained set is the ONLY source of delivery truth. SC-1b removed
|
|
13
|
+
* `Tool.delivers`, the flag this note used to describe as the eventual
|
|
14
|
+
* replacement: it was declared on the contract and read by nothing, here
|
|
15
|
+
* or anywhere. Should a tool's own declaration ever supersede the caller's
|
|
16
|
+
* set, it enters as a new field with a wiring and a gate, never as a
|
|
17
|
+
* standing promise the code has not kept.
|
|
18
|
+
*
|
|
19
|
+
* The verdict counts producer calls that COMPLETED (non-error results).
|
|
20
|
+
* `claimedInText` is computed and REPORTED but does not enter `passed` —
|
|
21
|
+
* a caller that wants "claimed but not delivered" to fail combines the two
|
|
22
|
+
* itself (the evals fixture does). With `required: false`, text claiming
|
|
23
|
+
* delivery over zero producer calls passes here. The canonical lie —
|
|
24
|
+
* "generated-document" with zero producer calls and a clean completed
|
|
25
|
+
* terminal — is caught by that combination.
|
|
15
26
|
*
|
|
16
27
|
* In M3.5 the emission side (artifact URLs extracted from results) joins;
|
|
17
28
|
* today a completed producer IS the emission.
|
|
@@ -21,6 +21,8 @@ import type { Message } from "../protocol/messages.js";
|
|
|
21
21
|
/**
|
|
22
22
|
* Rough token estimate (chars/4 + structural overhead). Calibration-free on
|
|
23
23
|
* purpose: context economy only needs a stable MONOTONE proxy, not an exact
|
|
24
|
-
* count — the threshold absorbs the error (mauri ADR-0007).
|
|
24
|
+
* count — the threshold absorbs the error (mauri ADR-0007). The proxy's
|
|
25
|
+
* three-word contract, and the pins that hold it, are
|
|
26
|
+
* packages/core/tests/sc1b-estimator.test.ts.
|
|
25
27
|
*/
|
|
26
28
|
export declare function estimateTokens(messages: readonly Message[]): number;
|
|
@@ -17,16 +17,43 @@
|
|
|
17
17
|
* The model-generated half of context economy (the /compact summary layer)
|
|
18
18
|
* lives in kernel/summarize.ts.
|
|
19
19
|
*/
|
|
20
|
+
/**
|
|
21
|
+
* What a non-text block (an image) contributes. There is no character count
|
|
22
|
+
* to proxy, and this module refuses to guess a provider's image
|
|
23
|
+
* tokenization; the figure exists so a block is never worth ZERO, which is
|
|
24
|
+
* what MONOTONE requires. Deliberately small: under-stating an image is a
|
|
25
|
+
* threshold that fires slightly late, over-stating it is one that fires on
|
|
26
|
+
* a conversation that was never large.
|
|
27
|
+
*/
|
|
28
|
+
const NON_TEXT_BLOCK_TOKENS = 8;
|
|
29
|
+
/**
|
|
30
|
+
* chars/4 over a `string | ContentBlock[]` content field.
|
|
31
|
+
*
|
|
32
|
+
* SC-1b ①: the array arm must be summed BLOCK BY BLOCK. Reading `.length`
|
|
33
|
+
* off it yields the block COUNT — a five-block 50 KB message scored ~2
|
|
34
|
+
* tokens, and the live microcompact threshold believed it.
|
|
35
|
+
*/
|
|
36
|
+
function contentTokens(content) {
|
|
37
|
+
if (typeof content === "string")
|
|
38
|
+
return Math.ceil(content.length / 4);
|
|
39
|
+
let tokens = 0;
|
|
40
|
+
for (const block of content) {
|
|
41
|
+
tokens += block.type === "text" ? Math.ceil(block.text.length / 4) : NON_TEXT_BLOCK_TOKENS;
|
|
42
|
+
}
|
|
43
|
+
return tokens;
|
|
44
|
+
}
|
|
20
45
|
/**
|
|
21
46
|
* Rough token estimate (chars/4 + structural overhead). Calibration-free on
|
|
22
47
|
* purpose: context economy only needs a stable MONOTONE proxy, not an exact
|
|
23
|
-
* count — the threshold absorbs the error (mauri ADR-0007).
|
|
48
|
+
* count — the threshold absorbs the error (mauri ADR-0007). The proxy's
|
|
49
|
+
* three-word contract, and the pins that hold it, are
|
|
50
|
+
* packages/core/tests/sc1b-estimator.test.ts.
|
|
24
51
|
*/
|
|
25
52
|
export function estimateTokens(messages) {
|
|
26
53
|
let total = 0;
|
|
27
54
|
for (const msg of messages) {
|
|
28
55
|
if (msg.role === "user") {
|
|
29
|
-
total +=
|
|
56
|
+
total += contentTokens(msg.content);
|
|
30
57
|
}
|
|
31
58
|
else if (msg.role === "assistant") {
|
|
32
59
|
for (const block of msg.blocks) {
|
|
@@ -37,7 +64,7 @@ export function estimateTokens(messages) {
|
|
|
37
64
|
}
|
|
38
65
|
}
|
|
39
66
|
else {
|
|
40
|
-
total +=
|
|
67
|
+
total += contentTokens(msg.content) + 10;
|
|
41
68
|
}
|
|
42
69
|
}
|
|
43
70
|
return total;
|
|
@@ -37,7 +37,12 @@ export declare class EventLog {
|
|
|
37
37
|
*/
|
|
38
38
|
append(ev: EventInput): Event;
|
|
39
39
|
get all(): readonly Event[];
|
|
40
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* Incremental view for consumers that already saw `seq` and before —
|
|
42
|
+
* STRICTLY after, so a poll loop delivers each event exactly once. A
|
|
43
|
+
* consumer that has seen nothing passes -1. (SC-1b ④: this filtered
|
|
44
|
+
* `>= seq` and re-served the seam event on every poll.)
|
|
45
|
+
*/
|
|
41
46
|
since(seq: number): readonly Event[];
|
|
42
47
|
get lastSeq(): number;
|
|
43
48
|
}
|
package/dist/kernel/event-log.js
CHANGED
|
@@ -41,9 +41,14 @@ export class EventLog {
|
|
|
41
41
|
get all() {
|
|
42
42
|
return this.#events;
|
|
43
43
|
}
|
|
44
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* Incremental view for consumers that already saw `seq` and before —
|
|
46
|
+
* STRICTLY after, so a poll loop delivers each event exactly once. A
|
|
47
|
+
* consumer that has seen nothing passes -1. (SC-1b ④: this filtered
|
|
48
|
+
* `>= seq` and re-served the seam event on every poll.)
|
|
49
|
+
*/
|
|
45
50
|
since(seq) {
|
|
46
|
-
return this.#events.filter((e) => e.seq
|
|
51
|
+
return this.#events.filter((e) => e.seq > seq);
|
|
47
52
|
}
|
|
48
53
|
get lastSeq() {
|
|
49
54
|
return this.#next - 1;
|
package/dist/kernel/loop.d.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* L2 — the ReAct loop. The kernel's only loop; everything else is harness.
|
|
3
3
|
*
|
|
4
4
|
* An async generator that yields every event as it happens (never buffers a
|
|
5
|
-
* turn into a list — the
|
|
6
|
-
* `terminal` event per run (ADR-0004).
|
|
5
|
+
* turn into a list — the reference implementation's failure), and converges
|
|
6
|
+
* on exactly one `terminal` event per run (ADR-0004).
|
|
7
7
|
*
|
|
8
8
|
* SINGLE TRUTH (Phase B): the loop holds ONE EventLog. Messages are never
|
|
9
9
|
* stored alongside it — every adapter call derives them via
|
|
@@ -100,13 +100,23 @@ export interface LoopConfig {
|
|
|
100
100
|
*/
|
|
101
101
|
readonly approvalVerdict?: (decisionId: string) => boolean | undefined;
|
|
102
102
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
103
|
+
* DEAD — accepted by the type, never read by this loop.
|
|
104
|
+
*
|
|
105
|
+
* It was the C group channel for the failed-receipt pause: the loop
|
|
106
|
+
* persisted `uncertain_pending` and awaited a human verdict. ADR-0038
|
|
107
|
+
* removed that pause (a complete receipt IS the outcome), and with it
|
|
108
|
+
* every read of this field — a failure is now simply recorded failed and
|
|
109
|
+
* the siblings run on. The runtime still passes both callbacks
|
|
110
|
+
* (runtime/run.ts), so supplying them is harmless and changes nothing.
|
|
111
|
+
*
|
|
112
|
+
* The crash window — started, no receipt — is the ONLY uncertainty left,
|
|
113
|
+
* and the runtime's recovery driver owns it (RESOLVE_UNCERTAIN in
|
|
114
|
+
* runtime/recovery-plan.ts), not the loop. Both fields are kept because
|
|
115
|
+
* the surface is frozen (ADR-0051); do not read them as live wiring.
|
|
107
116
|
*/
|
|
108
117
|
readonly resolveUncertainty?: (executionId: string) => Promise<"rerun" | "abandoned">;
|
|
109
|
-
/**
|
|
118
|
+
/** DEAD, as above — the uncertainty twin of `approvalVerdict`
|
|
119
|
+
* (round 4, adversarial). Never read by the loop since ADR-0038. */
|
|
110
120
|
readonly uncertaintyVerdict?: (executionId: string) => "rerun" | "abandoned" | undefined;
|
|
111
121
|
/**
|
|
112
122
|
* E1: the COMPOSED approval chain — the runtime composes the
|
package/dist/kernel/loop.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* L2 — the ReAct loop. The kernel's only loop; everything else is harness.
|
|
3
3
|
*
|
|
4
4
|
* An async generator that yields every event as it happens (never buffers a
|
|
5
|
-
* turn into a list — the
|
|
6
|
-
* `terminal` event per run (ADR-0004).
|
|
5
|
+
* turn into a list — the reference implementation's failure), and converges
|
|
6
|
+
* on exactly one `terminal` event per run (ADR-0004).
|
|
7
7
|
*
|
|
8
8
|
* SINGLE TRUTH (Phase B): the loop holds ONE EventLog. Messages are never
|
|
9
9
|
* stored alongside it — every adapter call derives them via
|
package/dist/kernel/mode.d.ts
CHANGED
|
@@ -6,21 +6,19 @@
|
|
|
6
6
|
* - `visibleToolNames` — physical removal: the registry is subset() to these
|
|
7
7
|
* tools BEFORE the adapter is called. The model cannot call what it cannot
|
|
8
8
|
* see; no system-prompt overlay can make that guarantee.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* -
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
9
|
+
*
|
|
10
|
+
* That is the whole profile. SC-1b: `systemOverlay`, `permissionDefault`,
|
|
11
|
+
* `compactionKeepExtra`, and `stopPredicate` were REMOVED at 0.12.0 by the
|
|
12
|
+
* SC-1 memo's adjudication — all four were declared here and read by
|
|
13
|
+
* nothing, in the kernel or above it. Two of them ("reserved, read by the
|
|
14
|
+
* harness when the semantics land") had been waiting since mauri ADR-0011
|
|
15
|
+
* for semantics that never landed. A field that describes an intention
|
|
16
|
+
* rather than a behavior is a promise the type system makes on the
|
|
17
|
+
* kernel's behalf and the kernel does not keep; the honest profile is the
|
|
18
|
+
* one member that is actually applied.
|
|
16
19
|
*/
|
|
17
|
-
import type { PermissionDecision } from "./permission.js";
|
|
18
20
|
export interface ModeProfile {
|
|
19
21
|
readonly name: string;
|
|
20
|
-
readonly systemOverlay?: string;
|
|
21
22
|
readonly visibleToolNames?: readonly string[];
|
|
22
|
-
readonly permissionDefault?: PermissionDecision;
|
|
23
|
-
readonly compactionKeepExtra?: readonly string[];
|
|
24
|
-
readonly stopPredicate?: string;
|
|
25
23
|
}
|
|
26
24
|
export declare function resolveModeProfile(modes: readonly ModeProfile[] | undefined, name: string | undefined): ModeProfile | undefined;
|
package/dist/kernel/mode.js
CHANGED
|
@@ -6,13 +6,16 @@
|
|
|
6
6
|
* - `visibleToolNames` — physical removal: the registry is subset() to these
|
|
7
7
|
* tools BEFORE the adapter is called. The model cannot call what it cannot
|
|
8
8
|
* see; no system-prompt overlay can make that guarantee.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* -
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
9
|
+
*
|
|
10
|
+
* That is the whole profile. SC-1b: `systemOverlay`, `permissionDefault`,
|
|
11
|
+
* `compactionKeepExtra`, and `stopPredicate` were REMOVED at 0.12.0 by the
|
|
12
|
+
* SC-1 memo's adjudication — all four were declared here and read by
|
|
13
|
+
* nothing, in the kernel or above it. Two of them ("reserved, read by the
|
|
14
|
+
* harness when the semantics land") had been waiting since mauri ADR-0011
|
|
15
|
+
* for semantics that never landed. A field that describes an intention
|
|
16
|
+
* rather than a behavior is a promise the type system makes on the
|
|
17
|
+
* kernel's behalf and the kernel does not keep; the honest profile is the
|
|
18
|
+
* one member that is actually applied.
|
|
16
19
|
*/
|
|
17
20
|
export function resolveModeProfile(modes, name) {
|
|
18
21
|
if (!name || !modes)
|
|
@@ -5,9 +5,18 @@
|
|
|
5
5
|
* allow one call, deny with a reason fed back to the model, or defer to a
|
|
6
6
|
* human. The kernel's contract is only the decision shape; where decisions
|
|
7
7
|
* are stored (accept-for-session) is harness territory (PermissionStore,
|
|
8
|
-
* M2).
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* M2).
|
|
9
|
+
*
|
|
10
|
+
* `defer` IS A REAL PAUSE. The M1 note that once lived here — "defer is a
|
|
11
|
+
* deny with reason 'awaiting user'; the human-in-the-loop wiring arrives
|
|
12
|
+
* with the harness" — described the behavior ADR-0024 decision #3 replaced,
|
|
13
|
+
* and that ADR's own Context names this note as the thing it fixed (a
|
|
14
|
+
* denial "fakes the pause": the model sees a refusal and adjusts while no
|
|
15
|
+
* human ever decided). Shipped now: the loop persists `permission_requested`
|
|
16
|
+
* and AWAITS the approval channel in the same run frame, the human's
|
|
17
|
+
* verdict is persisted as `permission_decided`, and the pause survives a
|
|
18
|
+
* crash (kernel/loop.ts). With no approval channel configured the deferral
|
|
19
|
+
* degrades to an HONEST denial that says so.
|
|
11
20
|
*/
|
|
12
21
|
export type PermissionDecision = {
|
|
13
22
|
readonly action: "allow";
|
|
@@ -5,9 +5,18 @@
|
|
|
5
5
|
* allow one call, deny with a reason fed back to the model, or defer to a
|
|
6
6
|
* human. The kernel's contract is only the decision shape; where decisions
|
|
7
7
|
* are stored (accept-for-session) is harness territory (PermissionStore,
|
|
8
|
-
* M2).
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* M2).
|
|
9
|
+
*
|
|
10
|
+
* `defer` IS A REAL PAUSE. The M1 note that once lived here — "defer is a
|
|
11
|
+
* deny with reason 'awaiting user'; the human-in-the-loop wiring arrives
|
|
12
|
+
* with the harness" — described the behavior ADR-0024 decision #3 replaced,
|
|
13
|
+
* and that ADR's own Context names this note as the thing it fixed (a
|
|
14
|
+
* denial "fakes the pause": the model sees a refusal and adjusts while no
|
|
15
|
+
* human ever decided). Shipped now: the loop persists `permission_requested`
|
|
16
|
+
* and AWAITS the approval channel in the same run frame, the human's
|
|
17
|
+
* verdict is persisted as `permission_decided`, and the pause survives a
|
|
18
|
+
* crash (kernel/loop.ts). With no approval channel configured the deferral
|
|
19
|
+
* degrades to an HONEST denial that says so.
|
|
11
20
|
*/
|
|
12
21
|
/** The denial a tool result carries when a call was refused pre-flight. */
|
|
13
22
|
export function denialResult(reason) {
|
package/dist/kernel/project.d.ts
CHANGED
|
@@ -19,8 +19,10 @@
|
|
|
19
19
|
* re-runs the compaction algorithm (a future version could differ, A group/D
|
|
20
20
|
* group); `microcompacted` boundaries re-derive the cleared view from the
|
|
21
21
|
* stream itself (deterministic and idempotent); `summarized` (ADR-0044)
|
|
22
|
-
* replaces its covered range with one
|
|
23
|
-
*
|
|
22
|
+
* replaces its covered range with one USER message carrying the summary
|
|
23
|
+
* behind SUMMARY_FRAMING (E6's boundary honesty — see that constant
|
|
24
|
+
* below; it is deliberately NOT an assistant message). All three are
|
|
25
|
+
* persisted facts — the replay equals the live run. See ADR-0002.
|
|
24
26
|
*/
|
|
25
27
|
import type { Event } from "../protocol/events.js";
|
|
26
28
|
import type { EventInput } from "./event-log.js";
|
package/dist/kernel/project.js
CHANGED
|
@@ -19,8 +19,10 @@
|
|
|
19
19
|
* re-runs the compaction algorithm (a future version could differ, A group/D
|
|
20
20
|
* group); `microcompacted` boundaries re-derive the cleared view from the
|
|
21
21
|
* stream itself (deterministic and idempotent); `summarized` (ADR-0044)
|
|
22
|
-
* replaces its covered range with one
|
|
23
|
-
*
|
|
22
|
+
* replaces its covered range with one USER message carrying the summary
|
|
23
|
+
* behind SUMMARY_FRAMING (E6's boundary honesty — see that constant
|
|
24
|
+
* below; it is deliberately NOT an assistant message). All three are
|
|
25
|
+
* persisted facts — the replay equals the live run. See ADR-0002.
|
|
24
26
|
*/
|
|
25
27
|
/**
|
|
26
28
|
* C area: tools whose output is eligible for microcompact clearing — reads,
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
* events carry `seq`). The three properties that let a ReAct loop stream
|
|
9
9
|
* without buffering and without losing its place.
|
|
10
10
|
*
|
|
11
|
-
* WHY not a `Promise<Event[]>`: a buffered adapter is what made
|
|
12
|
-
* streaming a second-class feature bolted onto
|
|
13
|
-
* shape IS the architecture — see ADR-0001.
|
|
11
|
+
* WHY not a `Promise<Event[]>`: a buffered adapter is what made the
|
|
12
|
+
* reference implementation's streaming a second-class feature bolted onto
|
|
13
|
+
* a batch loop. The contract shape IS the architecture — see ADR-0001.
|
|
14
14
|
*
|
|
15
15
|
* Adapters translate provider wire events INTO `Event`. They never see tool
|
|
16
16
|
* handlers (only `ToolSpec` projections) — the kernel is the only thing that
|
package/dist/protocol/adapter.js
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
* events carry `seq`). The three properties that let a ReAct loop stream
|
|
9
9
|
* without buffering and without losing its place.
|
|
10
10
|
*
|
|
11
|
-
* WHY not a `Promise<Event[]>`: a buffered adapter is what made
|
|
12
|
-
* streaming a second-class feature bolted onto
|
|
13
|
-
* shape IS the architecture — see ADR-0001.
|
|
11
|
+
* WHY not a `Promise<Event[]>`: a buffered adapter is what made the
|
|
12
|
+
* reference implementation's streaming a second-class feature bolted onto
|
|
13
|
+
* a batch loop. The contract shape IS the architecture — see ADR-0001.
|
|
14
14
|
*
|
|
15
15
|
* Adapters translate provider wire events INTO `Event`. They never see tool
|
|
16
16
|
* handlers (only `ToolSpec` projections) — the kernel is the only thing that
|
|
@@ -220,10 +220,17 @@ export interface ToolExecutionSucceeded {
|
|
|
220
220
|
readonly tags?: readonly string[];
|
|
221
221
|
}
|
|
222
222
|
/**
|
|
223
|
-
* The side effect ran and FAILED.
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
223
|
+
* The side effect ran and FAILED. A complete receipt IS the outcome, so this
|
|
224
|
+
* execution is "failed" — NEVER "uncertain", whatever `safeToRetry` says
|
|
225
|
+
* (ADR-0038 superseding ADR-0025 decision #3: uncertainty belongs to the
|
|
226
|
+
* crash window alone — started, no receipt). The run does not pause here;
|
|
227
|
+
* siblings continue and the model retries with the error in hand, and that
|
|
228
|
+
* retry is a NEW call that re-passes the approval chain.
|
|
229
|
+
*
|
|
230
|
+
* `safeToRetry` is the tool's own `idempotent: true` declaration, carried
|
|
231
|
+
* for HISTORY: since ADR-0038 it no longer feeds the ledger's status
|
|
232
|
+
* derivation (runtime/ledger.ts). Its one live consequence is the honest
|
|
233
|
+
* note appended to a non-idempotent failure's result (ADR-0038 Amendment 1).
|
|
227
234
|
*/
|
|
228
235
|
export interface ToolExecutionFailed {
|
|
229
236
|
readonly seq: number;
|
|
@@ -294,11 +301,20 @@ export interface PermissionExpired {
|
|
|
294
301
|
readonly reason: string;
|
|
295
302
|
}
|
|
296
303
|
/**
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
301
|
-
* pause
|
|
304
|
+
* HISTORICAL — the current kernel NEVER emits this event.
|
|
305
|
+
*
|
|
306
|
+
* It marked the C group's failed-receipt pause: a non-idempotent execution
|
|
307
|
+
* that FAILED paused the run until a human ruled. ADR-0038 removed that
|
|
308
|
+
* pause (a complete receipt IS the outcome), so nothing appends this any
|
|
309
|
+
* more — pinned by `packages/core/tests/execution-gate.test.ts` and
|
|
310
|
+
* `packages/runtime/tests/execution.test.ts`, which assert its ABSENCE.
|
|
311
|
+
*
|
|
312
|
+
* The variant stays because the durable contract is frozen (ADR-0051) and
|
|
313
|
+
* old logs replay theirs verbatim (ADR-0038, Consequences): the projection
|
|
314
|
+
* renders nothing for it, and the ledger reports those receipted executions
|
|
315
|
+
* as "failed". The crash window — started, no receipt — is now the only
|
|
316
|
+
* source of uncertainty, and it is resolved through
|
|
317
|
+
* `uncertainExecutions()` / `resolveUncertain()`, not through this event.
|
|
302
318
|
*/
|
|
303
319
|
export interface UncertainPending {
|
|
304
320
|
readonly seq: number;
|
|
@@ -342,9 +358,11 @@ export interface MicroCompactEvent {
|
|
|
342
358
|
* range. `coversToSeq` is the seq of the LAST covered event; the covered
|
|
343
359
|
* range runs from just past the previous `summarized` event's coversToSeq
|
|
344
360
|
* (or the trajectory's start for the first) up to coversToSeq. The
|
|
345
|
-
* projection replaces exactly those events with ONE
|
|
346
|
-
*
|
|
347
|
-
*
|
|
361
|
+
* projection replaces exactly those events with ONE USER message carrying
|
|
362
|
+
* the summary behind a fixed framing line (E6's boundary honesty: the
|
|
363
|
+
* model reads compressed history as CONTEXT, never as a reply it produced
|
|
364
|
+
* — see SUMMARY_FRAMING in kernel/project.ts). It is not an assistant
|
|
365
|
+
* message; every `summarized` event always renders its own message. Byte-stable: a summarized event is a persisted fact, so the
|
|
348
366
|
* same events derive the same messages on every replay.
|
|
349
367
|
*
|
|
350
368
|
* The summary is generated OFF-LOOP through the session's own adapter —
|
|
@@ -83,7 +83,7 @@ export interface KisoExtension {
|
|
|
83
83
|
* E2: EXTEND the system prompt — append-only, never replace (a replace
|
|
84
84
|
* is a footgun; appends guarantee "adding an extension never removes
|
|
85
85
|
* existing guidance" — the monotonicity family of the approval chain's
|
|
86
|
-
* deny>
|
|
86
|
+
* deny > allow > ask and the veto short-circuit). The session's own
|
|
87
87
|
* systemPrompt comes first, then each extension's append in load order,
|
|
88
88
|
* \n\n-joined.
|
|
89
89
|
*/
|
|
@@ -10,7 +10,12 @@
|
|
|
10
10
|
* carries images. Forcing every caller into the array shape to serve the
|
|
11
11
|
* 5% that need vision is a tax paid on every line of product code.
|
|
12
12
|
*
|
|
13
|
-
* See ADR-0003 (sum type)
|
|
13
|
+
* See ADR-0003 (sum type). The tool contract's record is mauri ADR-0008 —
|
|
14
|
+
* the PREDECESSOR series, cited the same way in kernel/hooks.ts and
|
|
15
|
+
* kernel/mode.ts: kiso's own numbers 0006-0019 were NEVER assigned
|
|
16
|
+
* (docs/adrs/README.md), so an unprefixed "ADR-0008" sends a reader to a
|
|
17
|
+
* record that does not exist in this repo. The live tool contract is
|
|
18
|
+
* tools/tool.ts itself.
|
|
14
19
|
*
|
|
15
20
|
* This module is types-only: it compiles to nothing.
|
|
16
21
|
*/
|
|
@@ -107,8 +112,12 @@ export type Message = UserMessage | AssistantMessage | ToolResultMessage;
|
|
|
107
112
|
/**
|
|
108
113
|
* What the adapter advertises to the model.
|
|
109
114
|
*
|
|
110
|
-
* Deliberately minimal: the full tool (handler
|
|
111
|
-
* is L3-internal and an adapter
|
|
115
|
+
* Deliberately minimal: the full tool (the handler above all, plus the
|
|
116
|
+
* declarations the kernel keeps to itself) is L3-internal and an adapter
|
|
117
|
+
* must never see it. NB the historical list here named a `repair` member
|
|
118
|
+
* and a `dedup` member — neither exists on `Tool`: the (name, input) dedup
|
|
119
|
+
* guard was removed by ADR-0025, and repair means RECEIPT repair, which is
|
|
120
|
+
* the runtime's, not a tool's. An adapter that can reach
|
|
112
121
|
* the handler will eventually call it, and then the kernel is no longer the
|
|
113
122
|
* only thing that runs tools.
|
|
114
123
|
*/
|
|
@@ -10,7 +10,12 @@
|
|
|
10
10
|
* carries images. Forcing every caller into the array shape to serve the
|
|
11
11
|
* 5% that need vision is a tax paid on every line of product code.
|
|
12
12
|
*
|
|
13
|
-
* See ADR-0003 (sum type)
|
|
13
|
+
* See ADR-0003 (sum type). The tool contract's record is mauri ADR-0008 —
|
|
14
|
+
* the PREDECESSOR series, cited the same way in kernel/hooks.ts and
|
|
15
|
+
* kernel/mode.ts: kiso's own numbers 0006-0019 were NEVER assigned
|
|
16
|
+
* (docs/adrs/README.md), so an unprefixed "ADR-0008" sends a reader to a
|
|
17
|
+
* record that does not exist in this repo. The live tool contract is
|
|
18
|
+
* tools/tool.ts itself.
|
|
14
19
|
*
|
|
15
20
|
* This module is types-only: it compiles to nothing.
|
|
16
21
|
*/
|
package/dist/tools/tool.d.ts
CHANGED
|
@@ -4,9 +4,15 @@
|
|
|
4
4
|
* A tool is a pure declaration + handler pair. The kernel never branches on
|
|
5
5
|
* a tool's internals: `parameters` is a JSON Schema the kernel validates and
|
|
6
6
|
* projects to the adapter as `ToolSpec` (adapter never sees the handler —
|
|
7
|
-
* see ADR-0001)
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* see ADR-0001).
|
|
8
|
+
*
|
|
9
|
+
* SC-1b: `concurrencySafe` and `delivers` were REMOVED at 0.12.0 by the
|
|
10
|
+
* SC-1 memo's adjudication — both were declared and consulted by nothing.
|
|
11
|
+
* Their absence is the honest contract; the concurrency RACE they were
|
|
12
|
+
* mistaken for a defense against is a real open question and moved to EC-1,
|
|
13
|
+
* which owes a mechanism that does not depend on a per-tool opt-in.
|
|
14
|
+
* Delivery truth is named by the CALLER (governance/delivery.ts's
|
|
15
|
+
* `DeliveryConfig.producers`), which is where it always actually lived.
|
|
10
16
|
*
|
|
11
17
|
* WHY JSON Schema instead of a runtime library: the kernel has zero runtime
|
|
12
18
|
* dependencies (ADR-0001). Zod / TypeBox / valibot live at the harness layer;
|
|
@@ -49,22 +55,28 @@ export interface Tool<I = unknown> {
|
|
|
49
55
|
/** JSON Schema (draft-07 subset). Validated before execute. */
|
|
50
56
|
readonly parameters: Readonly<Record<string, unknown>>;
|
|
51
57
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
58
|
+
* The tool's own declaration that REPEATING its side effect is safe
|
|
59
|
+
* (reads, searches, pure computations).
|
|
60
|
+
*
|
|
61
|
+
* It is NOT a dedup guard. The kernel runs every logical call, including
|
|
62
|
+
* one whose (name, input) is identical to an earlier one — ADR-0024
|
|
63
|
+
* decision #2's (name, input) guard was REMOVED by ADR-0025 decision #1
|
|
64
|
+
* ("NO (name, input) dedup", kernel/loop.ts). Exactly-once is enforced
|
|
65
|
+
* by execution IDENTITY instead: a confirmed success is never
|
|
66
|
+
* re-executed (a lost model-facing result is repaired FROM the durable
|
|
67
|
+
* receipt), and an execution that STARTED without reporting — the crash
|
|
68
|
+
* window — waits for a human verdict. A FAILED execution is failed, not
|
|
69
|
+
* uncertain: a complete receipt IS the outcome (ADR-0038).
|
|
70
|
+
*
|
|
71
|
+
* What this flag actually decides, and nothing more:
|
|
72
|
+
* - a failure from a tool that did NOT declare it carries the honest
|
|
73
|
+
* "side effects may have partially applied; verify before retrying"
|
|
74
|
+
* note on the result (ADR-0038 Amendment 1);
|
|
75
|
+
* - it rides the durable receipt as `tool_execution_failed.safeToRetry`
|
|
76
|
+
* — history only, since ADR-0038 stopped it feeding ledger status.
|
|
77
|
+
*
|
|
78
|
+
* Undeclared is the safe side: unknown idempotency means the note
|
|
79
|
+
* applies. A retry is a NEW call and re-passes the approval chain.
|
|
68
80
|
*/
|
|
69
81
|
readonly idempotent?: boolean;
|
|
70
82
|
/** R-C: ONE line for the system prompt — the tool's role, never the
|
package/dist/tools/tool.js
CHANGED
|
@@ -4,9 +4,15 @@
|
|
|
4
4
|
* A tool is a pure declaration + handler pair. The kernel never branches on
|
|
5
5
|
* a tool's internals: `parameters` is a JSON Schema the kernel validates and
|
|
6
6
|
* projects to the adapter as `ToolSpec` (adapter never sees the handler —
|
|
7
|
-
* see ADR-0001)
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* see ADR-0001).
|
|
8
|
+
*
|
|
9
|
+
* SC-1b: `concurrencySafe` and `delivers` were REMOVED at 0.12.0 by the
|
|
10
|
+
* SC-1 memo's adjudication — both were declared and consulted by nothing.
|
|
11
|
+
* Their absence is the honest contract; the concurrency RACE they were
|
|
12
|
+
* mistaken for a defense against is a real open question and moved to EC-1,
|
|
13
|
+
* which owes a mechanism that does not depend on a per-tool opt-in.
|
|
14
|
+
* Delivery truth is named by the CALLER (governance/delivery.ts's
|
|
15
|
+
* `DeliveryConfig.producers`), which is where it always actually lived.
|
|
10
16
|
*
|
|
11
17
|
* WHY JSON Schema instead of a runtime library: the kernel has zero runtime
|
|
12
18
|
* dependencies (ADR-0001). Zod / TypeBox / valibot live at the harness layer;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vincemakes/kiso-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "kiso (foundation) core — protocol, event log, loop, hooks, modes, permissions, compaction, delivery truth. The 2,000-line kernel at the bottom of the kiso framework.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"openai"
|
|
34
34
|
],
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@vincemakes/kiso-evals": "0.
|
|
36
|
+
"@vincemakes/kiso-evals": "0.12.0",
|
|
37
37
|
"@types/node": "^26.1.2",
|
|
38
38
|
"typescript": "^5.7.2",
|
|
39
39
|
"vitest": "^3.0.0"
|