@wrongstack/core 0.310.1 → 0.313.1
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 +84 -6391
- package/dist/chronicle/project-server.js +84 -4868
- package/dist/chunk-2BUUIMQB.js +225 -0
- package/dist/chunk-2FK4WTFF.js +207 -0
- package/dist/chunk-2FQL4PDC.js +292 -0
- package/dist/chunk-2KKODIQU.js +2256 -0
- package/dist/chunk-2YU4WVBW.js +134 -0
- package/dist/chunk-3E244UDA.js +356 -0
- package/dist/chunk-3XPVB7BA.js +135 -0
- package/dist/chunk-4LJJYBAU.js +388 -0
- package/dist/chunk-4VWO3ZXL.js +342 -0
- package/dist/chunk-4XV6IR37.js +187 -0
- package/dist/chunk-4ZHTKJHM.js +183 -0
- package/dist/chunk-52RTVH4M.js +361 -0
- package/dist/chunk-57GEWK5X.js +26 -0
- package/dist/chunk-5DSMEVA4.js +931 -0
- package/dist/chunk-5RP3QTRL.js +1223 -0
- package/dist/chunk-5S437PRC.js +50 -0
- package/dist/chunk-5XDUGTKN.js +511 -0
- package/dist/chunk-62V2AFVG.js +422 -0
- package/dist/chunk-65RDIOR2.js +2470 -0
- package/dist/chunk-6AKOTGLM.js +597 -0
- package/dist/chunk-7ZHZE5EO.js +28 -0
- package/dist/chunk-A455ATZB.js +140 -0
- package/dist/chunk-AD7ZFZCS.js +46 -0
- package/dist/chunk-AI4LLQ2U.js +856 -0
- package/dist/chunk-ASX6AW36.js +789 -0
- package/dist/chunk-AT4V4XGI.js +3522 -0
- package/dist/chunk-AWNQ6ED6.js +311 -0
- package/dist/chunk-B4AMLZPB.js +9 -0
- package/dist/chunk-BAKVJLEV.js +417 -0
- package/dist/chunk-BJHVULHO.js +55 -0
- package/dist/chunk-CB2HFKTP.js +9 -0
- package/dist/chunk-CE4ZOCOI.js +1640 -0
- package/dist/chunk-CQQL4ZOQ.js +151 -0
- package/dist/chunk-DEIQMBD2.js +65 -0
- package/dist/chunk-E6I5RXVK.js +58 -0
- package/dist/chunk-EFEHDQGY.js +1589 -0
- package/dist/chunk-EODDVJBM.js +82 -0
- package/dist/chunk-EPC3GZD4.js +308 -0
- package/dist/chunk-FAYRX2AD.js +13 -0
- package/dist/chunk-FFSX2QDQ.js +362 -0
- package/dist/chunk-FHAMQS7Q.js +5856 -0
- package/dist/chunk-FIV4IJL7.js +2263 -0
- package/dist/chunk-FNXVT7HF.js +52 -0
- package/dist/chunk-FSWCWSTS.js +395 -0
- package/dist/chunk-FW5LDDMJ.js +16464 -0
- package/dist/chunk-FXQLIX3K.js +211 -0
- package/dist/chunk-G5AAKEEZ.js +228 -0
- package/dist/chunk-G5S3S5ZN.js +38 -0
- package/dist/chunk-GAZEWQEZ.js +231 -0
- package/dist/chunk-GFJOMSHG.js +125 -0
- package/dist/chunk-GFXZTHNI.js +158 -0
- package/dist/chunk-GM54GJBU.js +960 -0
- package/dist/chunk-GPQ3NJPR.js +900 -0
- package/dist/chunk-GTCU6DZ3.js +1 -0
- package/dist/chunk-H5E77KUJ.js +15 -0
- package/dist/chunk-H72H4XDU.js +1023 -0
- package/dist/chunk-HA4ZYA6T.js +178 -0
- package/dist/chunk-I45KAW2N.js +5020 -0
- package/dist/chunk-IQ35HMQL.js +1396 -0
- package/dist/chunk-IYFBFX34.js +86 -0
- package/dist/chunk-JJPMWPB6.js +109 -0
- package/dist/chunk-JTHKOYWU.js +663 -0
- package/dist/chunk-JVGPR3TS.js +365 -0
- package/dist/chunk-JVKB2TBL.js +48 -0
- package/dist/chunk-JX7VBZDK.js +31 -0
- package/dist/chunk-K3G6JBUC.js +5232 -0
- package/dist/chunk-K4YUNKU7.js +589 -0
- package/dist/chunk-KBZGE6LN.js +710 -0
- package/dist/chunk-KDQJCT2J.js +45 -0
- package/dist/chunk-KI4L2DUL.js +560 -0
- package/dist/chunk-KJ2ZTQSL.js +47 -0
- package/dist/chunk-KSJ5UTP7.js +154 -0
- package/dist/chunk-LHOA5DWA.js +28 -0
- package/dist/chunk-LX5QWLBL.js +27 -0
- package/dist/chunk-LZDDLNCZ.js +279 -0
- package/dist/chunk-M2WF6AXG.js +115 -0
- package/dist/chunk-M7BS2K6U.js +1 -0
- package/dist/chunk-NDBIPFNY.js +102 -0
- package/dist/chunk-NEMIWEXC.js +1199 -0
- package/dist/chunk-NFAYHPRH.js +323 -0
- package/dist/chunk-O37BQ65S.js +21 -0
- package/dist/chunk-O74MJHXU.js +187 -0
- package/dist/chunk-OJZEX73F.js +112 -0
- package/dist/chunk-PAAWLLZX.js +74 -0
- package/dist/chunk-PFXFQQRT.js +339 -0
- package/dist/chunk-PFZO3C6H.js +14 -0
- package/dist/chunk-PHH7LD45.js +113 -0
- package/dist/chunk-QRTG4XTI.js +188 -0
- package/dist/chunk-QVOVMXJR.js +1351 -0
- package/dist/chunk-RCQYT2I4.js +757 -0
- package/dist/chunk-RD6DEE36.js +1178 -0
- package/dist/chunk-RJIZEJ42.js +30 -0
- package/dist/chunk-RPOA7IAE.js +150 -0
- package/dist/chunk-SN2DQRL6.js +1172 -0
- package/dist/chunk-SQJVFEBV.js +41 -0
- package/dist/chunk-SQP64RCS.js +5391 -0
- package/dist/chunk-SVT4RNTR.js +49 -0
- package/dist/chunk-SWUFN7XM.js +43 -0
- package/dist/chunk-SXMVYC5H.js +174 -0
- package/dist/chunk-SZ6AYUIZ.js +23 -0
- package/dist/chunk-T3KGZBU5.js +3171 -0
- package/dist/chunk-TBRL2RCC.js +9 -0
- package/dist/chunk-TRT2HRWZ.js +18 -0
- package/dist/chunk-TYW2GI5I.js +1077 -0
- package/dist/chunk-UIWONWVG.js +4959 -0
- package/dist/chunk-VB3H5WWB.js +151 -0
- package/dist/chunk-W4A6QA3D.js +258 -0
- package/dist/chunk-WBPVKEEE.js +227 -0
- package/dist/chunk-WEBMSQP2.js +123 -0
- package/dist/chunk-WOEZV3Q4.js +333 -0
- package/dist/chunk-WQQON3SV.js +473 -0
- package/dist/chunk-WQTOVMGV.js +119 -0
- package/dist/chunk-WZO23AWO.js +2779 -0
- package/dist/chunk-XBDP4QPW.js +7 -0
- package/dist/chunk-XEBHSJLT.js +103 -0
- package/dist/chunk-XQ2ECNK3.js +1 -0
- package/dist/chunk-XQ2XGIBF.js +2086 -0
- package/dist/chunk-Y2GE5TSI.js +355 -0
- package/dist/chunk-YBUJCZ57.js +351 -0
- package/dist/chunk-YNCVSFGF.js +149 -0
- package/dist/chunk-YUPMXOGP.js +282 -0
- package/dist/chunk-YY6APYUM.js +49 -0
- package/dist/chunk-Z2IJUO45.js +691 -0
- package/dist/chunk-ZEHUCJHY.js +129 -0
- package/dist/chunk-ZYU2YOJ6.js +1496 -0
- package/dist/chunk-ZZ4V3WIZ.js +163 -0
- package/dist/coordination/agents/index.js +145 -6260
- package/dist/coordination/index.js +365 -34323
- package/dist/coordination/mailbox-project-server.js +48 -3220
- package/dist/coordination/mailbox-types.d.ts +13 -1
- package/dist/coordination/provider-status-tracker.d.ts +4 -0
- package/dist/coordination/sqlite-mailbox.d.ts +2 -1
- package/dist/core/agent.d.ts +14 -1
- package/dist/core/index.js +267 -12479
- package/dist/core/model-ref.js +5 -23
- package/dist/core/provider-runner.d.ts +36 -1
- package/dist/design/index.js +50 -1087
- package/dist/execution/index.d.ts +1 -1
- package/dist/execution/index.js +1599 -21887
- package/dist/execution/prompt-enhancer.js +16 -535
- package/dist/execution/retry-policy.d.ts +31 -1
- package/dist/extension/index.js +7 -311
- package/dist/goal/index.js +33 -3435
- package/dist/hooks/index.js +14 -1138
- package/dist/hq/index.js +112 -5139
- package/dist/hq/protocol.js +21 -668
- package/dist/index.js +1410 -92655
- package/dist/infrastructure/index.js +64 -4811
- package/dist/kernel/events/provider-events.d.ts +15 -0
- package/dist/kernel/events/wrongtrace-events.d.ts +26 -0
- package/dist/kernel/events.d.ts +16 -7
- package/dist/kernel/index.js +14 -992
- package/dist/models/index.js +40 -1117
- package/dist/notifications/index.js +3 -108
- package/dist/observability/index.js +17 -279
- package/dist/plugin/index.js +584 -14835
- package/dist/prompts/index.js +14 -948
- package/dist/registry/index.js +9 -822
- package/dist/registry-R23UBE7H.js +14 -0
- package/dist/replay/index.js +6 -84
- package/dist/review-finding-store-DKAV3AS6.js +21 -0
- package/dist/review-report-store-OWY3EC3N.js +19 -0
- package/dist/security/index.js +114 -2202
- package/dist/session-catalog/index.js +36 -2103
- package/dist/session-catalog/project-server.js +42 -1435
- package/dist/skills/index.js +35 -1578
- package/dist/storage/index.js +182 -15600
- package/dist/tasking/index.js +10 -676
- package/dist/tools/index.js +52 -9589
- package/dist/types/config/autonomy.d.ts +5 -0
- package/dist/types/config/tools.d.ts +2 -2
- package/dist/types/config/ui.d.ts +1 -1
- package/dist/types/errors.d.ts +18 -0
- package/dist/types/index.js +121 -1341
- package/dist/types/provider-runner.d.ts +8 -0
- package/dist/types/session-markers.js +8 -144
- package/dist/utils/error.js +3 -4
- package/dist/utils/expect-defined.js +3 -9
- package/dist/utils/heap-watchdog.js +6 -706
- package/dist/utils/index.js +269 -5685
- package/dist/utils/sage-output-block.js +5 -42
- package/dist/wiring/proxy-rewrite.d.ts +92 -4
- package/dist/wiring/proxy-rewrite.js +20 -61
- package/dist/worktree/index.js +6 -887
- package/package.json +4 -4
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// src/utils/merge-models-payload.ts
|
|
2
|
+
var REMOVE_PROVIDERS_KEY = "_removeProviders";
|
|
3
|
+
var REMOVE_MODELS_KEY = "_removeModels";
|
|
4
|
+
function mergeModelsPayload(base, overlay) {
|
|
5
|
+
const removeProviders = Array.isArray(overlay[REMOVE_PROVIDERS_KEY]) ? overlay[REMOVE_PROVIDERS_KEY] : [];
|
|
6
|
+
const removeModels = overlay[REMOVE_MODELS_KEY] && typeof overlay[REMOVE_MODELS_KEY] === "object" ? overlay[REMOVE_MODELS_KEY] : {};
|
|
7
|
+
const out = {};
|
|
8
|
+
for (const [id, provider] of Object.entries(base)) {
|
|
9
|
+
out[id] = cloneProvider(provider);
|
|
10
|
+
}
|
|
11
|
+
for (const [id, ovProvider] of Object.entries(overlay)) {
|
|
12
|
+
if (id === REMOVE_PROVIDERS_KEY || id === REMOVE_MODELS_KEY) continue;
|
|
13
|
+
const existing = out[id];
|
|
14
|
+
out[id] = existing ? mergeProvider(existing, ovProvider) : cloneProvider(ovProvider);
|
|
15
|
+
}
|
|
16
|
+
for (const providerId of removeProviders) {
|
|
17
|
+
delete out[providerId];
|
|
18
|
+
}
|
|
19
|
+
for (const [providerId, modelIds] of Object.entries(removeModels)) {
|
|
20
|
+
const provider = out[providerId];
|
|
21
|
+
if (!provider?.models) continue;
|
|
22
|
+
for (const modelId of modelIds) {
|
|
23
|
+
delete provider.models[modelId];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
function mergeProvider(base, overlay) {
|
|
29
|
+
const models = {};
|
|
30
|
+
for (const [mid, m] of Object.entries(base.models ?? {})) {
|
|
31
|
+
models[mid] = { ...m };
|
|
32
|
+
}
|
|
33
|
+
for (const [mid, ovModel] of Object.entries(overlay.models ?? {})) {
|
|
34
|
+
const existing = models[mid];
|
|
35
|
+
models[mid] = existing ? mergeModel(existing, ovModel) : { ...ovModel };
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
...base,
|
|
39
|
+
// Overlay scalar fields win when explicitly provided; otherwise keep base.
|
|
40
|
+
...stripUndefined({
|
|
41
|
+
id: overlay.id,
|
|
42
|
+
name: overlay.name,
|
|
43
|
+
npm: overlay.npm,
|
|
44
|
+
api: overlay.api,
|
|
45
|
+
env: overlay.env,
|
|
46
|
+
doc: overlay.doc
|
|
47
|
+
}),
|
|
48
|
+
models
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function mergeModel(base, overlay) {
|
|
52
|
+
const merged = { ...base, ...overlay };
|
|
53
|
+
if (base.limit || overlay.limit) {
|
|
54
|
+
merged.limit = { ...base.limit, ...overlay.limit };
|
|
55
|
+
}
|
|
56
|
+
if (base.cost || overlay.cost) {
|
|
57
|
+
merged.cost = { ...base.cost, ...overlay.cost };
|
|
58
|
+
}
|
|
59
|
+
if (base.modalities || overlay.modalities) {
|
|
60
|
+
merged.modalities = { ...base.modalities, ...overlay.modalities };
|
|
61
|
+
}
|
|
62
|
+
return merged;
|
|
63
|
+
}
|
|
64
|
+
function cloneProvider(p) {
|
|
65
|
+
const models = {};
|
|
66
|
+
for (const [mid, m] of Object.entries(p.models ?? {})) {
|
|
67
|
+
models[mid] = { ...m };
|
|
68
|
+
}
|
|
69
|
+
return { ...p, models };
|
|
70
|
+
}
|
|
71
|
+
function stripUndefined(obj) {
|
|
72
|
+
const out = {};
|
|
73
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
74
|
+
if (v !== void 0) out[k] = v;
|
|
75
|
+
}
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export {
|
|
80
|
+
mergeModelsPayload
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=chunk-EODDVJBM.js.map
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
// src/security/kanban-governance-port.ts
|
|
2
|
+
var notWired = () => {
|
|
3
|
+
throw new Error(
|
|
4
|
+
"KanbanGovernancePort is not wired \u2014 register the implementation at the CLI composition root (see setKanbanGovernance)."
|
|
5
|
+
);
|
|
6
|
+
};
|
|
7
|
+
var port = void 0;
|
|
8
|
+
function setKanbanGovernance(impl) {
|
|
9
|
+
port = impl;
|
|
10
|
+
}
|
|
11
|
+
function kanbanGovernance() {
|
|
12
|
+
return port ?? notWired();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// src/security/kanban-boundary.ts
|
|
16
|
+
import { realpath } from "node:fs/promises";
|
|
17
|
+
import * as path from "node:path";
|
|
18
|
+
var GOVERNANCE_CONTROL_TOOLS = /* @__PURE__ */ new Set(["kanban", "plan", "task", "todo", "nextsteps"]);
|
|
19
|
+
var PATH_KEYS = /* @__PURE__ */ new Set([
|
|
20
|
+
"path",
|
|
21
|
+
"paths",
|
|
22
|
+
"file",
|
|
23
|
+
"files",
|
|
24
|
+
"directory",
|
|
25
|
+
"dir",
|
|
26
|
+
"cwd",
|
|
27
|
+
"root",
|
|
28
|
+
"baseDir",
|
|
29
|
+
"out",
|
|
30
|
+
"outputPath",
|
|
31
|
+
"sourcePath",
|
|
32
|
+
"targetPath",
|
|
33
|
+
"destinationPath",
|
|
34
|
+
"fromPath",
|
|
35
|
+
"toPath",
|
|
36
|
+
"worktreePath"
|
|
37
|
+
]);
|
|
38
|
+
var TOOL_PATH_KEYS = {
|
|
39
|
+
// `target` is an identifier in tools such as plan/task/document, but a
|
|
40
|
+
// filesystem target in language_info. Keep ambiguous names tool-specific.
|
|
41
|
+
language_info: ["target"]
|
|
42
|
+
};
|
|
43
|
+
async function evaluateToolKanbanBoundary(tool, input, ctx, options = {}) {
|
|
44
|
+
if (tool.name === "kanban") return { decision: "allow" };
|
|
45
|
+
const identity = resolveKanbanIdentity(ctx);
|
|
46
|
+
const governanceRequired = options.requireGovernance && isGovernedMutation(tool, input);
|
|
47
|
+
if (!identity.boardId) {
|
|
48
|
+
return governanceRequired ? {
|
|
49
|
+
decision: "block",
|
|
50
|
+
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."
|
|
51
|
+
} : { decision: "allow" };
|
|
52
|
+
}
|
|
53
|
+
const board = await kanbanGovernance().readBoard(
|
|
54
|
+
identity.policyRoot ?? ctx.projectRoot,
|
|
55
|
+
identity.boardId
|
|
56
|
+
);
|
|
57
|
+
if (!board) {
|
|
58
|
+
return governanceRequired ? {
|
|
59
|
+
decision: "block",
|
|
60
|
+
reason: `Active Kanban board not found: ${identity.boardId}. Recreate or select a valid managed card before mutation.`,
|
|
61
|
+
boardId: identity.boardId,
|
|
62
|
+
...identity.taskId ? { taskId: identity.taskId } : {}
|
|
63
|
+
} : { decision: "allow" };
|
|
64
|
+
}
|
|
65
|
+
const task = identity.taskId ? board.tasks.find((candidate) => candidate.id === identity.taskId) : void 0;
|
|
66
|
+
if (governanceRequired && board.lifecycle?.mode === "managed") {
|
|
67
|
+
if (!identity.taskId) {
|
|
68
|
+
return {
|
|
69
|
+
decision: "block",
|
|
70
|
+
reason: "Kanban governance requires an active task, not only a board. Complete the card details and call kanban start_task before mutation.",
|
|
71
|
+
boardId: board.id
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (!task) {
|
|
75
|
+
return {
|
|
76
|
+
decision: "block",
|
|
77
|
+
reason: `Active Kanban task not found: ${identity.taskId}. Call kanban start_task with a valid card.`,
|
|
78
|
+
boardId: board.id,
|
|
79
|
+
taskId: identity.taskId
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const readiness = kanbanGovernance().evaluateContractGraphReadiness(board, task.id);
|
|
83
|
+
if (!readiness.ready) {
|
|
84
|
+
const issueLines = readiness.issues.map((issue, index) => ` ${index + 1}. ${issue.message}`).join("\n");
|
|
85
|
+
return {
|
|
86
|
+
decision: "block",
|
|
87
|
+
reason: `Active card failed contract-readiness check (${readiness.issues.length} issue(s)):
|
|
88
|
+
` + issueLines + `
|
|
89
|
+
Resolve the readiness issues, then call kanban start_task to retry.`,
|
|
90
|
+
boardId: board.id,
|
|
91
|
+
taskId: task.id,
|
|
92
|
+
readinessIssues: readiness.issues
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const lifecycleStage = task.lifecycle?.currentStage;
|
|
96
|
+
const assignmentStatus = task.assignment?.status;
|
|
97
|
+
const lifecycleOk = lifecycleStage === "running";
|
|
98
|
+
const assignmentOk = assignmentStatus === "running";
|
|
99
|
+
if (!lifecycleOk || !assignmentOk) {
|
|
100
|
+
const failed = [];
|
|
101
|
+
let reassessmentNote = "";
|
|
102
|
+
if (!lifecycleOk) {
|
|
103
|
+
failed.push(`lifecycle.currentStage (got: ${lifecycleStage ?? "missing"}; want: 'running')`);
|
|
104
|
+
}
|
|
105
|
+
if (!assignmentOk) {
|
|
106
|
+
failed.push(`assignment.status (got: ${assignmentStatus ?? "missing"}; want: 'running')`);
|
|
107
|
+
if (lifecycleOk && (assignmentStatus === "queued" || assignmentStatus === void 0 || assignmentStatus === null)) {
|
|
108
|
+
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.';
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
decision: "block",
|
|
113
|
+
reason: `Active card failed ${failed.length} governance check(s) before product mutation:
|
|
114
|
+
` + failed.map((line, index) => ` ${index + 1}. ${line}`).join("\n") + reassessmentNote,
|
|
115
|
+
boardId: board.id,
|
|
116
|
+
taskId: task.id
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (identity.leaseId && task?.assignment) {
|
|
121
|
+
const caps2 = tool.capabilities ?? [];
|
|
122
|
+
const isWrite = caps2.includes("fs.write") || caps2.includes("fs.write.outside-project") || caps2.some((c) => c.startsWith("shell."));
|
|
123
|
+
if (isWrite && tool.name !== "kanban" && task.assignment.leaseId !== identity.leaseId) {
|
|
124
|
+
return {
|
|
125
|
+
decision: "block",
|
|
126
|
+
reason: `Task ${task.id} lease mismatch: the current worker's lease (${identity.leaseId}) does not match the active lease on the board (${task.assignment.leaseId}). This task was likely recovered and reassigned to another worker. File modifications from a stale worker are blocked. Use kanban mark_assignment with expectedLeaseId to resolve, or use kanban get_board to reassess the current state.`,
|
|
127
|
+
boardId: board.id,
|
|
128
|
+
taskId: task.id
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const layers = kanbanGovernance().resolveKanbanBoundaryLayers(board, task);
|
|
133
|
+
if (layers.length === 0) return { decision: "allow" };
|
|
134
|
+
const caps = tool.capabilities ?? [];
|
|
135
|
+
const access = caps.includes("fs.write") || caps.includes("fs.write.outside-project") ? "write" : caps.includes("fs.read") ? "read" : void 0;
|
|
136
|
+
const shellLike = caps.some((capability) => capability.startsWith("shell."));
|
|
137
|
+
const candidates = access ? await extractCandidatePaths(tool.name, input, ctx) : [];
|
|
138
|
+
let evaluation;
|
|
139
|
+
if (shellLike || access && candidates.length === 0) {
|
|
140
|
+
evaluation = kanbanGovernance().evaluateKanbanBoundaryOpaque(layers, tool.name);
|
|
141
|
+
} else if (access) {
|
|
142
|
+
const results = candidates.map(
|
|
143
|
+
(candidate) => kanbanGovernance().evaluateKanbanBoundaryPath(layers, candidate, access)
|
|
144
|
+
);
|
|
145
|
+
evaluation = results.find((result) => result.decision === "block") ?? results.find((result) => result.decision === "confirm") ?? { decision: "allow" };
|
|
146
|
+
} else {
|
|
147
|
+
evaluation = { decision: "allow" };
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
...evaluation,
|
|
151
|
+
boardId: board.id,
|
|
152
|
+
...task ? { taskId: task.id } : {}
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
function isGovernedMutation(tool, input) {
|
|
156
|
+
if (!tool.mutating || GOVERNANCE_CONTROL_TOOLS.has(tool.name)) return false;
|
|
157
|
+
if (tool.capabilities?.includes("tool.meta")) return false;
|
|
158
|
+
if (tool.name === "git") {
|
|
159
|
+
const command = input["command"];
|
|
160
|
+
if (command === "status" || command === "log" || command === "diff") return false;
|
|
161
|
+
if (command === "worktree" && input["worktreeAction"] === "list") return false;
|
|
162
|
+
}
|
|
163
|
+
const capabilities = tool.capabilities ?? [];
|
|
164
|
+
return capabilities.some(
|
|
165
|
+
(capability) => capability === "fs.write" || capability === "fs.write.outside-project" || capability === "package.install" || capability === "tool.mutate.any" || capability.startsWith("shell.") || capability === "net.outbound"
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
function resolveKanbanIdentity(ctx) {
|
|
169
|
+
const metaKanban = ctx.meta["kanban"];
|
|
170
|
+
const record = metaKanban && typeof metaKanban === "object" ? metaKanban : void 0;
|
|
171
|
+
const boardId = ctx.currentKanbanBoardId ?? (typeof record?.["boardId"] === "string" ? record["boardId"] : void 0);
|
|
172
|
+
const taskId = ctx.currentKanbanTaskId ?? (typeof record?.["taskId"] === "string" ? record["taskId"] : void 0);
|
|
173
|
+
const policyRoot = typeof record?.["projectRoot"] === "string" ? record["projectRoot"] : void 0;
|
|
174
|
+
const leaseId = typeof record?.["leaseId"] === "string" ? record["leaseId"] : void 0;
|
|
175
|
+
return {
|
|
176
|
+
...boardId ? { boardId } : {},
|
|
177
|
+
...taskId ? { taskId } : {},
|
|
178
|
+
...policyRoot ? { policyRoot } : {},
|
|
179
|
+
...leaseId ? { leaseId } : {}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
async function extractCandidatePaths(toolName, input, ctx) {
|
|
183
|
+
if (toolName === "patch" && typeof input["patch"] === "string") {
|
|
184
|
+
const directoryInput = stringValue(input["directory"]) ?? ctx.workingDir;
|
|
185
|
+
const directory = path.isAbsolute(directoryInput) ? directoryInput : path.resolve(ctx.workingDir, directoryInput);
|
|
186
|
+
const strip = Math.max(1, numericValue(input["strip"]) ?? 1);
|
|
187
|
+
const targets = extractPatchTargets(input["patch"], strip).map(
|
|
188
|
+
(target) => relativeToProject(path.resolve(directory, target), ctx.projectRoot)
|
|
189
|
+
);
|
|
190
|
+
return Promise.all(targets.map((target) => canonicalizeCandidatePath(target, ctx)));
|
|
191
|
+
}
|
|
192
|
+
const values = [];
|
|
193
|
+
const pathKeys = new Set(PATH_KEYS);
|
|
194
|
+
for (const key of TOOL_PATH_KEYS[toolName] ?? []) pathKeys.add(key);
|
|
195
|
+
collectPathValues(input, values, pathKeys);
|
|
196
|
+
if (toolName === "scaffold" && typeof input["name"] === "string") {
|
|
197
|
+
const cwd = stringValue(input["cwd"]) ?? ctx.workingDir;
|
|
198
|
+
values.push(path.join(cwd, input["name"]));
|
|
199
|
+
}
|
|
200
|
+
const candidates = [
|
|
201
|
+
...new Set(values.flatMap(splitPathList).map((value) => resolveInputPath(value, ctx)))
|
|
202
|
+
];
|
|
203
|
+
return Promise.all(candidates.map((candidate) => canonicalizeCandidatePath(candidate, ctx)));
|
|
204
|
+
}
|
|
205
|
+
async function canonicalizeCandidatePath(candidate, ctx) {
|
|
206
|
+
if (path.isAbsolute(candidate)) return candidate;
|
|
207
|
+
const absolute = path.resolve(ctx.projectRoot, candidate);
|
|
208
|
+
const canonicalRoot = await realpath(ctx.projectRoot).catch(() => ctx.projectRoot);
|
|
209
|
+
let probe = absolute;
|
|
210
|
+
const missingSegments = [];
|
|
211
|
+
while (true) {
|
|
212
|
+
try {
|
|
213
|
+
const canonical = path.join(await realpath(probe), ...missingSegments);
|
|
214
|
+
return relativeToProject(canonical, canonicalRoot);
|
|
215
|
+
} catch (cause) {
|
|
216
|
+
const code = cause.code;
|
|
217
|
+
if (code !== "ENOENT" && code !== "ENOTDIR") return absolute;
|
|
218
|
+
const parent = path.dirname(probe);
|
|
219
|
+
if (parent === probe) return absolute;
|
|
220
|
+
missingSegments.unshift(path.basename(probe));
|
|
221
|
+
probe = parent;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
function collectPathValues(value, output, pathKeys, key) {
|
|
226
|
+
if (typeof value === "string") {
|
|
227
|
+
if (key && pathKeys.has(key)) output.push(value);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
if (Array.isArray(value)) {
|
|
231
|
+
for (const item of value) collectPathValues(item, output, pathKeys, key);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (!value || typeof value !== "object") return;
|
|
235
|
+
for (const [childKey, child] of Object.entries(value)) {
|
|
236
|
+
collectPathValues(child, output, pathKeys, childKey);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function splitPathList(value) {
|
|
240
|
+
return value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
241
|
+
}
|
|
242
|
+
function resolveInputPath(value, ctx) {
|
|
243
|
+
const absolute = path.isAbsolute(value) ? value : path.resolve(ctx.workingDir, value);
|
|
244
|
+
return relativeToProject(absolute, ctx.projectRoot);
|
|
245
|
+
}
|
|
246
|
+
function relativeToProject(absolute, projectRoot) {
|
|
247
|
+
const relative2 = path.relative(projectRoot, absolute).replace(/\\/g, "/");
|
|
248
|
+
return relative2.startsWith("../") || path.isAbsolute(relative2) ? absolute : relative2 || ".";
|
|
249
|
+
}
|
|
250
|
+
function extractPatchTargets(patchText, strip) {
|
|
251
|
+
const targets = [];
|
|
252
|
+
for (const match of patchText.matchAll(/^\+\+\+\s+([^\t\r\n]+)/gm)) {
|
|
253
|
+
const raw = match[1]?.trim();
|
|
254
|
+
if (!raw || raw === "/dev/null") continue;
|
|
255
|
+
const parts = raw.replace(/\\/g, "/").split("/").filter((part) => part && part !== ".");
|
|
256
|
+
if (parts.length > strip) targets.push(parts.slice(strip).join("/"));
|
|
257
|
+
}
|
|
258
|
+
return targets;
|
|
259
|
+
}
|
|
260
|
+
function stringValue(value) {
|
|
261
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
262
|
+
}
|
|
263
|
+
function numericValue(value) {
|
|
264
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// src/utils/lru-cache.ts
|
|
268
|
+
var LruCache = class {
|
|
269
|
+
store = /* @__PURE__ */ new Map();
|
|
270
|
+
capacity;
|
|
271
|
+
constructor(capacity) {
|
|
272
|
+
if (capacity < 1) throw new Error(`LruCache capacity must be >= 1, got ${capacity}`);
|
|
273
|
+
this.capacity = capacity;
|
|
274
|
+
}
|
|
275
|
+
get(key) {
|
|
276
|
+
if (!this.store.has(key)) return void 0;
|
|
277
|
+
const value = this.store.get(key);
|
|
278
|
+
this.store.delete(key);
|
|
279
|
+
this.store.set(key, value);
|
|
280
|
+
return value;
|
|
281
|
+
}
|
|
282
|
+
set(key, value) {
|
|
283
|
+
if (this.store.has(key)) this.store.delete(key);
|
|
284
|
+
this.store.set(key, value);
|
|
285
|
+
while (this.store.size > this.capacity) {
|
|
286
|
+
const oldest = this.store.keys().next();
|
|
287
|
+
if (oldest.done) break;
|
|
288
|
+
this.store.delete(oldest.value);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
has(key) {
|
|
292
|
+
return this.store.has(key);
|
|
293
|
+
}
|
|
294
|
+
clear() {
|
|
295
|
+
this.store.clear();
|
|
296
|
+
}
|
|
297
|
+
get size() {
|
|
298
|
+
return this.store.size;
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
export {
|
|
303
|
+
LruCache,
|
|
304
|
+
setKanbanGovernance,
|
|
305
|
+
kanbanGovernance,
|
|
306
|
+
evaluateToolKanbanBoundary
|
|
307
|
+
};
|
|
308
|
+
//# sourceMappingURL=chunk-EPC3GZD4.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// src/utils/socket-path.ts
|
|
2
|
+
import {
|
|
3
|
+
assertUnixSocketPathWithinLimit,
|
|
4
|
+
checkUnixSocketPath,
|
|
5
|
+
unixSocketPathLimit
|
|
6
|
+
} from "@wrongstack/persistence";
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
assertUnixSocketPathWithinLimit,
|
|
10
|
+
checkUnixSocketPath,
|
|
11
|
+
unixSocketPathLimit
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=chunk-FAYRX2AD.js.map
|