@wrongstack/core 0.309.0 → 0.310.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/chronicle/index.js +113 -41
- package/dist/chronicle/metrics-ingest.d.ts +7 -0
- package/dist/chronicle/metrics-schema.d.ts +4 -1
- package/dist/chronicle/project-server.js +94 -38
- package/dist/chronicle/query.d.ts +1 -0
- package/dist/chronicle/sqlite-journal-schema.d.ts +2 -1
- package/dist/chronicle/types.d.ts +2 -0
- package/dist/{agent-status-helpers.d.ts → coordination/agent-status-helpers.d.ts} +1 -1
- package/dist/{agent-status-tracker.d.ts → coordination/agent-status-tracker.d.ts} +2 -2
- package/dist/{middleware → coordination}/collab-pause.d.ts +1 -1
- package/dist/coordination/director-kanban-queue-helpers.d.ts +1 -1
- package/dist/coordination/director.d.ts +7 -0
- package/dist/coordination/explore-companion.d.ts +9 -6
- package/dist/coordination/fleet-status-tool.d.ts +1 -1
- package/dist/coordination/index.d.ts +5 -1
- package/dist/coordination/index.js +2392 -405
- package/dist/coordination/kanban-dispatch-port.d.ts +30 -0
- package/dist/coordination/kanban-ops-port.d.ts +21 -0
- package/dist/coordination/mailbox-hooks.d.ts +1 -1
- package/dist/coordination/mailbox-project-server.js +14 -9
- package/dist/coordination/mutation-engine.d.ts +5 -3
- package/dist/core/context.d.ts +35 -44
- package/dist/core/conversation-state.d.ts +16 -52
- package/dist/core/index.js +92 -25
- package/dist/core/provider-runner.d.ts +2 -2
- package/dist/core/run-env.d.ts +7 -28
- package/dist/core/streaming-response-builder.d.ts +2 -2
- package/dist/execution/index.js +138 -162
- package/dist/goal/index.js +100 -22
- package/dist/hq/auth-store.d.ts +9 -0
- package/dist/hq/cost-bridge.d.ts +1 -1
- package/dist/hq/index.js +69 -7
- package/dist/index.d.ts +12 -5
- package/dist/index.js +21185 -26807
- package/dist/infrastructure/index.js +232 -135
- package/dist/infrastructure/provider-cache-ledger.d.ts +1 -1
- package/dist/infrastructure/token-counter.d.ts +5 -1
- package/dist/kernel/events/file-events.d.ts +6 -0
- package/dist/kernel/events/provider-events.d.ts +10 -7
- package/dist/kernel/events/session-events.d.ts +4 -4
- package/dist/kernel/events/tool-events.d.ts +12 -2
- package/dist/observability/index.js +1 -1
- package/dist/plugin/index.js +218 -47
- package/dist/prompts/index.js +360 -3
- package/dist/security/auto-approve-policy.d.ts +2 -2
- package/dist/security/index.d.ts +1 -0
- package/dist/security/index.js +224 -68
- package/dist/security/kanban-boundary.d.ts +1 -1
- package/dist/security/kanban-governance-port.d.ts +28 -0
- package/dist/security/permission-helpers.d.ts +11 -0
- package/dist/security/permission-policy.d.ts +10 -1
- package/dist/security/yolo-risk.d.ts +17 -0
- package/dist/session-catalog/index.js +34 -5
- package/dist/session-catalog/project-server.js +34 -5
- package/dist/session-catalog/protocol.d.ts +1 -1
- package/dist/session-catalog/registry.d.ts +1 -1
- package/dist/session-catalog/store-schema.d.ts +1 -1
- package/dist/session-catalog/store.d.ts +1 -1
- package/dist/skills/index.js +39 -6
- package/dist/storage/annotations-store.d.ts +1 -1
- package/dist/storage/board-store-port.d.ts +45 -0
- package/dist/storage/completed-work-checkpoint.d.ts +1 -1
- package/dist/storage/config-loader/types.d.ts +1 -1
- package/dist/storage/event-bus-port.d.ts +27 -0
- package/dist/storage/file-session-writer.d.ts +47 -5
- package/dist/storage/goal-coordination.d.ts +1 -1
- package/dist/storage/goal-store.d.ts +1 -1
- package/dist/storage/index.d.ts +3 -4
- package/dist/storage/index.js +1107 -1462
- package/dist/storage/plan-store.d.ts +1 -1
- package/dist/storage/queue-store.d.ts +1 -1
- package/dist/storage/replay-log-store.d.ts +1 -1
- package/dist/storage/session-recovery.d.ts +10 -0
- package/dist/storage/session-resume-validation.d.ts +13 -1
- package/dist/storage/session-store/events.d.ts +1 -1
- package/dist/storage/session-store/load-session-data.d.ts +1 -1
- package/dist/storage/session-store/rename-session.d.ts +1 -1
- package/dist/storage/session-store/resume-session.d.ts +3 -1
- package/dist/storage/session-store/session-store-index.d.ts +2 -1
- package/dist/storage/session-store/types.d.ts +1 -1
- package/dist/storage/session-store.d.ts +70 -0
- package/dist/storage/session-summary-tracker.d.ts +8 -0
- package/dist/storage/session-write-buffer.d.ts +31 -2
- package/dist/storage/task-store.d.ts +1 -1
- package/dist/storage/todos-checkpoint.d.ts +1 -1
- package/dist/storage/tool-audit-log.d.ts +1 -1
- package/dist/tasking/index.js +100 -22
- package/dist/tasking/task-tracker.d.ts +24 -1
- package/dist/types/compactor.d.ts +2 -2
- package/dist/types/context.d.ts +212 -0
- package/dist/types/conversation-state.d.ts +109 -0
- package/dist/types/error-handler.d.ts +2 -2
- package/dist/types/file-event-record.d.ts +6 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.js +17 -1
- package/dist/types/permission.d.ts +3 -3
- package/dist/types/plugin.d.ts +3 -3
- package/dist/types/provider-runner.d.ts +2 -2
- package/dist/types/provider.d.ts +10 -0
- package/dist/types/run-env.d.ts +32 -0
- package/dist/types/session.d.ts +3 -0
- package/dist/types/slash-command.d.ts +2 -2
- package/dist/types/token-counter.d.ts +30 -1
- package/dist/types/tool-executor.d.ts +2 -2
- package/dist/types/tool.d.ts +20 -5
- package/dist/utils/context-breakdown.d.ts +2 -2
- package/dist/utils/context-evidence.d.ts +12 -12
- package/dist/utils/crash-shield.d.ts +9 -0
- package/dist/utils/heap-watchdog.js +11 -3
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.js +126 -160
- package/dist/utils/regex-guard.d.ts +7 -30
- package/dist/utils/terminal-sanitize.d.ts +41 -0
- package/dist/utils/todos-format.d.ts +1 -1
- package/dist/utils/tool-subject.d.ts +1 -1
- package/dist/utils/tree-kill.d.ts +2 -0
- package/dist/utils/tree-kill.js +1 -0
- package/instructions/agents/chaos-monkey.md +5 -1
- package/instructions/coordination/subagent-baseline.md +10 -0
- package/instructions/system-lite.md +2 -0
- package/instructions/system-pro.md +40 -0
- package/instructions/system.md +15 -0
- package/package.json +7 -10
- package/dist/defaults/index.d.ts +0 -69
- package/dist/defaults/index.js +0 -37755
- /package/dist/{fleet-notifier.d.ts → coordination/fleet-notifier.d.ts} +0 -0
- /package/dist/{session-registry-atomic-file.d.ts → session-catalog/session-registry-atomic-file.d.ts} +0 -0
- /package/dist/{session-registry-types.d.ts → session-catalog/session-registry-types.d.ts} +0 -0
- /package/dist/{session-registry.d.ts → session-catalog/session-registry.d.ts} +0 -0
package/dist/execution/index.js
CHANGED
|
@@ -488,7 +488,9 @@ function hasToolUseBlock(message) {
|
|
|
488
488
|
return message?.role === "assistant" && Array.isArray(message.content) && message.content.some((block) => block.type === "tool_use");
|
|
489
489
|
}
|
|
490
490
|
var ConversationState = class {
|
|
491
|
+
/** Owning context; public for structural typing (Roadmap 10A). */
|
|
491
492
|
ctx;
|
|
493
|
+
/** Subscribers; public for structural typing (Roadmap 10A). */
|
|
492
494
|
listeners = /* @__PURE__ */ new Set();
|
|
493
495
|
_revision = 0;
|
|
494
496
|
constructor(ctx) {
|
|
@@ -543,9 +545,8 @@ var ConversationState = class {
|
|
|
543
545
|
}
|
|
544
546
|
/**
|
|
545
547
|
* How many of the oldest messages must be dropped to satisfy both retention
|
|
546
|
-
* caps — count ({@link
|
|
547
|
-
*
|
|
548
|
-
* fits, which is the overwhelmingly common case.
|
|
548
|
+
* caps — count and size (see {@link AgentContext.messageLimits}). Returns 0
|
|
549
|
+
* when the history already fits, which is the overwhelmingly common case.
|
|
549
550
|
*
|
|
550
551
|
* The size pass reads the per-message `_estTokens` cache populated at
|
|
551
552
|
* mutation time, so it is a sum over numbers rather than a re-walk of
|
|
@@ -553,9 +554,7 @@ var ConversationState = class {
|
|
|
553
554
|
* cap determines the starting index for the sum but does not gate it.
|
|
554
555
|
*/
|
|
555
556
|
overflowCount(arr) {
|
|
556
|
-
const
|
|
557
|
-
const maxMessages = contextClass.MAX_MESSAGES;
|
|
558
|
-
const maxMessageTokens = contextClass.MAX_MESSAGE_TOKENS;
|
|
557
|
+
const { maxMessages, maxMessageTokens } = this.ctx.messageLimits;
|
|
559
558
|
let drop = maxMessages > 0 ? Math.max(0, arr.length - maxMessages) : 0;
|
|
560
559
|
if (maxMessageTokens <= 0) return this.protocolSafeDropCount(arr, drop);
|
|
561
560
|
let total = 0;
|
|
@@ -826,6 +825,10 @@ var Context = class _Context {
|
|
|
826
825
|
* so storage operations can include it in `storage.*` events.
|
|
827
826
|
*/
|
|
828
827
|
traceId;
|
|
828
|
+
/** Logical provider request whose response produced the current tool calls. */
|
|
829
|
+
activeLogicalRequestId = void 0;
|
|
830
|
+
/** Content-addressed prompt composition for {@link activeLogicalRequestId}. */
|
|
831
|
+
activePromptManifestId = void 0;
|
|
829
832
|
/**
|
|
830
833
|
* Session id pinned to the currently-executing run. Set by `Agent.run()`
|
|
831
834
|
* at run start and cleared when the run ends. Event-emission sites must
|
|
@@ -851,6 +854,7 @@ var Context = class _Context {
|
|
|
851
854
|
return resolveEventSessionId(this);
|
|
852
855
|
}
|
|
853
856
|
/** Callbacks fired when `setWorkingDir()` changes the working directory. */
|
|
857
|
+
/** WorkingDir-change callbacks; public for structural typing (Roadmap 10A). */
|
|
854
858
|
_onWorkingDirChanged = [];
|
|
855
859
|
/**
|
|
856
860
|
* Serializes externally requested provider/model changes. Request creation
|
|
@@ -1106,7 +1110,16 @@ var Context = class _Context {
|
|
|
1106
1110
|
* For hooks that must survive across run boundaries (mailbox heartbeat,
|
|
1107
1111
|
* awareness polling, HQ publisher), prefer `registerAgentHook` instead.
|
|
1108
1112
|
*/
|
|
1113
|
+
/** Run-scoped abort hooks (drained by drainAbortHooks). Public for structural typing (Roadmap 10A). */
|
|
1109
1114
|
abortHooks = /* @__PURE__ */ new Set();
|
|
1115
|
+
/** Retention limits honoring runtime subclass overrides of the statics. */
|
|
1116
|
+
get messageLimits() {
|
|
1117
|
+
const cls = this.constructor;
|
|
1118
|
+
return Object.freeze({
|
|
1119
|
+
maxMessages: cls.MAX_MESSAGES,
|
|
1120
|
+
maxMessageTokens: cls.MAX_MESSAGE_TOKENS
|
|
1121
|
+
});
|
|
1122
|
+
}
|
|
1110
1123
|
registerAbortHook(fn) {
|
|
1111
1124
|
this.abortHooks.add(fn);
|
|
1112
1125
|
return () => this.abortHooks.delete(fn);
|
|
@@ -1131,6 +1144,7 @@ var Context = class _Context {
|
|
|
1131
1144
|
* awareness polling interval, HQ publisher connection, and auto-compaction
|
|
1132
1145
|
* timer — resources that must survive from the first run to the last.
|
|
1133
1146
|
*/
|
|
1147
|
+
/** Session-lifetime teardown hooks (drained by drainAgentHooks). Public for structural typing (Roadmap 10A). */
|
|
1134
1148
|
agentHooks = /* @__PURE__ */ new Set();
|
|
1135
1149
|
registerAgentHook(fn) {
|
|
1136
1150
|
this.agentHooks.add(fn);
|
|
@@ -1311,6 +1325,9 @@ var Context = class _Context {
|
|
|
1311
1325
|
agentName: this.agentName,
|
|
1312
1326
|
provider: typeof this.provider === "object" ? this.provider.id : String(this.provider),
|
|
1313
1327
|
model: this.model,
|
|
1328
|
+
...this.activeLogicalRequestId ? { logicalRequestId: this.activeLogicalRequestId } : {},
|
|
1329
|
+
...this.activePromptManifestId ? { promptManifestId: this.activePromptManifestId } : {},
|
|
1330
|
+
provenanceConfidence: this.activeLogicalRequestId && this.activePromptManifestId ? "explicit" : "unknown",
|
|
1314
1331
|
toolName: input.toolName,
|
|
1315
1332
|
toolUseId: input.toolUseId,
|
|
1316
1333
|
scope,
|
|
@@ -1338,6 +1355,9 @@ var Context = class _Context {
|
|
|
1338
1355
|
agentName: this.agentName,
|
|
1339
1356
|
provider: record.provider,
|
|
1340
1357
|
model: record.model,
|
|
1358
|
+
...record.logicalRequestId ? { logicalRequestId: record.logicalRequestId } : {},
|
|
1359
|
+
...record.promptManifestId ? { promptManifestId: record.promptManifestId } : {},
|
|
1360
|
+
provenanceConfidence: record.provenanceConfidence,
|
|
1341
1361
|
toolName: input.toolName,
|
|
1342
1362
|
toolUseId: input.toolUseId,
|
|
1343
1363
|
scope,
|
|
@@ -3570,127 +3590,11 @@ function assertNever(x, message) {
|
|
|
3570
3590
|
}
|
|
3571
3591
|
|
|
3572
3592
|
// src/utils/regex-guard.ts
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
// Adjacent quantifiers: a++ a*+
|
|
3579
|
-
/[+*]{2,}/,
|
|
3580
|
-
// Quantifier on alternation with length 2+
|
|
3581
|
-
/\([^|)]+\|[^)]+\)[+*][+*]/,
|
|
3582
|
-
// Greedy quantifier inside lookahead/lookbehind — (?!.*a+)
|
|
3583
|
-
/[([][^)\]]*[+*][^)\]]*[)\]][^)]*\?\??/
|
|
3584
|
-
];
|
|
3585
|
-
function hasAmbiguousQuantifiedAlternation(pattern) {
|
|
3586
|
-
for (let i = 0; i < pattern.length; i++) {
|
|
3587
|
-
if (pattern[i] !== "(") continue;
|
|
3588
|
-
if (i > 0 && pattern[i - 1] === "\\") continue;
|
|
3589
|
-
let depth = 0;
|
|
3590
|
-
let inClass = false;
|
|
3591
|
-
let j = i;
|
|
3592
|
-
for (; j < pattern.length; j++) {
|
|
3593
|
-
const ch = pattern[j];
|
|
3594
|
-
if (ch === "\\") {
|
|
3595
|
-
j++;
|
|
3596
|
-
continue;
|
|
3597
|
-
}
|
|
3598
|
-
if (inClass) {
|
|
3599
|
-
if (ch === "]") inClass = false;
|
|
3600
|
-
continue;
|
|
3601
|
-
}
|
|
3602
|
-
if (ch === "[") {
|
|
3603
|
-
inClass = true;
|
|
3604
|
-
continue;
|
|
3605
|
-
}
|
|
3606
|
-
if (ch === "(") depth++;
|
|
3607
|
-
else if (ch === ")") {
|
|
3608
|
-
depth--;
|
|
3609
|
-
if (depth === 0) break;
|
|
3610
|
-
}
|
|
3611
|
-
}
|
|
3612
|
-
if (j >= pattern.length) return false;
|
|
3613
|
-
const next = pattern[j + 1];
|
|
3614
|
-
if (next !== "+" && next !== "*" && next !== "{") continue;
|
|
3615
|
-
let inner = pattern.slice(i + 1, j);
|
|
3616
|
-
inner = inner.replace(/^\?(?::|<?[=!])/u, "");
|
|
3617
|
-
const branches = [];
|
|
3618
|
-
let current = "";
|
|
3619
|
-
let d = 0;
|
|
3620
|
-
let cls = false;
|
|
3621
|
-
for (let k = 0; k < inner.length; k++) {
|
|
3622
|
-
const ch = inner[k];
|
|
3623
|
-
if (ch === "\\") {
|
|
3624
|
-
current += ch + (inner[k + 1] ?? "");
|
|
3625
|
-
k++;
|
|
3626
|
-
continue;
|
|
3627
|
-
}
|
|
3628
|
-
if (cls) {
|
|
3629
|
-
if (ch === "]") cls = false;
|
|
3630
|
-
current += ch;
|
|
3631
|
-
continue;
|
|
3632
|
-
}
|
|
3633
|
-
if (ch === "[") {
|
|
3634
|
-
cls = true;
|
|
3635
|
-
current += ch;
|
|
3636
|
-
continue;
|
|
3637
|
-
}
|
|
3638
|
-
if (ch === "(") d++;
|
|
3639
|
-
if (ch === ")") d--;
|
|
3640
|
-
if (ch === "|" && d === 0) {
|
|
3641
|
-
branches.push(current);
|
|
3642
|
-
current = "";
|
|
3643
|
-
continue;
|
|
3644
|
-
}
|
|
3645
|
-
current += ch;
|
|
3646
|
-
}
|
|
3647
|
-
branches.push(current);
|
|
3648
|
-
if (branches.length < 2) continue;
|
|
3649
|
-
for (let a = 0; a < branches.length; a++) {
|
|
3650
|
-
for (let b = a + 1; b < branches.length; b++) {
|
|
3651
|
-
const x = branches[a];
|
|
3652
|
-
const y = branches[b];
|
|
3653
|
-
if (x === "" || y === "") return true;
|
|
3654
|
-
if (x === y || x.startsWith(y) || y.startsWith(x)) return true;
|
|
3655
|
-
}
|
|
3656
|
-
}
|
|
3657
|
-
}
|
|
3658
|
-
return false;
|
|
3659
|
-
}
|
|
3660
|
-
function compileUserRegex(pattern, flags) {
|
|
3661
|
-
if (typeof pattern !== "string") {
|
|
3662
|
-
return { ok: false, reason: "pattern must be a string" };
|
|
3663
|
-
}
|
|
3664
|
-
if (pattern.length === 0) {
|
|
3665
|
-
return { ok: false, reason: "pattern is empty" };
|
|
3666
|
-
}
|
|
3667
|
-
if (pattern.length > MAX_PATTERN_LEN) {
|
|
3668
|
-
return { ok: false, reason: `pattern exceeds ${MAX_PATTERN_LEN} characters` };
|
|
3669
|
-
}
|
|
3670
|
-
for (const rx of DANGEROUS_PATTERNS) {
|
|
3671
|
-
if (rx.test(pattern)) {
|
|
3672
|
-
return {
|
|
3673
|
-
ok: false,
|
|
3674
|
-
reason: "pattern looks vulnerable to catastrophic backtracking \u2014 rewrite without nested quantifiers"
|
|
3675
|
-
};
|
|
3676
|
-
}
|
|
3677
|
-
}
|
|
3678
|
-
if (hasAmbiguousQuantifiedAlternation(pattern)) {
|
|
3679
|
-
return {
|
|
3680
|
-
ok: false,
|
|
3681
|
-
reason: "pattern quantifies an alternation with overlapping branches \u2014 rewrite so no two branches can match the same text"
|
|
3682
|
-
};
|
|
3683
|
-
}
|
|
3684
|
-
try {
|
|
3685
|
-
return { ok: true, regex: new RegExp(pattern, flags) };
|
|
3686
|
-
} catch (err) {
|
|
3687
|
-
return {
|
|
3688
|
-
ok: false,
|
|
3689
|
-
reason: err instanceof Error ? err.message : "invalid regex"
|
|
3690
|
-
};
|
|
3691
|
-
}
|
|
3692
|
-
}
|
|
3693
|
-
var MAX_SUBJECT_LEN = 64 * 1024;
|
|
3593
|
+
import {
|
|
3594
|
+
capSubject,
|
|
3595
|
+
compileUserRegex,
|
|
3596
|
+
MAX_SUBJECT_LEN
|
|
3597
|
+
} from "@wrongstack/primitives";
|
|
3694
3598
|
|
|
3695
3599
|
// src/execution/autonomous-runner.ts
|
|
3696
3600
|
var DoneConditionChecker = class {
|
|
@@ -5088,7 +4992,12 @@ function isContextOverflowShaped(err) {
|
|
|
5088
4992
|
const providerErr = err;
|
|
5089
4993
|
if (providerErr.kind === "context_overflow" || providerErr.status === 413) return true;
|
|
5090
4994
|
if (providerErr.status < 400) return false;
|
|
5091
|
-
const text = [
|
|
4995
|
+
const text = [
|
|
4996
|
+
providerErr.message,
|
|
4997
|
+
providerErr.body?.message,
|
|
4998
|
+
providerErr.body?.type,
|
|
4999
|
+
providerErr.body?.raw
|
|
5000
|
+
].filter(Boolean).join("\n");
|
|
5092
5001
|
return CONTEXT_OVERFLOW_RE.test(text);
|
|
5093
5002
|
}
|
|
5094
5003
|
function describeStatus(status, type) {
|
|
@@ -10393,27 +10302,39 @@ var DefaultErrorHandler = class {
|
|
|
10393
10302
|
import { execFile } from "node:child_process";
|
|
10394
10303
|
import { promisify } from "node:util";
|
|
10395
10304
|
|
|
10396
|
-
// src/storage/
|
|
10397
|
-
|
|
10305
|
+
// src/storage/board-store-port.ts
|
|
10306
|
+
var notWired = () => {
|
|
10307
|
+
throw new Error(
|
|
10308
|
+
"Kanban BoardStorePort is not wired \u2014 register the implementation at the CLI composition root (see setBoardStorePort)."
|
|
10309
|
+
);
|
|
10310
|
+
};
|
|
10311
|
+
var port = void 0;
|
|
10312
|
+
function boardStore() {
|
|
10313
|
+
return port ?? notWired();
|
|
10314
|
+
}
|
|
10315
|
+
function tryBoardStore() {
|
|
10316
|
+
return port ?? null;
|
|
10317
|
+
}
|
|
10398
10318
|
|
|
10399
10319
|
// src/storage/goal-kanban.ts
|
|
10400
|
-
import { addTask, createBoard, getBoard, listBoards, removeBoard } from "@wrongstack/kanban";
|
|
10401
10320
|
var GOAL_BOARD_TAG_PREFIX = "goal:";
|
|
10402
10321
|
async function findGoalKanbanBoard(projectRoot, boardId) {
|
|
10403
10322
|
if (!projectRoot || !boardId) return null;
|
|
10404
10323
|
try {
|
|
10405
|
-
return await getBoard(projectRoot, boardId);
|
|
10324
|
+
return await boardStore().getBoard(projectRoot, boardId);
|
|
10406
10325
|
} catch {
|
|
10407
10326
|
return null;
|
|
10408
10327
|
}
|
|
10409
10328
|
}
|
|
10410
10329
|
async function findGoalBoardByTag(projectRoot, goalFile) {
|
|
10411
10330
|
if (!projectRoot) return null;
|
|
10331
|
+
const store = tryBoardStore();
|
|
10332
|
+
if (!store) return null;
|
|
10412
10333
|
const tag = goalTag(goalFile);
|
|
10413
|
-
const boards = await listBoards(projectRoot);
|
|
10334
|
+
const boards = await store.listBoards(projectRoot);
|
|
10414
10335
|
const matched = boards.find((b) => b.tags?.includes(tag));
|
|
10415
10336
|
if (!matched) return null;
|
|
10416
|
-
return getBoard(projectRoot, matched.id).catch(() => null);
|
|
10337
|
+
return store.getBoard(projectRoot, matched.id).catch(() => null);
|
|
10417
10338
|
}
|
|
10418
10339
|
function goalTag(goalFile) {
|
|
10419
10340
|
const goal = (goalFile.refinedGoal || goalFile.goal).replace(/\s+/g, "-").slice(0, 24).toLowerCase();
|
|
@@ -10577,7 +10498,7 @@ async function refreshGoalKanban(projectRoot, goal, completed, resolvedBoard) {
|
|
|
10577
10498
|
const originMatch = task.origin?.system === "goal" && task.origin?.taskId ? originKeys.has(task.origin.taskId) : false;
|
|
10578
10499
|
const titleMatch = !task.origin?.taskId && completedTitles.has(normalizeTitle(task.title));
|
|
10579
10500
|
if (!originMatch && !titleMatch) continue;
|
|
10580
|
-
const result = await updateTask(
|
|
10501
|
+
const result = await boardStore().updateTask(
|
|
10581
10502
|
projectRoot,
|
|
10582
10503
|
board.id,
|
|
10583
10504
|
task.id,
|
|
@@ -17098,11 +17019,13 @@ var CHAOS_MONKEY_AGENT = {
|
|
|
17098
17019
|
tools: [...TOOLS.build],
|
|
17099
17020
|
skillNames: ["testing", "typescript-strict"],
|
|
17100
17021
|
spawnBudgetExempt: true,
|
|
17101
|
-
//
|
|
17102
|
-
//
|
|
17103
|
-
//
|
|
17104
|
-
//
|
|
17105
|
-
|
|
17022
|
+
// Run in the live checkout: mutation targets are usually freshly
|
|
17023
|
+
// written and uncommitted — a worktree spawned from HEAD would not
|
|
17024
|
+
// contain them and every mutant would drift. The mutation_test tool
|
|
17025
|
+
// honors this value as its default; callers can still override per
|
|
17026
|
+
// call via its `chaosWorktree` input when targets are committed and
|
|
17027
|
+
// isolation is wanted.
|
|
17028
|
+
worktree: "off",
|
|
17106
17029
|
// Report travels via submit_result + final text, not the leader's stream.
|
|
17107
17030
|
textStream: "silent",
|
|
17108
17031
|
toolStream: "silent"
|
|
@@ -20441,6 +20364,10 @@ var DefaultSkillLoader = class {
|
|
|
20441
20364
|
);
|
|
20442
20365
|
for (const e of entries) {
|
|
20443
20366
|
if (!await entryIsDirectory(dir, e)) continue;
|
|
20367
|
+
if (!isValidSkillNameFormat(e.name)) {
|
|
20368
|
+
this.skipped.push({ dir, entry: e.name, reason: "invalid-name-format" });
|
|
20369
|
+
continue;
|
|
20370
|
+
}
|
|
20444
20371
|
const skillFile = path15.join(dir, e.name, "SKILL.md");
|
|
20445
20372
|
let raw;
|
|
20446
20373
|
try {
|
|
@@ -21510,9 +21437,21 @@ function renderCommandLine(command, args) {
|
|
|
21510
21437
|
});
|
|
21511
21438
|
return [command, ...rendered].join(" ");
|
|
21512
21439
|
}
|
|
21513
|
-
function
|
|
21440
|
+
function renderSubjectFields(obj, fields) {
|
|
21441
|
+
const parts = [];
|
|
21442
|
+
for (const field of fields) {
|
|
21443
|
+
const value = obj[field];
|
|
21444
|
+
if (value === void 0 || value === null || value === "" || value === false) continue;
|
|
21445
|
+
const str = String(value);
|
|
21446
|
+
parts.push(`${field}=${/\s/.test(str) ? `"${str.replace(/"/g, '\\"')}"` : str}`);
|
|
21447
|
+
}
|
|
21448
|
+
return parts.join(" ");
|
|
21449
|
+
}
|
|
21450
|
+
function subjectForToolInput(toolName, input, subjectKey, subjectFields) {
|
|
21514
21451
|
if (!input || typeof input !== "object") return void 0;
|
|
21515
21452
|
const obj = input;
|
|
21453
|
+
const extra = subjectFields && subjectFields.length > 0 ? renderSubjectFields(obj, subjectFields) : "";
|
|
21454
|
+
const withExtra = (base) => extra ? `${base} ${extra}` : base;
|
|
21516
21455
|
if (subjectKey) {
|
|
21517
21456
|
const value = obj[subjectKey];
|
|
21518
21457
|
if (Array.isArray(value)) {
|
|
@@ -21528,9 +21467,9 @@ function subjectForToolInput(toolName, input, subjectKey) {
|
|
|
21528
21467
|
if (subjectKey === "command") {
|
|
21529
21468
|
const rendered = renderCommandLine(value, obj["args"]);
|
|
21530
21469
|
if (value === "commit" && obj["dry_run"] === true) {
|
|
21531
|
-
return `${escapeGlobSubject(rendered)}:dry-run`;
|
|
21470
|
+
return `${escapeGlobSubject(withExtra(rendered))}:dry-run`;
|
|
21532
21471
|
}
|
|
21533
|
-
return escapeGlobSubject(rendered);
|
|
21472
|
+
return escapeGlobSubject(withExtra(rendered));
|
|
21534
21473
|
}
|
|
21535
21474
|
if (subjectKey === "directory" && obj["dry_run"] === true) {
|
|
21536
21475
|
return `${escapeGlobSubject(value)}:dry-run`;
|
|
@@ -22025,6 +21964,8 @@ function logToolSuccess(opts, ctx, use, toolName, durationMs, outputChars) {
|
|
|
22025
21964
|
id: use.id,
|
|
22026
21965
|
sessionId: ctx.session.id,
|
|
22027
21966
|
...ctx.traceId ? { traceId: ctx.traceId } : {},
|
|
21967
|
+
...ctx.activeLogicalRequestId ? { logicalRequestId: ctx.activeLogicalRequestId } : {},
|
|
21968
|
+
...ctx.activePromptManifestId ? { promptManifestId: ctx.activePromptManifestId } : {},
|
|
22028
21969
|
agentId: ctx.agentId ?? "<unknown>",
|
|
22029
21970
|
durationMs,
|
|
22030
21971
|
outputChars
|
|
@@ -22049,6 +21990,8 @@ function logToolFailure(opts, ctx, use, toolName, durationMs, err) {
|
|
|
22049
21990
|
id: use.id,
|
|
22050
21991
|
sessionId: ctx.session.id,
|
|
22051
21992
|
...ctx.traceId ? { traceId: ctx.traceId } : {},
|
|
21993
|
+
...ctx.activeLogicalRequestId ? { logicalRequestId: ctx.activeLogicalRequestId } : {},
|
|
21994
|
+
...ctx.activePromptManifestId ? { promptManifestId: ctx.activePromptManifestId } : {},
|
|
22052
21995
|
agentId: ctx.agentId ?? "<unknown>",
|
|
22053
21996
|
durationMs,
|
|
22054
21997
|
category,
|
|
@@ -22118,14 +22061,20 @@ import { isDeepStrictEqual } from "node:util";
|
|
|
22118
22061
|
// src/security/kanban-boundary.ts
|
|
22119
22062
|
import { realpath } from "node:fs/promises";
|
|
22120
22063
|
import * as path17 from "node:path";
|
|
22121
|
-
|
|
22122
|
-
|
|
22123
|
-
|
|
22124
|
-
|
|
22125
|
-
|
|
22126
|
-
|
|
22127
|
-
}
|
|
22128
|
-
var
|
|
22064
|
+
|
|
22065
|
+
// src/security/kanban-governance-port.ts
|
|
22066
|
+
var notWired2 = () => {
|
|
22067
|
+
throw new Error(
|
|
22068
|
+
"KanbanGovernancePort is not wired \u2014 register the implementation at the CLI composition root (see setKanbanGovernance)."
|
|
22069
|
+
);
|
|
22070
|
+
};
|
|
22071
|
+
var port2 = void 0;
|
|
22072
|
+
function kanbanGovernance() {
|
|
22073
|
+
return port2 ?? notWired2();
|
|
22074
|
+
}
|
|
22075
|
+
|
|
22076
|
+
// src/security/kanban-boundary.ts
|
|
22077
|
+
var GOVERNANCE_CONTROL_TOOLS = /* @__PURE__ */ new Set(["kanban", "plan", "task", "todo", "nextsteps"]);
|
|
22129
22078
|
var PATH_KEYS = /* @__PURE__ */ new Set([
|
|
22130
22079
|
"path",
|
|
22131
22080
|
"paths",
|
|
@@ -22160,7 +22109,10 @@ async function evaluateToolKanbanBoundary(tool, input, ctx, options = {}) {
|
|
|
22160
22109
|
reason: "Kanban governance is mandatory before product mutation. Create a managed card, add its required details and executable acceptance criteria, then call kanban start_task to bind it to this run."
|
|
22161
22110
|
} : { decision: "allow" };
|
|
22162
22111
|
}
|
|
22163
|
-
const board = await readBoard(
|
|
22112
|
+
const board = await kanbanGovernance().readBoard(
|
|
22113
|
+
identity.policyRoot ?? ctx.projectRoot,
|
|
22114
|
+
identity.boardId
|
|
22115
|
+
);
|
|
22164
22116
|
if (!board) {
|
|
22165
22117
|
return governanceRequired ? {
|
|
22166
22118
|
decision: "block",
|
|
@@ -22186,22 +22138,39 @@ async function evaluateToolKanbanBoundary(tool, input, ctx, options = {}) {
|
|
|
22186
22138
|
taskId: identity.taskId
|
|
22187
22139
|
};
|
|
22188
22140
|
}
|
|
22189
|
-
const readiness = evaluateContractGraphReadiness(board, task.id);
|
|
22141
|
+
const readiness = kanbanGovernance().evaluateContractGraphReadiness(board, task.id);
|
|
22190
22142
|
if (!readiness.ready) {
|
|
22143
|
+
const issueLines = readiness.issues.map((issue, index) => ` ${index + 1}. ${issue.message}`).join("\n");
|
|
22191
22144
|
return {
|
|
22192
22145
|
decision: "block",
|
|
22193
|
-
reason:
|
|
22146
|
+
reason: `Active card failed contract-readiness check (${readiness.issues.length} issue(s)):
|
|
22147
|
+
` + issueLines + `
|
|
22148
|
+
Resolve the readiness issues, then call kanban start_task to retry.`,
|
|
22194
22149
|
boardId: board.id,
|
|
22195
22150
|
taskId: task.id,
|
|
22196
22151
|
readinessIssues: readiness.issues
|
|
22197
22152
|
};
|
|
22198
22153
|
}
|
|
22199
|
-
|
|
22200
|
-
|
|
22201
|
-
|
|
22154
|
+
const lifecycleStage = task.lifecycle?.currentStage;
|
|
22155
|
+
const assignmentStatus = task.assignment?.status;
|
|
22156
|
+
const lifecycleOk = lifecycleStage === "running";
|
|
22157
|
+
const assignmentOk = assignmentStatus === "running";
|
|
22158
|
+
if (!lifecycleOk || !assignmentOk) {
|
|
22159
|
+
const failed = [];
|
|
22160
|
+
let reassessmentNote = "";
|
|
22161
|
+
if (!lifecycleOk) {
|
|
22162
|
+
failed.push(`lifecycle.currentStage (got: ${lifecycleStage ?? "missing"}; want: 'running')`);
|
|
22163
|
+
}
|
|
22164
|
+
if (!assignmentOk) {
|
|
22165
|
+
failed.push(`assignment.status (got: ${assignmentStatus ?? "missing"}; want: 'running')`);
|
|
22166
|
+
if (lifecycleOk && (assignmentStatus === "queued" || assignmentStatus === void 0 || assignmentStatus === null)) {
|
|
22167
|
+
reassessmentNote = '\nNote: lifecycle is still "running" but the assignment was cleared \u2014 the automated kanban reassessment agent likely reset the binding. Re-issue kanban start_task to re-bind the leader to this card.';
|
|
22168
|
+
}
|
|
22169
|
+
}
|
|
22202
22170
|
return {
|
|
22203
22171
|
decision: "block",
|
|
22204
|
-
reason: `Active card
|
|
22172
|
+
reason: `Active card failed ${failed.length} governance check(s) before product mutation:
|
|
22173
|
+
` + failed.map((line, index) => ` ${index + 1}. ${line}`).join("\n") + reassessmentNote,
|
|
22205
22174
|
boardId: board.id,
|
|
22206
22175
|
taskId: task.id
|
|
22207
22176
|
};
|
|
@@ -22219,7 +22188,7 @@ async function evaluateToolKanbanBoundary(tool, input, ctx, options = {}) {
|
|
|
22219
22188
|
};
|
|
22220
22189
|
}
|
|
22221
22190
|
}
|
|
22222
|
-
const layers = resolveKanbanBoundaryLayers(board, task);
|
|
22191
|
+
const layers = kanbanGovernance().resolveKanbanBoundaryLayers(board, task);
|
|
22223
22192
|
if (layers.length === 0) return { decision: "allow" };
|
|
22224
22193
|
const caps = tool.capabilities ?? [];
|
|
22225
22194
|
const access2 = caps.includes("fs.write") || caps.includes("fs.write.outside-project") ? "write" : caps.includes("fs.read") ? "read" : void 0;
|
|
@@ -22227,10 +22196,10 @@ async function evaluateToolKanbanBoundary(tool, input, ctx, options = {}) {
|
|
|
22227
22196
|
const candidates = access2 ? await extractCandidatePaths(tool.name, input, ctx) : [];
|
|
22228
22197
|
let evaluation;
|
|
22229
22198
|
if (shellLike || access2 && candidates.length === 0) {
|
|
22230
|
-
evaluation = evaluateKanbanBoundaryOpaque(layers, tool.name);
|
|
22199
|
+
evaluation = kanbanGovernance().evaluateKanbanBoundaryOpaque(layers, tool.name);
|
|
22231
22200
|
} else if (access2) {
|
|
22232
22201
|
const results = candidates.map(
|
|
22233
|
-
(candidate) => evaluateKanbanBoundaryPath(layers, candidate, access2)
|
|
22202
|
+
(candidate) => kanbanGovernance().evaluateKanbanBoundaryPath(layers, candidate, access2)
|
|
22234
22203
|
);
|
|
22235
22204
|
evaluation = results.find((result) => result.decision === "block") ?? results.find((result) => result.decision === "confirm") ?? { decision: "allow" };
|
|
22236
22205
|
} else {
|
|
@@ -22757,6 +22726,8 @@ var ToolExecutor = class _ToolExecutor {
|
|
|
22757
22726
|
this.opts.events?.emit("permission.evaluated", {
|
|
22758
22727
|
sessionId: resolveEventSessionId(ctx),
|
|
22759
22728
|
...ctx.traceId ? { traceId: ctx.traceId } : {},
|
|
22729
|
+
...ctx.activeLogicalRequestId ? { logicalRequestId: ctx.activeLogicalRequestId } : {},
|
|
22730
|
+
...ctx.activePromptManifestId ? { promptManifestId: ctx.activePromptManifestId } : {},
|
|
22760
22731
|
...ctx.agentId ? { agentId: ctx.agentId } : {},
|
|
22761
22732
|
name: tool.name,
|
|
22762
22733
|
id: use.id,
|
|
@@ -22781,7 +22752,7 @@ var ToolExecutor = class _ToolExecutor {
|
|
|
22781
22752
|
return { result, tool, durationMs: Date.now() - start };
|
|
22782
22753
|
}
|
|
22783
22754
|
if (effectivePermission === "confirm") {
|
|
22784
|
-
const suggestedPattern = boundary.decision === "confirm" ? `kanban-boundary:${boundary.path ?? tool.name}` : subjectForToolInput(tool.name, use.input, tool.subjectKey) ?? tool.name;
|
|
22755
|
+
const suggestedPattern = boundary.decision === "confirm" ? `kanban-boundary:${boundary.path ?? tool.name}` : subjectForToolInput(tool.name, use.input, tool.subjectKey, tool.subjectFields) ?? tool.name;
|
|
22785
22756
|
if (this.opts.confirmAwaiter) {
|
|
22786
22757
|
const awaiter = this.opts.confirmAwaiter;
|
|
22787
22758
|
const choice = await new Promise(
|
|
@@ -22908,6 +22879,9 @@ ${post.additionalContext}`;
|
|
|
22908
22879
|
agentName: ctx.agentName,
|
|
22909
22880
|
provider: typeof ctx.provider === "object" ? ctx.provider.id : String(ctx.provider),
|
|
22910
22881
|
model: ctx.model,
|
|
22882
|
+
...ctx.activeLogicalRequestId ? { logicalRequestId: ctx.activeLogicalRequestId } : {},
|
|
22883
|
+
...ctx.activePromptManifestId ? { promptManifestId: ctx.activePromptManifestId } : {},
|
|
22884
|
+
provenanceConfidence: ctx.activeLogicalRequestId && ctx.activePromptManifestId ? "explicit" : "unknown",
|
|
22911
22885
|
toolName: tool.name,
|
|
22912
22886
|
toolUseId: use.id,
|
|
22913
22887
|
scope: ctx.currentKanbanTaskId ? "task" : "session",
|
|
@@ -23050,6 +23024,8 @@ ${preToolContext.text}` : preToolContext.text;
|
|
|
23050
23024
|
this.opts.events?.emit("tool.started", {
|
|
23051
23025
|
sessionId: resolveEventSessionId(ctx),
|
|
23052
23026
|
...ctx.traceId ? { traceId: ctx.traceId } : {},
|
|
23027
|
+
...ctx.activeLogicalRequestId ? { logicalRequestId: ctx.activeLogicalRequestId } : {},
|
|
23028
|
+
...ctx.activePromptManifestId ? { promptManifestId: ctx.activePromptManifestId } : {},
|
|
23053
23029
|
agentId: ctx.agentId,
|
|
23054
23030
|
agentName: ctx.agentName,
|
|
23055
23031
|
name: tool.name,
|