@telora/daemon 0.20.21 → 0.20.32
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/build-info.json +4 -3
- package/dist/audit-phase.d.ts +43 -6
- package/dist/audit-phase.d.ts.map +1 -1
- package/dist/audit-phase.js +124 -23
- package/dist/audit-phase.js.map +1 -1
- package/dist/auto-update.d.ts +87 -0
- package/dist/auto-update.d.ts.map +1 -1
- package/dist/auto-update.js +142 -8
- package/dist/auto-update.js.map +1 -1
- package/dist/cascade-restatement.d.ts +13 -147
- package/dist/cascade-restatement.d.ts.map +1 -1
- package/dist/cascade-restatement.js +13 -429
- package/dist/cascade-restatement.js.map +1 -1
- package/dist/focus-engine.d.ts.map +1 -1
- package/dist/focus-engine.js +15 -0
- package/dist/focus-engine.js.map +1 -1
- package/dist/focus-loop-registry.d.ts.map +1 -1
- package/dist/focus-loop-registry.js +43 -90
- package/dist/focus-loop-registry.js.map +1 -1
- package/dist/focus-loop.d.ts +0 -2
- package/dist/focus-loop.d.ts.map +1 -1
- package/dist/focus-loop.js +33 -25
- package/dist/focus-loop.js.map +1 -1
- package/dist/focus-phase.d.ts +26 -0
- package/dist/focus-phase.d.ts.map +1 -1
- package/dist/focus-phase.js +38 -0
- package/dist/focus-phase.js.map +1 -1
- package/dist/focus-prompt-builder.d.ts.map +1 -1
- package/dist/focus-prompt-builder.js +5 -1
- package/dist/focus-prompt-builder.js.map +1 -1
- package/dist/listener.d.ts.map +1 -1
- package/dist/listener.js +40 -9
- package/dist/listener.js.map +1 -1
- package/dist/loops/llm-client.d.ts.map +1 -1
- package/dist/loops/llm-client.js +17 -4
- package/dist/loops/llm-client.js.map +1 -1
- package/dist/prompt-listing.d.ts +25 -0
- package/dist/prompt-listing.d.ts.map +1 -1
- package/dist/prompt-listing.js +61 -0
- package/dist/prompt-listing.js.map +1 -1
- package/dist/queries/audit-runs.d.ts +56 -2
- package/dist/queries/audit-runs.d.ts.map +1 -1
- package/dist/queries/audit-runs.js +40 -0
- package/dist/queries/audit-runs.js.map +1 -1
- package/dist/queries/deliveries.d.ts +27 -0
- package/dist/queries/deliveries.d.ts.map +1 -1
- package/dist/queries/deliveries.js.map +1 -1
- package/dist/queries/focuses.d.ts +0 -9
- package/dist/queries/focuses.d.ts.map +1 -1
- package/dist/queries/focuses.js +0 -14
- package/dist/queries/focuses.js.map +1 -1
- package/dist/resolvers/index.d.ts +1 -1
- package/dist/resolvers/index.d.ts.map +1 -1
- package/dist/resolvers/index.js +1 -1
- package/dist/resolvers/index.js.map +1 -1
- package/dist/resolvers/shared/audit.d.ts +5 -0
- package/dist/resolvers/shared/audit.d.ts.map +1 -1
- package/dist/resolvers/shared/audit.js +8 -3
- package/dist/resolvers/shared/audit.js.map +1 -1
- package/dist/resolvers/shared/git-diff.d.ts +13 -0
- package/dist/resolvers/shared/git-diff.d.ts.map +1 -1
- package/dist/resolvers/shared/git-diff.js +30 -0
- package/dist/resolvers/shared/git-diff.js.map +1 -1
- package/dist/security-scan-engine.d.ts +9 -1
- package/dist/security-scan-engine.d.ts.map +1 -1
- package/dist/security-scan-engine.js +25 -2
- package/dist/security-scan-engine.js.map +1 -1
- package/dist/spawn/review-role-fallback.d.ts +74 -0
- package/dist/spawn/review-role-fallback.d.ts.map +1 -0
- package/dist/spawn/review-role-fallback.js +62 -0
- package/dist/spawn/review-role-fallback.js.map +1 -0
- package/dist/staleness-sensor.d.ts +153 -0
- package/dist/staleness-sensor.d.ts.map +1 -0
- package/dist/staleness-sensor.js +308 -0
- package/dist/staleness-sensor.js.map +1 -0
- package/dist/unified-shell.d.ts.map +1 -1
- package/dist/unified-shell.js +11 -0
- package/dist/unified-shell.js.map +1 -1
- package/dist/verification-engine.d.ts +17 -1
- package/dist/verification-engine.d.ts.map +1 -1
- package/dist/verification-engine.js +143 -104
- package/dist/verification-engine.js.map +1 -1
- package/dist/verification-feedback.d.ts +68 -1
- package/dist/verification-feedback.d.ts.map +1 -1
- package/dist/verification-feedback.js +175 -0
- package/dist/verification-feedback.js.map +1 -1
- package/dist/verify-reconciliation.d.ts +16 -1
- package/dist/verify-reconciliation.d.ts.map +1 -1
- package/dist/verify-reconciliation.js +18 -2
- package/dist/verify-reconciliation.js.map +1 -1
- package/dist/verify-restatement.d.ts +7 -0
- package/dist/verify-restatement.d.ts.map +1 -1
- package/dist/verify-restatement.js +1 -0
- package/dist/verify-restatement.js.map +1 -1
- package/dist/version-check.d.ts +6 -0
- package/dist/version-check.d.ts.map +1 -1
- package/dist/version-check.js +1 -1
- package/dist/version-check.js.map +1 -1
- package/package.json +2 -2
- package/dist/drift-ratify-loop.d.ts +0 -68
- package/dist/drift-ratify-loop.d.ts.map +0 -1
- package/dist/drift-ratify-loop.js +0 -161
- package/dist/drift-ratify-loop.js.map +0 -1
- package/dist/negative-branch.d.ts +0 -136
- package/dist/negative-branch.d.ts.map +0 -1
- package/dist/negative-branch.js +0 -241
- package/dist/negative-branch.js.map +0 -1
- package/dist/shortfall-disposition-config.d.ts +0 -34
- package/dist/shortfall-disposition-config.d.ts.map +0 -1
- package/dist/shortfall-disposition-config.js +0 -46
- package/dist/shortfall-disposition-config.js.map +0 -1
- package/dist/shortfall-disposition-loop.d.ts +0 -86
- package/dist/shortfall-disposition-loop.d.ts.map +0 -1
- package/dist/shortfall-disposition-loop.js +0 -309
- package/dist/shortfall-disposition-loop.js.map +0 -1
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Periodic drift auto-ratification tick.
|
|
3
|
-
*
|
|
4
|
-
* Lists `proposed` drift proposals per product, runs each through the
|
|
5
|
-
* fail-closed policy in `drift-ratify-policy.ts`, and ratifies the ones the
|
|
6
|
-
* daemon is sanctioned to ratify unattended. Proposals the policy routes to a
|
|
7
|
-
* review session (`review_dispose`) or refuses to classify (`hold`) are left
|
|
8
|
-
* in `proposed`, untouched.
|
|
9
|
-
*
|
|
10
|
-
* WHAT THIS CLOSES. Drift proposals pooled in `proposed` faster than a human
|
|
11
|
-
* could ratify them, so the reality tree lagged observed reality and every
|
|
12
|
-
* consumer of the graph (audit assembly, propose_injections, focus.context)
|
|
13
|
-
* computed against a stale intent model. The ledger is unchanged -- this only
|
|
14
|
-
* changes WHO ratifies. Ratified proposals still reach the graph exclusively
|
|
15
|
-
* via the existing realign_crt phase (`applyRatifiedProposals`), which this
|
|
16
|
-
* module does not touch.
|
|
17
|
-
*
|
|
18
|
-
* WHAT THIS MUST NEVER DO. Ratify an inward shortfall. That is the machine
|
|
19
|
-
* rewriting a claim its own work failed to meet. The policy module owns that
|
|
20
|
-
* decision; this tick owns only list -> classify -> ratify-the-safe-ones, and
|
|
21
|
-
* deliberately contains no safe-kind rules of its own. If you find yourself
|
|
22
|
-
* adding kind logic here, it belongs in drift-ratify-policy.ts.
|
|
23
|
-
*
|
|
24
|
-
* ACTOR STAMP. The tick calls `crt_drift_proposal_ratify` with no session id.
|
|
25
|
-
* The edge handler resolves the actor from the caller's credential kind, so a
|
|
26
|
-
* tracker-authenticated daemon call is recorded as `ratified_by_kind='system'`
|
|
27
|
-
* with `ratified_by=NULL` automatically. Passing a session id would instead
|
|
28
|
-
* stamp `review_session` -- that is the review-disposition path, not this one.
|
|
29
|
-
*
|
|
30
|
-
* Activation: opt-out via TELORA_DRIFT_RATIFY_LOOP=0. See `shouldRunLoop()` in
|
|
31
|
-
* focus-engine.ts.
|
|
32
|
-
*
|
|
33
|
-
* @module drift-ratify-loop
|
|
34
|
-
*/
|
|
35
|
-
import { loadEnvConfig } from '@telora/daemon-core';
|
|
36
|
-
import { callApi as defaultCallApi } from './queries/shared.js';
|
|
37
|
-
import { classifyDriftProposal } from './drift-ratify-policy.js';
|
|
38
|
-
import { createLogger } from './log.js';
|
|
39
|
-
const log = createLogger({ module: 'drift-ratify-loop' });
|
|
40
|
-
/**
|
|
41
|
-
* Per-product backoff for list failures, so a persistent server-side failure
|
|
42
|
-
* does not retry-storm every tick. Module-level so the window survives across
|
|
43
|
-
* `runDriftRatifyTick` calls within the daemon process. Keyed productId ->
|
|
44
|
-
* earliest next-attempt epoch ms. Mirrors the drift-eval loop's window
|
|
45
|
-
* (drift-eval-loop.ts:74) and complements the isolated 'drift' circuit breaker
|
|
46
|
-
* in queries/shared.ts, which fails fast once the breaker opens.
|
|
47
|
-
*/
|
|
48
|
-
const listBackoffUntil = new Map();
|
|
49
|
-
/**
|
|
50
|
-
* Resolve the per-product list-failure backoff window (ms).
|
|
51
|
-
*
|
|
52
|
-
* Deliberately REUSES TELORA_DRIFT_LIST_BACKOFF_MS rather than introducing a
|
|
53
|
-
* knob of its own. The knob's meaning -- how long to back off a product after a
|
|
54
|
-
* drift-list failure -- is exactly this loop's need, and both loops fail the
|
|
55
|
-
* same way for the same reasons, so one operator dial covering both is coherent
|
|
56
|
-
* rather than a conflation. It also keeps this loop free of any dependency on a
|
|
57
|
-
* @telora/daemon-core republish: daemon-core is registry-installed, so a new
|
|
58
|
-
* knob added to its source would be invisible to this package until it is
|
|
59
|
-
* published and reinstalled. Injectable via deps for tests.
|
|
60
|
-
*/
|
|
61
|
-
function defaultListBackoffMs() {
|
|
62
|
-
return loadEnvConfig().TELORA_DRIFT_LIST_BACKOFF_MS;
|
|
63
|
-
}
|
|
64
|
-
/** Test-only: clear the per-product list-failure backoff state. */
|
|
65
|
-
export function __resetDriftRatifyBackoffForTesting() {
|
|
66
|
-
listBackoffUntil.clear();
|
|
67
|
-
}
|
|
68
|
-
function defaultDeps() {
|
|
69
|
-
return {
|
|
70
|
-
callApi: defaultCallApi,
|
|
71
|
-
now: () => Date.now(),
|
|
72
|
-
listBackoffMs: defaultListBackoffMs(),
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Run one auto-ratification tick across every product in the daemon config.
|
|
77
|
-
*
|
|
78
|
-
* Per-proposal failures are counted and skipped, never aborting the batch --
|
|
79
|
-
* one unratifiable proposal must not strand the rest of the stream (mirrors
|
|
80
|
-
* `applyRatifiedProposals`, realign-apply.ts:403-416).
|
|
81
|
-
*
|
|
82
|
-
* Returns counters useful for log lines and tests.
|
|
83
|
-
*/
|
|
84
|
-
export async function runDriftRatifyTick(config, depOverrides = {}) {
|
|
85
|
-
const deps = { ...defaultDeps(), ...depOverrides };
|
|
86
|
-
const counts = {
|
|
87
|
-
productsScanned: 0,
|
|
88
|
-
productsSkipped: 0,
|
|
89
|
-
proposalsExamined: 0,
|
|
90
|
-
ratified: 0,
|
|
91
|
-
leftForReview: 0,
|
|
92
|
-
held: 0,
|
|
93
|
-
errors: 0,
|
|
94
|
-
};
|
|
95
|
-
for (const product of config.products) {
|
|
96
|
-
counts.productsScanned += 1;
|
|
97
|
-
// Skip a product still inside its list-failure backoff window.
|
|
98
|
-
const nowMs = deps.now();
|
|
99
|
-
const backoffUntil = listBackoffUntil.get(product.id) ?? 0;
|
|
100
|
-
if (nowMs < backoffUntil) {
|
|
101
|
-
counts.productsSkipped += 1;
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
let proposals;
|
|
105
|
-
try {
|
|
106
|
-
// NOTE: crt_drift_proposal_list cannot filter on proposed_metadata
|
|
107
|
-
// (drift-proposals.ts:78-119 supports focusId/productId/realityTreeId/
|
|
108
|
-
// status only), so the shortfall split is decided client-side by the
|
|
109
|
-
// policy below -- not by the query.
|
|
110
|
-
const list = await deps.callApi('crt_drift_proposal_list', {
|
|
111
|
-
productId: product.id,
|
|
112
|
-
status: 'proposed',
|
|
113
|
-
});
|
|
114
|
-
proposals = list.items ?? [];
|
|
115
|
-
// Success clears any prior backoff for this product.
|
|
116
|
-
listBackoffUntil.delete(product.id);
|
|
117
|
-
}
|
|
118
|
-
catch (err) {
|
|
119
|
-
counts.errors += 1;
|
|
120
|
-
listBackoffUntil.set(product.id, nowMs + deps.listBackoffMs);
|
|
121
|
-
log.warn(`[drift-ratify-loop] list failed for product ${product.id} (backing off ${deps.listBackoffMs}ms):`, err.message);
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
for (const proposal of proposals) {
|
|
125
|
-
counts.proposalsExamined += 1;
|
|
126
|
-
const { disposition, reason } = classifyDriftProposal({
|
|
127
|
-
proposalKind: proposal.proposalKind,
|
|
128
|
-
proposedMetadata: proposal.proposedMetadata,
|
|
129
|
-
});
|
|
130
|
-
if (disposition === 'review_dispose') {
|
|
131
|
-
// The bar-lowering channel. Left in `proposed` for an independent
|
|
132
|
-
// review session; this tick must not touch it.
|
|
133
|
-
counts.leftForReview += 1;
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
if (disposition === 'hold') {
|
|
137
|
-
// Fail-closed: unknown kind, malformed metadata, or an internally
|
|
138
|
-
// inconsistent row. Stays `proposed` so a human sees it.
|
|
139
|
-
counts.held += 1;
|
|
140
|
-
log.info(`[drift-ratify-loop] holding proposal ${proposal.id} (kind=${proposal.proposalKind}, reason=${reason})`);
|
|
141
|
-
continue;
|
|
142
|
-
}
|
|
143
|
-
try {
|
|
144
|
-
// No session id: the edge handler stamps ratified_by_kind='system' from
|
|
145
|
-
// the tracker credential. Ratified proposals reach the graph via the
|
|
146
|
-
// existing realign_crt phase; nothing here applies them.
|
|
147
|
-
await deps.callApi('crt_drift_proposal_ratify', { proposalId: proposal.id });
|
|
148
|
-
counts.ratified += 1;
|
|
149
|
-
}
|
|
150
|
-
catch (err) {
|
|
151
|
-
counts.errors += 1;
|
|
152
|
-
log.warn(`[drift-ratify-loop] ratify failed for proposal ${proposal.id} (${reason}):`, err.message);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
if (counts.proposalsExamined > 0 || counts.errors > 0 || counts.productsSkipped > 0) {
|
|
157
|
-
log.info(`[drift-ratify-loop] tick: products=${counts.productsScanned} skipped=${counts.productsSkipped} examined=${counts.proposalsExamined} ratified=${counts.ratified} forReview=${counts.leftForReview} held=${counts.held} errors=${counts.errors}`);
|
|
158
|
-
}
|
|
159
|
-
return counts;
|
|
160
|
-
}
|
|
161
|
-
//# sourceMappingURL=drift-ratify-loop.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"drift-ratify-loop.js","sourceRoot":"","sources":["../src/drift-ratify-loop.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Negative-branch (negative branch reservation) generation helper.
|
|
3
|
-
*
|
|
4
|
-
* The INVERSE of `de-restatement.ts`. Where de-restatement turns a UDE into the
|
|
5
|
-
* positive desired effect it becomes once an injection resolves it, this asks
|
|
6
|
-
* the opposite question: what NEW undesired effects might this injection ITSELF
|
|
7
|
-
* introduce? In Goldratt's Thinking Processes this is a "negative branch
|
|
8
|
-
* reservation" -- a side effect the injection drags in that the clean recolor
|
|
9
|
-
* never surfaces.
|
|
10
|
-
*
|
|
11
|
-
* Reuses the same model-invocation pattern as `de-restatement.ts` -- spawning
|
|
12
|
-
* the `claude` CLI in print mode -- so there is NO new client or secret wiring.
|
|
13
|
-
* A clean injection yields ZERO candidates (the model emits "NONE" -> []).
|
|
14
|
-
*
|
|
15
|
-
* The generated candidates are persisted as `crt_drift_proposals`
|
|
16
|
-
* (`proposal_kind='add_node'`) carrying `sourceInjectionId` + `isNegativeBranch`
|
|
17
|
-
* so a human ratifies/dismisses them: ratify -> the UDE is created and wired to
|
|
18
|
-
* the injection (see realign-apply `handleAddNode`); dismiss -> no residue.
|
|
19
|
-
*
|
|
20
|
-
* @module negative-branch
|
|
21
|
-
*/
|
|
22
|
-
import { type ChildProcess } from 'node:child_process';
|
|
23
|
-
export interface NegativeBranchInputs {
|
|
24
|
-
/** The injection whose side effects we are probing. */
|
|
25
|
-
injectionStatement: string;
|
|
26
|
-
/** Optional UDE statements the injection targets, for context. */
|
|
27
|
-
targetUdeStatements?: string[];
|
|
28
|
-
}
|
|
29
|
-
interface SpawnOpts {
|
|
30
|
-
stdio: ['pipe', 'pipe', 'pipe'];
|
|
31
|
-
}
|
|
32
|
-
export interface NegativeBranchOptions {
|
|
33
|
-
/** Path to the `claude` CLI binary (default: 'claude'). */
|
|
34
|
-
claudeBin?: string;
|
|
35
|
-
/** Timeout in ms; defaults to 2 minutes. */
|
|
36
|
-
timeoutMs?: number;
|
|
37
|
-
/** Override spawn for tests. Defaults to node:child_process spawn. */
|
|
38
|
-
spawnFn?: (cmd: string, args: string[], opts: SpawnOpts) => ChildProcess;
|
|
39
|
-
/**
|
|
40
|
-
* Override the entire model invocation for tests -- bypasses spawning the
|
|
41
|
-
* CLI. Receives the system prompt and user message, returns the raw model
|
|
42
|
-
* text. When omitted, the default spawns the `claude` CLI in print mode.
|
|
43
|
-
*/
|
|
44
|
-
invokeModel?: (systemPrompt: string, userMessage: string) => Promise<string>;
|
|
45
|
-
}
|
|
46
|
-
export declare const NEGATIVE_BRANCH_SYSTEM_PROMPT = "You author Goldratt \"negative branch reservations\" for a reality tree: the NEW undesirable effects that an injection might itself introduce.\n\nAn injection resolves one problem but can drag in fresh side effects. Your job is to surface those candidate new undesired effects (UDEs) so a human can decide whether they are real.\n\nRules:\n- Output ONE candidate undesired effect per line. No numbering, no bullets, no preamble, no commentary, no quotes.\n- Each line is a single concrete negative outcome the injection could cause -- a genuinely NEW problem, not a restatement of the problem the injection solves.\n- Be conservative: only list effects with a plausible causal link to the injection. Do NOT pad the list.\n- If the injection introduces no plausible new undesired effect, output exactly: NONE";
|
|
47
|
-
/** Exposed as a function to mirror `de-restatement`'s shape. */
|
|
48
|
-
export declare function buildNegativeBranchSystemPrompt(): string;
|
|
49
|
-
/** Build the user message describing the injection (and any targeted UDEs). */
|
|
50
|
-
export declare function buildNegativeBranchUserMessage(inputs: NegativeBranchInputs): string;
|
|
51
|
-
/**
|
|
52
|
-
* Parse raw model output into a list of candidate UDE statements.
|
|
53
|
-
*
|
|
54
|
-
* One candidate per line, trimmed, empties dropped. A lone "NONE" (case
|
|
55
|
-
* insensitive, optionally with surrounding punctuation) yields an empty list.
|
|
56
|
-
* Strips a leading bullet/number if the model added one despite the prompt.
|
|
57
|
-
*/
|
|
58
|
-
export declare function parseNegativeBranchCandidates(raw: string): string[];
|
|
59
|
-
/**
|
|
60
|
-
* Build the argv for the claude CLI invocation. Exposed for tests.
|
|
61
|
-
*
|
|
62
|
-
* NOTE: must NOT include `--bare` -- that flag makes the CLI skip credential
|
|
63
|
-
* loading, print "Not logged in" to stdout, and exit 1 (the negative-branch
|
|
64
|
-
* pass died silently before it ran).
|
|
65
|
-
*/
|
|
66
|
-
export declare function buildNegativeBranchCliArgs(systemPrompt: string): string[];
|
|
67
|
-
/**
|
|
68
|
-
* Generate candidate negative-branch UDE statements for an injection.
|
|
69
|
-
*
|
|
70
|
-
* Returns 0-N candidates. A clean injection (model outputs "NONE") yields [].
|
|
71
|
-
* Throws only on model-invocation failure; callers catch and skip so a single
|
|
72
|
-
* failure never aborts the surrounding loop.
|
|
73
|
-
*/
|
|
74
|
-
export declare function generateNegativeBranches(inputs: NegativeBranchInputs, opts?: NegativeBranchOptions): Promise<string[]>;
|
|
75
|
-
type CallApi = <T>(action: string, params?: Record<string, unknown>) => Promise<T>;
|
|
76
|
-
export interface ProposeNegativeBranchesInputs {
|
|
77
|
-
/** The injection node these negative branches hang off. */
|
|
78
|
-
injectionNodeId: string;
|
|
79
|
-
/** The injection statement (the probe input). */
|
|
80
|
-
injectionStatement: string;
|
|
81
|
-
/** Reality tree the proposals belong to (required by the create action). */
|
|
82
|
-
realityTreeId: string;
|
|
83
|
-
/** Focus context for the proposal (optional but recommended). */
|
|
84
|
-
focusId?: string | null;
|
|
85
|
-
/** UDE statements the injection targets, for generation context. */
|
|
86
|
-
targetUdeStatements?: string[];
|
|
87
|
-
}
|
|
88
|
-
export interface ProposeNegativeBranchesDeps {
|
|
89
|
-
callApi?: CallApi;
|
|
90
|
-
/** Override generation for tests. Defaults to `generateNegativeBranches`. */
|
|
91
|
-
generate?: (inputs: NegativeBranchInputs, opts?: NegativeBranchOptions) => Promise<string[]>;
|
|
92
|
-
/** Options forwarded to the default generator (model/spawn overrides). */
|
|
93
|
-
generateOptions?: NegativeBranchOptions;
|
|
94
|
-
/**
|
|
95
|
-
* Injectable clock for the durable pass marker. Defaults to
|
|
96
|
-
* `() => new Date().toISOString()`. Tests pass a fixed value so the stamped
|
|
97
|
-
* timestamp is deterministic. Kept as a thunk (not a bare value) mirroring the
|
|
98
|
-
* module's other injectable-deps style. The clock is read AFTER generation +
|
|
99
|
-
* proposal creation complete and just BEFORE the stamp write -- i.e. the
|
|
100
|
-
* timestamp marks when the pass finished its work, immediately prior to
|
|
101
|
-
* persisting the marker (it cannot be read after the write resolves, since the
|
|
102
|
-
* value being written is what the write persists).
|
|
103
|
-
*/
|
|
104
|
-
now?: () => string;
|
|
105
|
-
}
|
|
106
|
-
export interface ProposeNegativeBranchesResult {
|
|
107
|
-
/** Candidate statements the model produced. */
|
|
108
|
-
candidates: string[];
|
|
109
|
-
/** Drift-proposal ids successfully created (one per candidate). */
|
|
110
|
-
proposalIds: string[];
|
|
111
|
-
/** Per-candidate creation errors (creation failures do not abort the rest). */
|
|
112
|
-
errors: string[];
|
|
113
|
-
/**
|
|
114
|
-
* The ISO timestamp stamped onto the injection's
|
|
115
|
-
* `negative_branch_pass_ran_at` marker, or null if the stamp write failed.
|
|
116
|
-
* The pass having RUN (this being non-null) is what gates presentability --
|
|
117
|
-
* NOT whether `candidates` is empty. An empty candidate set with a set marker
|
|
118
|
-
* is the honest "ran clean" answer.
|
|
119
|
-
*/
|
|
120
|
-
passRanAt: string | null;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Run generation for an injection, then persist each candidate as a
|
|
124
|
-
* ratify-able `add_node` drift proposal wired (via `sourceInjectionId`) to the
|
|
125
|
-
* injection that introduces it. Idempotency / dedupe is a human concern --
|
|
126
|
-
* proposals are surfaced, not auto-applied.
|
|
127
|
-
*
|
|
128
|
-
* A clean injection produces no candidates and creates no proposals -- but the
|
|
129
|
-
* pass still COMPLETED, so the injection's `negative_branch_pass_ran_at` marker
|
|
130
|
-
* is stamped regardless of candidate count (as long as generation did not
|
|
131
|
-
* throw). That durable marker, not the candidate count, is what later gates
|
|
132
|
-
* tree presentability: "ran clean" must be distinguishable from "never ran".
|
|
133
|
-
*/
|
|
134
|
-
export declare function proposeNegativeBranchesForInjection(inputs: ProposeNegativeBranchesInputs, deps?: ProposeNegativeBranchesDeps): Promise<ProposeNegativeBranchesResult>;
|
|
135
|
-
export {};
|
|
136
|
-
//# sourceMappingURL=negative-branch.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"negative-branch.d.ts","sourceRoot":"","sources":["../src/negative-branch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAK9D,MAAM,WAAW,oBAAoB;IACnC,uDAAuD;IACvD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC;AAED,UAAU,SAAS;IACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,qBAAqB;IACpC,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,KAAK,YAAY,CAAC;IACzE;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9E;AAID,eAAO,MAAM,6BAA6B,4yBAQ4C,CAAC;AAEvF,gEAAgE;AAChE,wBAAgB,+BAA+B,IAAI,MAAM,CAExD;AAED,+EAA+E;AAC/E,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAYnF;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBnE;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,CAOzE;AA0DD;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,oBAAoB,EAC5B,IAAI,GAAE,qBAA0B,GAC/B,OAAO,CAAC,MAAM,EAAE,CAAC,CAMnB;AAMD,KAAK,OAAO,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAEnF,MAAM,WAAW,6BAA6B;IAC5C,2DAA2D;IAC3D,eAAe,EAAE,MAAM,CAAC;IACxB,iDAAiD;IACjD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,aAAa,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,oEAAoE;IACpE,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,oBAAoB,EAAE,IAAI,CAAC,EAAE,qBAAqB,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7F,0EAA0E;IAC1E,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACxC;;;;;;;;;OASG;IACH,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,6BAA6B;IAC5C,+CAA+C;IAC/C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,mEAAmE;IACnE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,mCAAmC,CACvD,MAAM,EAAE,6BAA6B,EACrC,IAAI,GAAE,2BAAgC,GACrC,OAAO,CAAC,6BAA6B,CAAC,CA6ExC"}
|
package/dist/negative-branch.js
DELETED
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Negative-branch (negative branch reservation) generation helper.
|
|
3
|
-
*
|
|
4
|
-
* The INVERSE of `de-restatement.ts`. Where de-restatement turns a UDE into the
|
|
5
|
-
* positive desired effect it becomes once an injection resolves it, this asks
|
|
6
|
-
* the opposite question: what NEW undesired effects might this injection ITSELF
|
|
7
|
-
* introduce? In Goldratt's Thinking Processes this is a "negative branch
|
|
8
|
-
* reservation" -- a side effect the injection drags in that the clean recolor
|
|
9
|
-
* never surfaces.
|
|
10
|
-
*
|
|
11
|
-
* Reuses the same model-invocation pattern as `de-restatement.ts` -- spawning
|
|
12
|
-
* the `claude` CLI in print mode -- so there is NO new client or secret wiring.
|
|
13
|
-
* A clean injection yields ZERO candidates (the model emits "NONE" -> []).
|
|
14
|
-
*
|
|
15
|
-
* The generated candidates are persisted as `crt_drift_proposals`
|
|
16
|
-
* (`proposal_kind='add_node'`) carrying `sourceInjectionId` + `isNegativeBranch`
|
|
17
|
-
* so a human ratifies/dismisses them: ratify -> the UDE is created and wired to
|
|
18
|
-
* the injection (see realign-apply `handleAddNode`); dismiss -> no residue.
|
|
19
|
-
*
|
|
20
|
-
* @module negative-branch
|
|
21
|
-
*/
|
|
22
|
-
import { spawn } from 'node:child_process';
|
|
23
|
-
import { callApi as defaultCallApi } from './queries/shared.js';
|
|
24
|
-
import { trackChildProcess } from './spawner/worker-registry.js';
|
|
25
|
-
const DEFAULT_TIMEOUT_MS = 2 * 60 * 1000;
|
|
26
|
-
export const NEGATIVE_BRANCH_SYSTEM_PROMPT = `You author Goldratt "negative branch reservations" for a reality tree: the NEW undesirable effects that an injection might itself introduce.
|
|
27
|
-
|
|
28
|
-
An injection resolves one problem but can drag in fresh side effects. Your job is to surface those candidate new undesired effects (UDEs) so a human can decide whether they are real.
|
|
29
|
-
|
|
30
|
-
Rules:
|
|
31
|
-
- Output ONE candidate undesired effect per line. No numbering, no bullets, no preamble, no commentary, no quotes.
|
|
32
|
-
- Each line is a single concrete negative outcome the injection could cause -- a genuinely NEW problem, not a restatement of the problem the injection solves.
|
|
33
|
-
- Be conservative: only list effects with a plausible causal link to the injection. Do NOT pad the list.
|
|
34
|
-
- If the injection introduces no plausible new undesired effect, output exactly: NONE`;
|
|
35
|
-
/** Exposed as a function to mirror `de-restatement`'s shape. */
|
|
36
|
-
export function buildNegativeBranchSystemPrompt() {
|
|
37
|
-
return NEGATIVE_BRANCH_SYSTEM_PROMPT;
|
|
38
|
-
}
|
|
39
|
-
/** Build the user message describing the injection (and any targeted UDEs). */
|
|
40
|
-
export function buildNegativeBranchUserMessage(inputs) {
|
|
41
|
-
const parts = [`Injection:\n${inputs.injectionStatement}`];
|
|
42
|
-
const targets = (inputs.targetUdeStatements ?? []).filter((s) => s && s.trim() !== '');
|
|
43
|
-
if (targets.length > 0) {
|
|
44
|
-
parts.push(`Undesired effect(s) this injection resolves:\n${targets.map((s) => `- ${s}`).join('\n')}`);
|
|
45
|
-
}
|
|
46
|
-
parts.push('List the candidate NEW undesired effects this injection might itself introduce, one per line. If there are none, output exactly: NONE');
|
|
47
|
-
return parts.join('\n\n');
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Parse raw model output into a list of candidate UDE statements.
|
|
51
|
-
*
|
|
52
|
-
* One candidate per line, trimmed, empties dropped. A lone "NONE" (case
|
|
53
|
-
* insensitive, optionally with surrounding punctuation) yields an empty list.
|
|
54
|
-
* Strips a leading bullet/number if the model added one despite the prompt.
|
|
55
|
-
*/
|
|
56
|
-
export function parseNegativeBranchCandidates(raw) {
|
|
57
|
-
let s = raw.trim();
|
|
58
|
-
// Strip code fences if the model wrapped the answer.
|
|
59
|
-
s = s.replace(/```[a-zA-Z]*\s*/g, '').replace(/```/g, '').trim();
|
|
60
|
-
if (s === '')
|
|
61
|
-
return [];
|
|
62
|
-
const lines = s.split('\n');
|
|
63
|
-
const out = [];
|
|
64
|
-
for (const rawLine of lines) {
|
|
65
|
-
let line = rawLine.trim();
|
|
66
|
-
if (line === '')
|
|
67
|
-
continue;
|
|
68
|
-
// Drop a leading bullet ("- ", "* ") or "1. " numbering.
|
|
69
|
-
line = line.replace(/^[-*]\s+/, '').replace(/^\d+[.)]\s+/, '').trim();
|
|
70
|
-
// Strip a single layer of surrounding quotes/backticks.
|
|
71
|
-
line = line.replace(/^["'`]+/, '').replace(/["'`]+$/, '').trim();
|
|
72
|
-
if (line === '')
|
|
73
|
-
continue;
|
|
74
|
-
// A standalone NONE sentinel means "no negative branches".
|
|
75
|
-
if (/^none[.!]?$/i.test(line))
|
|
76
|
-
continue;
|
|
77
|
-
out.push(line);
|
|
78
|
-
}
|
|
79
|
-
return out;
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Build the argv for the claude CLI invocation. Exposed for tests.
|
|
83
|
-
*
|
|
84
|
-
* NOTE: must NOT include `--bare` -- that flag makes the CLI skip credential
|
|
85
|
-
* loading, print "Not logged in" to stdout, and exit 1 (the negative-branch
|
|
86
|
-
* pass died silently before it ran).
|
|
87
|
-
*/
|
|
88
|
-
export function buildNegativeBranchCliArgs(systemPrompt) {
|
|
89
|
-
return [
|
|
90
|
-
'--print',
|
|
91
|
-
'--output-format', 'text',
|
|
92
|
-
'--no-session-persistence',
|
|
93
|
-
'--system-prompt', systemPrompt,
|
|
94
|
-
];
|
|
95
|
-
}
|
|
96
|
-
/** Default model invocation: spawn the `claude` CLI in print mode and return stdout. */
|
|
97
|
-
function invokeClaudeCli(systemPrompt, userMessage, opts) {
|
|
98
|
-
const claudeBin = opts.claudeBin ?? 'claude';
|
|
99
|
-
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
100
|
-
const spawnFn = opts.spawnFn ?? ((cmd, args, sopts) => spawn(cmd, args, sopts));
|
|
101
|
-
const args = buildNegativeBranchCliArgs(systemPrompt);
|
|
102
|
-
return new Promise((resolve, reject) => {
|
|
103
|
-
let child;
|
|
104
|
-
try {
|
|
105
|
-
child = spawnFn(claudeBin, args, { stdio: ['pipe', 'pipe', 'pipe'] });
|
|
106
|
-
}
|
|
107
|
-
catch (err) {
|
|
108
|
-
reject(new Error(`negative-branch spawn failed: ${err.message}`));
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
// Register so a graceful stop reaps this one-shot if it is still running.
|
|
112
|
-
trackChildProcess(child, 'negative-branch');
|
|
113
|
-
let stdout = '';
|
|
114
|
-
let stderr = '';
|
|
115
|
-
child.stdout?.on('data', (chunk) => { stdout += chunk.toString('utf8'); });
|
|
116
|
-
child.stderr?.on('data', (chunk) => { stderr += chunk.toString('utf8'); });
|
|
117
|
-
const timer = setTimeout(() => {
|
|
118
|
-
try {
|
|
119
|
-
child.kill('SIGKILL');
|
|
120
|
-
}
|
|
121
|
-
catch { /* ignore */ }
|
|
122
|
-
}, timeoutMs);
|
|
123
|
-
child.on('error', (err) => {
|
|
124
|
-
clearTimeout(timer);
|
|
125
|
-
reject(new Error(`negative-branch spawn error: ${err.message}`));
|
|
126
|
-
});
|
|
127
|
-
child.on('close', (code) => {
|
|
128
|
-
clearTimeout(timer);
|
|
129
|
-
if (code !== 0) {
|
|
130
|
-
reject(new Error(`negative-branch exited ${code}: ${stderr.slice(-2000)}`));
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
resolve(stdout);
|
|
134
|
-
});
|
|
135
|
-
try {
|
|
136
|
-
child.stdin?.write(userMessage);
|
|
137
|
-
child.stdin?.end();
|
|
138
|
-
}
|
|
139
|
-
catch (err) {
|
|
140
|
-
clearTimeout(timer);
|
|
141
|
-
reject(new Error(`negative-branch stdin write failed: ${err.message}`));
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Generate candidate negative-branch UDE statements for an injection.
|
|
147
|
-
*
|
|
148
|
-
* Returns 0-N candidates. A clean injection (model outputs "NONE") yields [].
|
|
149
|
-
* Throws only on model-invocation failure; callers catch and skip so a single
|
|
150
|
-
* failure never aborts the surrounding loop.
|
|
151
|
-
*/
|
|
152
|
-
export async function generateNegativeBranches(inputs, opts = {}) {
|
|
153
|
-
const systemPrompt = buildNegativeBranchSystemPrompt();
|
|
154
|
-
const userMessage = buildNegativeBranchUserMessage(inputs);
|
|
155
|
-
const invoke = opts.invokeModel ?? ((sys, msg) => invokeClaudeCli(sys, msg, opts));
|
|
156
|
-
const raw = await invoke(systemPrompt, userMessage);
|
|
157
|
-
return parseNegativeBranchCandidates(raw);
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Run generation for an injection, then persist each candidate as a
|
|
161
|
-
* ratify-able `add_node` drift proposal wired (via `sourceInjectionId`) to the
|
|
162
|
-
* injection that introduces it. Idempotency / dedupe is a human concern --
|
|
163
|
-
* proposals are surfaced, not auto-applied.
|
|
164
|
-
*
|
|
165
|
-
* A clean injection produces no candidates and creates no proposals -- but the
|
|
166
|
-
* pass still COMPLETED, so the injection's `negative_branch_pass_ran_at` marker
|
|
167
|
-
* is stamped regardless of candidate count (as long as generation did not
|
|
168
|
-
* throw). That durable marker, not the candidate count, is what later gates
|
|
169
|
-
* tree presentability: "ran clean" must be distinguishable from "never ran".
|
|
170
|
-
*/
|
|
171
|
-
export async function proposeNegativeBranchesForInjection(inputs, deps = {}) {
|
|
172
|
-
const callApi = deps.callApi ?? defaultCallApi;
|
|
173
|
-
const generate = deps.generate ?? generateNegativeBranches;
|
|
174
|
-
const now = deps.now ?? (() => new Date().toISOString());
|
|
175
|
-
// If generation throws, the pass did NOT complete -- the caller catches and
|
|
176
|
-
// the marker stays null so the injection remains a surfaced doubt (no stamp).
|
|
177
|
-
const candidates = await generate({
|
|
178
|
-
injectionStatement: inputs.injectionStatement,
|
|
179
|
-
targetUdeStatements: inputs.targetUdeStatements,
|
|
180
|
-
}, deps.generateOptions);
|
|
181
|
-
const proposalIds = [];
|
|
182
|
-
const errors = [];
|
|
183
|
-
for (const candidate of candidates) {
|
|
184
|
-
const params = {
|
|
185
|
-
realityTreeId: inputs.realityTreeId,
|
|
186
|
-
proposalKind: 'add_node',
|
|
187
|
-
observedState: 'injection introduces a new undesired effect',
|
|
188
|
-
proposedCorrection: candidate,
|
|
189
|
-
proposedMetadata: {
|
|
190
|
-
statement: candidate,
|
|
191
|
-
nodeType: 'undesired_effect',
|
|
192
|
-
viewScope: 'frt_only',
|
|
193
|
-
sourceInjectionId: inputs.injectionNodeId,
|
|
194
|
-
isNegativeBranch: true,
|
|
195
|
-
},
|
|
196
|
-
};
|
|
197
|
-
if (inputs.focusId)
|
|
198
|
-
params.focusId = inputs.focusId;
|
|
199
|
-
try {
|
|
200
|
-
const res = await callApi('crt_drift_proposal_create', params);
|
|
201
|
-
const id = res?.proposal?.id;
|
|
202
|
-
if (typeof id === 'string')
|
|
203
|
-
proposalIds.push(id);
|
|
204
|
-
}
|
|
205
|
-
catch (err) {
|
|
206
|
-
errors.push(`negative-branch proposal create failed: ${err.message}`);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
// Generation completed (did not throw) -- stamp the durable per-injection
|
|
210
|
-
// marker so a clean (zero-candidate) pass leaves a trace. This is the whole
|
|
211
|
-
// point: presentability gates on a pass having RUN, never on the branch set
|
|
212
|
-
// being non-empty. Stamping is best-effort -- a write failure leaves the
|
|
213
|
-
// marker null (the injection re-runs next tick) but never aborts the result.
|
|
214
|
-
//
|
|
215
|
-
// RESIDUAL (documented, tolerated): the "RUN" signal is "generate() did not
|
|
216
|
-
// throw", so a DEGRADED model call that returns an empty body would be
|
|
217
|
-
// recorded as a clean pass (zero candidates, marker stamped) even though it
|
|
218
|
-
// surfaced nothing real. We accept this for two reasons: (1) the dominant
|
|
219
|
-
// silent-failure mode -- the `--bare` flag printing "Not logged in" and
|
|
220
|
-
// exiting 1 -- was removed (see buildNegativeBranchCliArgs), so a non-zero
|
|
221
|
-
// exit now throws and correctly leaves the marker null; and (2) a genuinely
|
|
222
|
-
// empty negative-branch set is the LEGITIMATE clean case this marker exists to
|
|
223
|
-
// record, and "did the model degrade vs honestly find nothing" is not
|
|
224
|
-
// mechanically separable here without a check that could itself be confidently
|
|
225
|
-
// wrong -- the negative-branch signal is deliberately advisory, not a hard
|
|
226
|
-
// gate, so a rare false-clean costs an advisory hint, never a blocked tree.
|
|
227
|
-
let passRanAt = null;
|
|
228
|
-
const stampedAt = now();
|
|
229
|
-
try {
|
|
230
|
-
await callApi('reality_tree_node_update', {
|
|
231
|
-
nodeId: inputs.injectionNodeId,
|
|
232
|
-
negativeBranchPassRanAt: stampedAt,
|
|
233
|
-
});
|
|
234
|
-
passRanAt = stampedAt;
|
|
235
|
-
}
|
|
236
|
-
catch (err) {
|
|
237
|
-
errors.push(`negative-branch pass-marker stamp failed: ${err.message}`);
|
|
238
|
-
}
|
|
239
|
-
return { candidates, proposalIds, errors, passRanAt };
|
|
240
|
-
}
|
|
241
|
-
//# sourceMappingURL=negative-branch.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"negative-branch.js","sourceRoot":"","sources":["../src/negative-branch.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Threshold for the shortfall-disposition attempt bound.
|
|
3
|
-
*
|
|
4
|
-
* The CANONICAL declaration (Zod schema, ENV_VAR_METADATA entry, default,
|
|
5
|
-
* description) lives in packages/daemon-core/src/env-config.ts, exactly like the
|
|
6
|
-
* stall-detector thresholds in stall-detector-config.ts.
|
|
7
|
-
*
|
|
8
|
-
* It is read RAW here rather than through loadEnvConfig() for one reason:
|
|
9
|
-
* @telora/daemon-core is REGISTRY-INSTALLED, not a workspace symlink, so
|
|
10
|
-
* packages/daemon compiles and runs against the PUBLISHED dist. A field added to
|
|
11
|
-
* daemon-core's source is invisible to loadEnvConfig() here until a publish
|
|
12
|
-
* lands and the pin moves. This is the same registry-lag workaround
|
|
13
|
-
* stall-detectors.ts documents for escalation kinds.
|
|
14
|
-
*
|
|
15
|
-
* The raw read is allowlisted in scripts/lint-config.json under "env-reads"
|
|
16
|
-
* with that reason. WHEN daemon-core >0.2.69 IS PUBLISHED AND PINNED: delete the
|
|
17
|
-
* allowlist entry and change this to
|
|
18
|
-
* `loadEnvConfig().TELORA_SHORTFALL_DISPOSITION_ATTEMPT_CAP`.
|
|
19
|
-
*
|
|
20
|
-
* @module shortfall-disposition-config
|
|
21
|
-
*/
|
|
22
|
-
/**
|
|
23
|
-
* Max scoped disposition passes armed per focus before the daemon stops arming
|
|
24
|
-
* and escalates instead.
|
|
25
|
-
*
|
|
26
|
-
* Invalid values (non-numeric, <= 0) fall back to the default rather than
|
|
27
|
-
* disabling the bound: a zero or negative cap would escalate immediately on
|
|
28
|
-
* every held focus, and a NaN would compare false forever and never escalate --
|
|
29
|
-
* the permanent silent wait this bound exists to prevent. Once daemon-core is
|
|
30
|
-
* republished, Zod's positiveInt does this validation at startup and fails loud,
|
|
31
|
-
* which is strictly better; this is the interim.
|
|
32
|
-
*/
|
|
33
|
-
export declare function resolveShortfallDispositionAttemptCap(env?: NodeJS.ProcessEnv): number;
|
|
34
|
-
//# sourceMappingURL=shortfall-disposition-config.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"shortfall-disposition-config.d.ts","sourceRoot":"","sources":["../src/shortfall-disposition-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAKH;;;;;;;;;;GAUG;AACH,wBAAgB,qCAAqC,CACnD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAUR"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Threshold for the shortfall-disposition attempt bound.
|
|
3
|
-
*
|
|
4
|
-
* The CANONICAL declaration (Zod schema, ENV_VAR_METADATA entry, default,
|
|
5
|
-
* description) lives in packages/daemon-core/src/env-config.ts, exactly like the
|
|
6
|
-
* stall-detector thresholds in stall-detector-config.ts.
|
|
7
|
-
*
|
|
8
|
-
* It is read RAW here rather than through loadEnvConfig() for one reason:
|
|
9
|
-
* @telora/daemon-core is REGISTRY-INSTALLED, not a workspace symlink, so
|
|
10
|
-
* packages/daemon compiles and runs against the PUBLISHED dist. A field added to
|
|
11
|
-
* daemon-core's source is invisible to loadEnvConfig() here until a publish
|
|
12
|
-
* lands and the pin moves. This is the same registry-lag workaround
|
|
13
|
-
* stall-detectors.ts documents for escalation kinds.
|
|
14
|
-
*
|
|
15
|
-
* The raw read is allowlisted in scripts/lint-config.json under "env-reads"
|
|
16
|
-
* with that reason. WHEN daemon-core >0.2.69 IS PUBLISHED AND PINNED: delete the
|
|
17
|
-
* allowlist entry and change this to
|
|
18
|
-
* `loadEnvConfig().TELORA_SHORTFALL_DISPOSITION_ATTEMPT_CAP`.
|
|
19
|
-
*
|
|
20
|
-
* @module shortfall-disposition-config
|
|
21
|
-
*/
|
|
22
|
-
/** Must match the daemon-core default so the two cannot silently disagree. */
|
|
23
|
-
const DEFAULT_SHORTFALL_DISPOSITION_ATTEMPT_CAP = 3;
|
|
24
|
-
/**
|
|
25
|
-
* Max scoped disposition passes armed per focus before the daemon stops arming
|
|
26
|
-
* and escalates instead.
|
|
27
|
-
*
|
|
28
|
-
* Invalid values (non-numeric, <= 0) fall back to the default rather than
|
|
29
|
-
* disabling the bound: a zero or negative cap would escalate immediately on
|
|
30
|
-
* every held focus, and a NaN would compare false forever and never escalate --
|
|
31
|
-
* the permanent silent wait this bound exists to prevent. Once daemon-core is
|
|
32
|
-
* republished, Zod's positiveInt does this validation at startup and fails loud,
|
|
33
|
-
* which is strictly better; this is the interim.
|
|
34
|
-
*/
|
|
35
|
-
export function resolveShortfallDispositionAttemptCap(env = process.env) {
|
|
36
|
-
const raw = env.TELORA_SHORTFALL_DISPOSITION_ATTEMPT_CAP;
|
|
37
|
-
if (raw === undefined || raw.trim() === '') {
|
|
38
|
-
return DEFAULT_SHORTFALL_DISPOSITION_ATTEMPT_CAP;
|
|
39
|
-
}
|
|
40
|
-
const parsed = Number(raw);
|
|
41
|
-
if (!Number.isFinite(parsed) || !Number.isInteger(parsed) || parsed <= 0) {
|
|
42
|
-
return DEFAULT_SHORTFALL_DISPOSITION_ATTEMPT_CAP;
|
|
43
|
-
}
|
|
44
|
-
return parsed;
|
|
45
|
-
}
|
|
46
|
-
//# sourceMappingURL=shortfall-disposition-config.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"shortfall-disposition-config.js","sourceRoot":"","sources":["../src/shortfall-disposition-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,8EAA8E;AAC9E,MAAM,yCAAyC,GAAG,CAAC,CAAC;AAEpD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qCAAqC,CACnD,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,GAAG,GAAG,GAAG,CAAC,wCAAwC,CAAC;IACzD,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC3C,OAAO,yCAAyC,CAAC;IACnD,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;QACzE,OAAO,yCAAyC,CAAC;IACnD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|