@lumenflow/cli 3.20.0 → 3.22.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/chunk-2D2VOCA4.js +37 -0
- package/dist/chunk-2D5KFYGX.js +284 -0
- package/dist/chunk-2GXVIN57.js +14072 -0
- package/dist/chunk-2MQ7HZWZ.js +26 -0
- package/dist/chunk-2UFQ3A3C.js +643 -0
- package/dist/chunk-3RG5ZIWI.js +10 -0
- package/dist/chunk-4N74J3UT.js +15 -0
- package/dist/chunk-5GTOXFYR.js +392 -0
- package/dist/chunk-5VY6MQMC.js +240 -0
- package/dist/chunk-67XVPMRY.js +1297 -0
- package/dist/chunk-6HO4GWJE.js +164 -0
- package/dist/chunk-6W5XHWYV.js +1890 -0
- package/dist/chunk-6X4EMYJQ.js +64 -0
- package/dist/chunk-6XYXI2NQ.js +772 -0
- package/dist/chunk-7ANSOV6Q.js +285 -0
- package/dist/chunk-A624LFLB.js +1380 -0
- package/dist/chunk-ADN5NHG4.js +126 -0
- package/dist/chunk-B7YJYJKG.js +33 -0
- package/dist/chunk-CCLHCPKG.js +210 -0
- package/dist/chunk-CK36VROC.js +1584 -0
- package/dist/chunk-D3UOFRSB.js +81 -0
- package/dist/chunk-DFR4DJBM.js +230 -0
- package/dist/chunk-DSYBDHYH.js +79 -0
- package/dist/chunk-DWMLTXKQ.js +1176 -0
- package/dist/chunk-E3REJTAJ.js +28 -0
- package/dist/chunk-EA3IVO64.js +633 -0
- package/dist/chunk-EK2AKZKD.js +55 -0
- package/dist/chunk-ELD7JTTT.js +343 -0
- package/dist/chunk-EX6TT2XI.js +195 -0
- package/dist/chunk-EXINSFZE.js +82 -0
- package/dist/chunk-EZ6ZBYBM.js +510 -0
- package/dist/chunk-FBKAPTJ2.js +16 -0
- package/dist/chunk-FVLV5RYH.js +1118 -0
- package/dist/chunk-GDNSBQVK.js +2485 -0
- package/dist/chunk-GPQHMBNN.js +278 -0
- package/dist/chunk-GTFJB67L.js +68 -0
- package/dist/chunk-HANJXVKW.js +1127 -0
- package/dist/chunk-HEVS5YLD.js +269 -0
- package/dist/chunk-HMEVZKPQ.js +9 -0
- package/dist/chunk-HRGSYNLM.js +3511 -0
- package/dist/chunk-ISZR5N4K.js +60 -0
- package/dist/chunk-J6SUPR2C.js +226 -0
- package/dist/chunk-JERYVEIZ.js +244 -0
- package/dist/chunk-JHHWGL2N.js +87 -0
- package/dist/chunk-JONWQUB5.js +775 -0
- package/dist/chunk-K2DIWWDM.js +1766 -0
- package/dist/chunk-KY4PGL5V.js +969 -0
- package/dist/chunk-L737LQ4C.js +1285 -0
- package/dist/chunk-LFTWYIB2.js +497 -0
- package/dist/chunk-LV47RFNJ.js +41 -0
- package/dist/chunk-MKSAITI7.js +15 -0
- package/dist/chunk-MZ7RKIX4.js +212 -0
- package/dist/chunk-NAP6CFSO.js +84 -0
- package/dist/chunk-ND6MY37M.js +16 -0
- package/dist/chunk-NMG736UR.js +683 -0
- package/dist/chunk-NRAXROED.js +32 -0
- package/dist/chunk-NRIZR3A7.js +690 -0
- package/dist/chunk-NX43BG3M.js +233 -0
- package/dist/chunk-O645XLSI.js +297 -0
- package/dist/chunk-OMJD6A3S.js +235 -0
- package/dist/chunk-QB6SJD4T.js +430 -0
- package/dist/chunk-QFSTL4J3.js +276 -0
- package/dist/chunk-QLGDFMFX.js +212 -0
- package/dist/chunk-RIAAGL2E.js +13 -0
- package/dist/chunk-RWO5XMZ6.js +86 -0
- package/dist/chunk-RXRKBBSM.js +149 -0
- package/dist/chunk-RZOZMML6.js +363 -0
- package/dist/chunk-U7I7FS7T.js +113 -0
- package/dist/chunk-UI42RODY.js +717 -0
- package/dist/chunk-UTVMVSCO.js +519 -0
- package/dist/chunk-V6OJGLBA.js +1746 -0
- package/dist/chunk-W2JHVH7D.js +152 -0
- package/dist/chunk-WD3Y7VQN.js +280 -0
- package/dist/chunk-WOCTQ5MS.js +303 -0
- package/dist/chunk-WZR3ZUNN.js +696 -0
- package/dist/chunk-XGI665H7.js +150 -0
- package/dist/chunk-XKY65P2T.js +304 -0
- package/dist/chunk-Y4CQZY65.js +57 -0
- package/dist/chunk-YFEXKLVE.js +194 -0
- package/dist/chunk-YHO3HS5X.js +287 -0
- package/dist/chunk-YLS7AZSX.js +738 -0
- package/dist/chunk-ZE473AO6.js +49 -0
- package/dist/chunk-ZF747T3O.js +644 -0
- package/dist/chunk-ZHCZHZH3.js +43 -0
- package/dist/chunk-ZZNZX2XY.js +87 -0
- package/dist/constants-7QAP3VQ4.js +23 -0
- package/dist/dist-IY3UUMWK.js +33 -0
- package/dist/init-templates.js +30 -22
- package/dist/init-templates.js.map +1 -1
- package/dist/invariants-runner-W5RGHCSU.js +27 -0
- package/dist/lane-lock-6J36HD5O.js +35 -0
- package/dist/mem-checkpoint-core-EANG2GVN.js +14 -0
- package/dist/mem-signal-core-2LZ2WYHW.js +19 -0
- package/dist/memory-store-OLB5FO7K.js +18 -0
- package/dist/service-6BYCOCO5.js +13 -0
- package/dist/spawn-policy-resolver-NTSZYQ6R.js +17 -0
- package/dist/spawn-task-builder-R4E2BHSW.js +22 -0
- package/dist/wu-done-pr-WLFFFEPJ.js +25 -0
- package/dist/wu-done-validation-3J5E36FE.js +30 -0
- package/dist/wu-duplicate-id-detector-5S7JHELK.js +232 -0
- package/dist/wu-spawn-strategy-resolver.js +18 -5
- package/dist/wu-spawn-strategy-resolver.js.map +1 -1
- package/package.json +8 -8
- package/packs/agent-runtime/.turbo/turbo-build.log +1 -1
- package/packs/agent-runtime/.turbo/turbo-typecheck.log +4 -0
- package/packs/agent-runtime/package.json +1 -1
- package/packs/sidekick/.turbo/turbo-build.log +1 -1
- package/packs/sidekick/.turbo/turbo-test.log +12 -0
- package/packs/sidekick/.turbo/turbo-typecheck.log +4 -0
- package/packs/sidekick/package.json +1 -1
- package/packs/software-delivery/.turbo/turbo-build.log +1 -1
- package/packs/software-delivery/.turbo/turbo-typecheck.log +4 -0
- package/packs/software-delivery/package.json +1 -1
- package/templates/core/.lumenflow/constraints.md.template +68 -3
- package/templates/core/LUMENFLOW.md.template +26 -26
- package/templates/core/_frameworks/lumenflow/wu-sizing-guide.md.template +1 -3
- package/templates/core/ai/onboarding/agent-safety-card.md.template +14 -4
- package/templates/core/ai/onboarding/first-wu-mistakes.md.template +96 -0
- package/templates/core/ai/onboarding/quick-ref-commands.md.template +23 -22
- package/templates/core/ai/onboarding/rapid-prototyping.md +2 -1
- package/templates/core/ai/onboarding/starting-prompt.md.template +3 -3
- package/templates/core/ai/onboarding/troubleshooting-wu-done.md.template +69 -1
|
@@ -0,0 +1,1127 @@
|
|
|
1
|
+
// ../kernel/dist/shared-constants.js
|
|
2
|
+
var UTF8_ENCODING = "utf8";
|
|
3
|
+
var BASE64_ENCODING = "base64";
|
|
4
|
+
var SHA256_ALGORITHM = "sha256";
|
|
5
|
+
var SHA256_HEX_LENGTH = 64;
|
|
6
|
+
var SHA256_HEX_REGEX = /^[a-f0-9]{64}$/;
|
|
7
|
+
var SHA256_INTEGRITY_PREFIX = "sha256:";
|
|
8
|
+
var SHA256_INTEGRITY_REGEX = /^sha256:[a-f0-9]{64}$/;
|
|
9
|
+
var WORKSPACE_FILE_NAME = "workspace.yaml";
|
|
10
|
+
var GIT_DIR_NAME = ".git";
|
|
11
|
+
var PACKS_DIR_NAME = "packs";
|
|
12
|
+
var PACK_MANIFEST_FILE_NAME = "manifest.yaml";
|
|
13
|
+
var PACKAGES_DIR_NAME = "packages";
|
|
14
|
+
var LUMENFLOW_SCOPE_NAME = "@lumenflow";
|
|
15
|
+
var LUMENFLOW_DIR_NAME = ".lumenflow";
|
|
16
|
+
var KERNEL_RUNTIME_ROOT_DIR_NAME = "kernel";
|
|
17
|
+
var KERNEL_RUNTIME_TASKS_DIR_NAME = "tasks";
|
|
18
|
+
var KERNEL_RUNTIME_EVENTS_DIR_NAME = "events";
|
|
19
|
+
var KERNEL_RUNTIME_EVIDENCE_DIR_NAME = "evidence";
|
|
20
|
+
var KERNEL_RUNTIME_EVENTS_FILE_NAME = "events.jsonl";
|
|
21
|
+
var KERNEL_RUNTIME_EVENTS_LOCK_FILE_NAME = "events.lock";
|
|
22
|
+
var RESERVED_FRAMEWORK_SCOPE_ROOT = LUMENFLOW_DIR_NAME;
|
|
23
|
+
var RESERVED_FRAMEWORK_SCOPE_PREFIX = `${LUMENFLOW_DIR_NAME}/`;
|
|
24
|
+
var RESERVED_FRAMEWORK_SCOPE_GLOB = `${LUMENFLOW_DIR_NAME}/**`;
|
|
25
|
+
var DEFAULT_WORKSPACE_CONFIG_HASH = "0".repeat(SHA256_HEX_LENGTH);
|
|
26
|
+
var DEFAULT_KERNEL_RUNTIME_VERSION = "kernel-dev";
|
|
27
|
+
var WORKSPACE_CONFIG_HASH_CONTEXT_KEYS = {
|
|
28
|
+
WORKSPACE_FILE_MISSING: "workspace_file_missing"
|
|
29
|
+
};
|
|
30
|
+
var EXECUTION_METADATA_KEYS = {
|
|
31
|
+
WORKSPACE_ALLOWED_SCOPES: "workspace_allowed_scopes",
|
|
32
|
+
LANE_ALLOWED_SCOPES: "lane_allowed_scopes",
|
|
33
|
+
TASK_DECLARED_SCOPES: "task_declared_scopes",
|
|
34
|
+
WORKSPACE_CONFIG_HASH: "workspace_config_hash",
|
|
35
|
+
RUNTIME_VERSION: "runtime_version",
|
|
36
|
+
PACK_ID: "pack_id",
|
|
37
|
+
PACK_VERSION: "pack_version",
|
|
38
|
+
PACK_INTEGRITY: "pack_integrity"
|
|
39
|
+
};
|
|
40
|
+
var KERNEL_POLICY_IDS = {
|
|
41
|
+
ALLOW_ALL: "kernel.policy.allow-all",
|
|
42
|
+
RUNTIME_FALLBACK: "kernel.policy.runtime-fallback",
|
|
43
|
+
BUILTIN_DEFAULT: "kernel.policy.builtin-default",
|
|
44
|
+
PROC_EXEC_DEFAULT_DENY: "kernel.policy.proc-exec-default-deny",
|
|
45
|
+
SCOPE_RESERVED_PATH: "kernel.scope.reserved-path",
|
|
46
|
+
SCOPE_BOUNDARY: "kernel.scope.boundary",
|
|
47
|
+
RECONCILIATION: "kernel.reconciliation",
|
|
48
|
+
APPROVAL_REQUIRED: "kernel.policy.approval-required"
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// ../kernel/dist/kernel.schemas.js
|
|
52
|
+
import { z } from "zod";
|
|
53
|
+
|
|
54
|
+
// ../kernel/dist/event-kinds.js
|
|
55
|
+
var KERNEL_EVENT_KINDS = {
|
|
56
|
+
TASK_CREATED: "task_created",
|
|
57
|
+
TASK_CLAIMED: "task_claimed",
|
|
58
|
+
TASK_BLOCKED: "task_blocked",
|
|
59
|
+
TASK_UNBLOCKED: "task_unblocked",
|
|
60
|
+
TASK_WAITING: "task_waiting",
|
|
61
|
+
TASK_RESUMED: "task_resumed",
|
|
62
|
+
TASK_COMPLETED: "task_completed",
|
|
63
|
+
TASK_RELEASED: "task_released",
|
|
64
|
+
TASK_DELEGATED: "task_delegated",
|
|
65
|
+
RUN_STARTED: "run_started",
|
|
66
|
+
RUN_PAUSED: "run_paused",
|
|
67
|
+
RUN_FAILED: "run_failed",
|
|
68
|
+
RUN_SUCCEEDED: "run_succeeded",
|
|
69
|
+
WORKSPACE_UPDATED: "workspace_updated",
|
|
70
|
+
WORKSPACE_WARNING: "workspace_warning",
|
|
71
|
+
SPEC_TAMPERED: "spec_tampered",
|
|
72
|
+
CHECKPOINT: "checkpoint"
|
|
73
|
+
};
|
|
74
|
+
var TASK_EVENT_KINDS = [
|
|
75
|
+
KERNEL_EVENT_KINDS.TASK_CREATED,
|
|
76
|
+
KERNEL_EVENT_KINDS.TASK_CLAIMED,
|
|
77
|
+
KERNEL_EVENT_KINDS.TASK_BLOCKED,
|
|
78
|
+
KERNEL_EVENT_KINDS.TASK_UNBLOCKED,
|
|
79
|
+
KERNEL_EVENT_KINDS.TASK_WAITING,
|
|
80
|
+
KERNEL_EVENT_KINDS.TASK_RESUMED,
|
|
81
|
+
KERNEL_EVENT_KINDS.TASK_COMPLETED,
|
|
82
|
+
KERNEL_EVENT_KINDS.TASK_RELEASED,
|
|
83
|
+
KERNEL_EVENT_KINDS.TASK_DELEGATED
|
|
84
|
+
];
|
|
85
|
+
var RUN_LIFECYCLE_EVENT_KINDS = [
|
|
86
|
+
KERNEL_EVENT_KINDS.RUN_STARTED,
|
|
87
|
+
KERNEL_EVENT_KINDS.RUN_PAUSED,
|
|
88
|
+
KERNEL_EVENT_KINDS.RUN_FAILED,
|
|
89
|
+
KERNEL_EVENT_KINDS.RUN_SUCCEEDED
|
|
90
|
+
];
|
|
91
|
+
var TASK_EVENT_KIND_SET = new Set(TASK_EVENT_KINDS);
|
|
92
|
+
var RUN_LIFECYCLE_EVENT_KIND_SET = new Set(RUN_LIFECYCLE_EVENT_KINDS);
|
|
93
|
+
function isTaskEventKind(kind) {
|
|
94
|
+
return TASK_EVENT_KIND_SET.has(kind);
|
|
95
|
+
}
|
|
96
|
+
function isRunLifecycleEventKind(kind) {
|
|
97
|
+
return RUN_LIFECYCLE_EVENT_KIND_SET.has(kind);
|
|
98
|
+
}
|
|
99
|
+
var TOOL_TRACE_KINDS = {
|
|
100
|
+
TOOL_CALL_STARTED: "tool_call_started",
|
|
101
|
+
TOOL_CALL_FINISHED: "tool_call_finished"
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// ../kernel/dist/kernel.schemas.js
|
|
105
|
+
var ISO_DATETIME_SCHEMA = z.string().datetime();
|
|
106
|
+
var SEMVER_REGEX = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-.]+)?(?:\+[0-9A-Za-z-.]+)?$/;
|
|
107
|
+
var SEMVER_MESSAGE = "Expected semantic version";
|
|
108
|
+
var RUN_STATUSES = {
|
|
109
|
+
PLANNED: "planned",
|
|
110
|
+
EXECUTING: "executing",
|
|
111
|
+
PAUSED: "paused",
|
|
112
|
+
FAILED: "failed",
|
|
113
|
+
SUCCEEDED: "succeeded"
|
|
114
|
+
};
|
|
115
|
+
var RUN_STATUS_VALUES = [
|
|
116
|
+
RUN_STATUSES.PLANNED,
|
|
117
|
+
RUN_STATUSES.EXECUTING,
|
|
118
|
+
RUN_STATUSES.PAUSED,
|
|
119
|
+
RUN_STATUSES.FAILED,
|
|
120
|
+
RUN_STATUSES.SUCCEEDED
|
|
121
|
+
];
|
|
122
|
+
var TOOL_HANDLER_KINDS = {
|
|
123
|
+
IN_PROCESS: "in-process",
|
|
124
|
+
SUBPROCESS: "subprocess"
|
|
125
|
+
};
|
|
126
|
+
var TOOL_HANDLER_KIND_VALUES = [
|
|
127
|
+
TOOL_HANDLER_KINDS.IN_PROCESS,
|
|
128
|
+
TOOL_HANDLER_KINDS.SUBPROCESS
|
|
129
|
+
];
|
|
130
|
+
var TOOL_ERROR_CODES = {
|
|
131
|
+
TOOL_NOT_FOUND: "TOOL_NOT_FOUND",
|
|
132
|
+
SCOPE_DENIED: "SCOPE_DENIED",
|
|
133
|
+
POLICY_DENIED: "POLICY_DENIED",
|
|
134
|
+
APPROVAL_REQUIRED: "APPROVAL_REQUIRED",
|
|
135
|
+
INVALID_INPUT: "INVALID_INPUT",
|
|
136
|
+
INVALID_OUTPUT: "INVALID_OUTPUT",
|
|
137
|
+
TOOL_EXECUTION_FAILED: "TOOL_EXECUTION_FAILED"
|
|
138
|
+
};
|
|
139
|
+
var ToolScopePathSchema = z.object({
|
|
140
|
+
type: z.literal("path"),
|
|
141
|
+
pattern: z.string().min(1),
|
|
142
|
+
access: z.enum(["read", "write"])
|
|
143
|
+
});
|
|
144
|
+
var ToolScopeNetworkBaseSchema = z.object({
|
|
145
|
+
type: z.literal("network"),
|
|
146
|
+
posture: z.enum(["off", "full", "allowlist"]),
|
|
147
|
+
allowlist_entries: z.array(z.string().min(1)).min(1).optional()
|
|
148
|
+
});
|
|
149
|
+
var ToolScopeNetworkSchema = ToolScopeNetworkBaseSchema.refine((data) => {
|
|
150
|
+
if (data.posture === "allowlist") {
|
|
151
|
+
return data.allowlist_entries !== void 0 && data.allowlist_entries.length > 0;
|
|
152
|
+
}
|
|
153
|
+
return true;
|
|
154
|
+
}, { message: "allowlist_entries required when posture is allowlist" });
|
|
155
|
+
var ToolScopeSchema = z.discriminatedUnion("type", [ToolScopePathSchema, ToolScopeNetworkBaseSchema]).refine((data) => {
|
|
156
|
+
if (data.type === "network" && data.posture === "allowlist") {
|
|
157
|
+
return data.allowlist_entries !== void 0 && data.allowlist_entries.length > 0;
|
|
158
|
+
}
|
|
159
|
+
return true;
|
|
160
|
+
}, { message: "allowlist_entries required when posture is allowlist" });
|
|
161
|
+
var AcceptanceSchema = z.union([
|
|
162
|
+
z.array(z.string().min(1)).min(1),
|
|
163
|
+
z.record(z.string().min(1), z.array(z.string().min(1)).min(1))
|
|
164
|
+
]);
|
|
165
|
+
var TaskSpecSchema = z.object({
|
|
166
|
+
id: z.string().min(1),
|
|
167
|
+
workspace_id: z.string().min(1),
|
|
168
|
+
lane_id: z.string().min(1),
|
|
169
|
+
domain: z.string().min(1),
|
|
170
|
+
title: z.string().min(1),
|
|
171
|
+
description: z.string().min(1),
|
|
172
|
+
acceptance: AcceptanceSchema,
|
|
173
|
+
declared_scopes: z.array(ToolScopeSchema),
|
|
174
|
+
expected_artifacts: z.array(z.string().min(1)).optional(),
|
|
175
|
+
risk: z.enum(["low", "medium", "high", "critical"]),
|
|
176
|
+
blocks: z.array(z.string().min(1)).optional(),
|
|
177
|
+
blocked_by: z.array(z.string().min(1)).optional(),
|
|
178
|
+
extensions: z.record(z.string(), z.unknown()).optional(),
|
|
179
|
+
type: z.string().min(1),
|
|
180
|
+
priority: z.enum(["P0", "P1", "P2", "P3"]),
|
|
181
|
+
created: z.string().date(),
|
|
182
|
+
labels: z.array(z.string().min(1)).optional()
|
|
183
|
+
});
|
|
184
|
+
var RunSchema = z.object({
|
|
185
|
+
run_id: z.string().min(1),
|
|
186
|
+
task_id: z.string().min(1),
|
|
187
|
+
status: z.enum(RUN_STATUS_VALUES),
|
|
188
|
+
started_at: ISO_DATETIME_SCHEMA,
|
|
189
|
+
completed_at: ISO_DATETIME_SCHEMA.optional(),
|
|
190
|
+
by: z.string().min(1),
|
|
191
|
+
session_id: z.string().min(1)
|
|
192
|
+
});
|
|
193
|
+
var TaskStateSchema = z.object({
|
|
194
|
+
task_id: z.string().min(1),
|
|
195
|
+
status: z.enum(["ready", "active", "blocked", "waiting", "done"]),
|
|
196
|
+
claimed_at: ISO_DATETIME_SCHEMA.optional(),
|
|
197
|
+
claimed_by: z.string().min(1).optional(),
|
|
198
|
+
session_id: z.string().min(1).optional(),
|
|
199
|
+
blocked_reason: z.string().min(1).optional(),
|
|
200
|
+
completed_at: ISO_DATETIME_SCHEMA.optional(),
|
|
201
|
+
current_run: RunSchema.optional(),
|
|
202
|
+
run_count: z.number().int().nonnegative(),
|
|
203
|
+
domain_state: z.record(z.string(), z.unknown()).optional()
|
|
204
|
+
});
|
|
205
|
+
var PackPinSchema = z.object({
|
|
206
|
+
id: z.string().min(1),
|
|
207
|
+
version: z.string().regex(SEMVER_REGEX, SEMVER_MESSAGE),
|
|
208
|
+
integrity: z.union([
|
|
209
|
+
z.literal("dev"),
|
|
210
|
+
z.string().regex(SHA256_INTEGRITY_REGEX, "Expected dev or sha256:<64-hex>")
|
|
211
|
+
]),
|
|
212
|
+
source: z.enum(["local", "git", "registry"]),
|
|
213
|
+
url: z.string().url().optional(),
|
|
214
|
+
/** Registry base URL override. When omitted, uses PackLoader's defaultRegistryUrl. */
|
|
215
|
+
registry_url: z.string().url().optional()
|
|
216
|
+
});
|
|
217
|
+
var LaneSpecSchema = z.object({
|
|
218
|
+
id: z.string().min(1),
|
|
219
|
+
title: z.string().min(1),
|
|
220
|
+
allowed_scopes: z.array(ToolScopeSchema).default([]),
|
|
221
|
+
wip_limit: z.number().int().positive().optional(),
|
|
222
|
+
policy_overrides: z.record(z.string(), z.unknown()).optional()
|
|
223
|
+
});
|
|
224
|
+
var WorkspaceControlPlanePolicyModeSchema = z.enum([
|
|
225
|
+
"authoritative",
|
|
226
|
+
"tighten-only",
|
|
227
|
+
"dev-override"
|
|
228
|
+
]);
|
|
229
|
+
var CONTROL_PLANE_AUTH_TOKEN_ENV_PATTERN = /^[A-Z][A-Z0-9_]*$/;
|
|
230
|
+
var WorkspaceControlPlaneAuthConfigSchema = z.object({
|
|
231
|
+
token_env: z.string().regex(CONTROL_PLANE_AUTH_TOKEN_ENV_PATTERN, "Expected uppercase environment variable name")
|
|
232
|
+
}).strict();
|
|
233
|
+
var WorkspaceControlPlaneConfigSchema = z.object({
|
|
234
|
+
endpoint: z.string().url(),
|
|
235
|
+
org_id: z.string().min(1),
|
|
236
|
+
project_id: z.string().min(1),
|
|
237
|
+
sync_interval: z.number().int().positive(),
|
|
238
|
+
policy_mode: WorkspaceControlPlanePolicyModeSchema,
|
|
239
|
+
auth: WorkspaceControlPlaneAuthConfigSchema
|
|
240
|
+
}).strict();
|
|
241
|
+
var WorkspaceSpecSchema = z.object({
|
|
242
|
+
id: z.string().min(1),
|
|
243
|
+
name: z.string().min(1),
|
|
244
|
+
packs: z.array(PackPinSchema),
|
|
245
|
+
lanes: z.array(LaneSpecSchema),
|
|
246
|
+
policies: z.record(z.string(), z.unknown()).optional(),
|
|
247
|
+
security: z.object({
|
|
248
|
+
allowed_scopes: z.array(ToolScopeSchema),
|
|
249
|
+
network_default: z.enum(["off", "full"]),
|
|
250
|
+
deny_overlays: z.array(z.string().min(1))
|
|
251
|
+
}),
|
|
252
|
+
software_delivery: z.record(z.string(), z.unknown()).optional(),
|
|
253
|
+
control_plane: WorkspaceControlPlaneConfigSchema.optional(),
|
|
254
|
+
memory_namespace: z.string().min(1),
|
|
255
|
+
event_namespace: z.string().min(1)
|
|
256
|
+
});
|
|
257
|
+
var KERNEL_OWNED_ROOT_KEYS = [
|
|
258
|
+
"id",
|
|
259
|
+
"name",
|
|
260
|
+
"packs",
|
|
261
|
+
"lanes",
|
|
262
|
+
"policies",
|
|
263
|
+
"security",
|
|
264
|
+
"control_plane",
|
|
265
|
+
"memory_namespace",
|
|
266
|
+
"event_namespace"
|
|
267
|
+
];
|
|
268
|
+
var KNOWN_PACK_CONFIG_KEY_MIGRATIONS = {
|
|
269
|
+
software_delivery: {
|
|
270
|
+
packId: "software-delivery",
|
|
271
|
+
packLabel: "software-delivery"
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
function validateWorkspaceRootKeys(workspaceData, packManifests, availableManifests = []) {
|
|
275
|
+
const kernelKeys = new Set(KERNEL_OWNED_ROOT_KEYS);
|
|
276
|
+
const packConfigKeys = /* @__PURE__ */ new Set();
|
|
277
|
+
for (const manifest of packManifests) {
|
|
278
|
+
if (manifest.config_key) {
|
|
279
|
+
packConfigKeys.add(manifest.config_key);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
const errors = [];
|
|
283
|
+
for (const key of Object.keys(workspaceData)) {
|
|
284
|
+
if (kernelKeys.has(key)) {
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
if (packConfigKeys.has(key)) {
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
const migration = KNOWN_PACK_CONFIG_KEY_MIGRATIONS[key];
|
|
291
|
+
if (migration) {
|
|
292
|
+
const availableManifest = availableManifests.find((m) => m.id === migration.packId) ?? packManifests.find((m) => m.id === migration.packId);
|
|
293
|
+
const versionFlag = availableManifest ? `--version ${availableManifest.version}` : "--version latest";
|
|
294
|
+
errors.push(`Your workspace has a "${key}" config block but the ${migration.packLabel} pack is not pinned. Since LumenFlow 3.x, pack config keys require explicit pack pinning. Add the ${migration.packLabel} pack to your workspace:
|
|
295
|
+
|
|
296
|
+
pnpm pack:install --id ${migration.packId} --source registry ${versionFlag}`);
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
errors.push(`Unknown workspace root key "${key}". Only kernel-owned keys and pack-declared config_keys are allowed. If this key belongs to a pack, ensure the pack is pinned and declares config_key in its manifest.`);
|
|
300
|
+
}
|
|
301
|
+
return {
|
|
302
|
+
valid: errors.length === 0,
|
|
303
|
+
errors
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
var KernelEventBaseSchema = z.object({
|
|
307
|
+
schema_version: z.literal(1),
|
|
308
|
+
timestamp: ISO_DATETIME_SCHEMA
|
|
309
|
+
});
|
|
310
|
+
var TaskEventBaseSchema = KernelEventBaseSchema.extend({
|
|
311
|
+
task_id: z.string().min(1)
|
|
312
|
+
});
|
|
313
|
+
var RunEventBaseSchema = TaskEventBaseSchema.extend({
|
|
314
|
+
run_id: z.string().min(1)
|
|
315
|
+
});
|
|
316
|
+
var TaskCreatedEventSchema = TaskEventBaseSchema.extend({
|
|
317
|
+
kind: z.literal(KERNEL_EVENT_KINDS.TASK_CREATED),
|
|
318
|
+
spec_hash: z.string().regex(SHA256_HEX_REGEX)
|
|
319
|
+
});
|
|
320
|
+
var TaskClaimedEventSchema = TaskEventBaseSchema.extend({
|
|
321
|
+
kind: z.literal(KERNEL_EVENT_KINDS.TASK_CLAIMED),
|
|
322
|
+
by: z.string().min(1),
|
|
323
|
+
session_id: z.string().min(1),
|
|
324
|
+
domain_data: z.record(z.string(), z.unknown()).optional()
|
|
325
|
+
});
|
|
326
|
+
var TaskBlockedEventSchema = TaskEventBaseSchema.extend({
|
|
327
|
+
kind: z.literal(KERNEL_EVENT_KINDS.TASK_BLOCKED),
|
|
328
|
+
reason: z.string().min(1)
|
|
329
|
+
});
|
|
330
|
+
var TaskUnblockedEventSchema = TaskEventBaseSchema.extend({
|
|
331
|
+
kind: z.literal(KERNEL_EVENT_KINDS.TASK_UNBLOCKED)
|
|
332
|
+
});
|
|
333
|
+
var TaskWaitingEventSchema = TaskEventBaseSchema.extend({
|
|
334
|
+
kind: z.literal(KERNEL_EVENT_KINDS.TASK_WAITING),
|
|
335
|
+
reason: z.string().min(1),
|
|
336
|
+
wait_for: z.string().min(1).optional()
|
|
337
|
+
});
|
|
338
|
+
var TaskResumedEventSchema = TaskEventBaseSchema.extend({
|
|
339
|
+
kind: z.literal(KERNEL_EVENT_KINDS.TASK_RESUMED)
|
|
340
|
+
});
|
|
341
|
+
var TaskCompletedEventSchema = TaskEventBaseSchema.extend({
|
|
342
|
+
kind: z.literal(KERNEL_EVENT_KINDS.TASK_COMPLETED),
|
|
343
|
+
evidence_refs: z.array(z.string().min(1)).optional()
|
|
344
|
+
});
|
|
345
|
+
var TaskReleasedEventSchema = TaskEventBaseSchema.extend({
|
|
346
|
+
kind: z.literal(KERNEL_EVENT_KINDS.TASK_RELEASED),
|
|
347
|
+
reason: z.string().min(1)
|
|
348
|
+
});
|
|
349
|
+
var TaskDelegatedEventSchema = TaskEventBaseSchema.extend({
|
|
350
|
+
kind: z.literal(KERNEL_EVENT_KINDS.TASK_DELEGATED),
|
|
351
|
+
parent_task_id: z.string().min(1),
|
|
352
|
+
delegation_id: z.string().min(1)
|
|
353
|
+
});
|
|
354
|
+
var RunStartedEventSchema = RunEventBaseSchema.extend({
|
|
355
|
+
kind: z.literal(KERNEL_EVENT_KINDS.RUN_STARTED),
|
|
356
|
+
by: z.string().min(1),
|
|
357
|
+
session_id: z.string().min(1)
|
|
358
|
+
});
|
|
359
|
+
var RunPausedEventSchema = RunEventBaseSchema.extend({
|
|
360
|
+
kind: z.literal(KERNEL_EVENT_KINDS.RUN_PAUSED),
|
|
361
|
+
reason: z.string().min(1)
|
|
362
|
+
});
|
|
363
|
+
var RunFailedEventSchema = RunEventBaseSchema.extend({
|
|
364
|
+
kind: z.literal(KERNEL_EVENT_KINDS.RUN_FAILED),
|
|
365
|
+
reason: z.string().min(1),
|
|
366
|
+
evidence_refs: z.array(z.string().min(1)).optional()
|
|
367
|
+
});
|
|
368
|
+
var RunSucceededEventSchema = RunEventBaseSchema.extend({
|
|
369
|
+
kind: z.literal(KERNEL_EVENT_KINDS.RUN_SUCCEEDED),
|
|
370
|
+
evidence_refs: z.array(z.string().min(1)).optional()
|
|
371
|
+
});
|
|
372
|
+
var WorkspaceUpdatedEventSchema = KernelEventBaseSchema.extend({
|
|
373
|
+
kind: z.literal(KERNEL_EVENT_KINDS.WORKSPACE_UPDATED),
|
|
374
|
+
config_hash: z.string().regex(SHA256_HEX_REGEX),
|
|
375
|
+
changes_summary: z.string().min(1)
|
|
376
|
+
});
|
|
377
|
+
var WorkspaceWarningEventSchema = KernelEventBaseSchema.extend({
|
|
378
|
+
kind: z.literal(KERNEL_EVENT_KINDS.WORKSPACE_WARNING),
|
|
379
|
+
message: z.string().min(1)
|
|
380
|
+
});
|
|
381
|
+
var SpecTamperedEventSchema = KernelEventBaseSchema.extend({
|
|
382
|
+
kind: z.literal(KERNEL_EVENT_KINDS.SPEC_TAMPERED),
|
|
383
|
+
spec: z.enum(["task", "workspace"]),
|
|
384
|
+
id: z.string().min(1),
|
|
385
|
+
expected_hash: z.string().regex(SHA256_HEX_REGEX),
|
|
386
|
+
actual_hash: z.string().regex(SHA256_HEX_REGEX)
|
|
387
|
+
});
|
|
388
|
+
var CheckpointEventSchema = TaskEventBaseSchema.extend({
|
|
389
|
+
kind: z.literal(KERNEL_EVENT_KINDS.CHECKPOINT),
|
|
390
|
+
run_id: z.string().min(1).optional(),
|
|
391
|
+
note: z.string().min(1),
|
|
392
|
+
progress: z.string().min(1).optional()
|
|
393
|
+
});
|
|
394
|
+
var KernelEventSchema = z.discriminatedUnion("kind", [
|
|
395
|
+
TaskCreatedEventSchema,
|
|
396
|
+
TaskClaimedEventSchema,
|
|
397
|
+
TaskBlockedEventSchema,
|
|
398
|
+
TaskUnblockedEventSchema,
|
|
399
|
+
TaskWaitingEventSchema,
|
|
400
|
+
TaskResumedEventSchema,
|
|
401
|
+
TaskCompletedEventSchema,
|
|
402
|
+
TaskReleasedEventSchema,
|
|
403
|
+
TaskDelegatedEventSchema,
|
|
404
|
+
RunStartedEventSchema,
|
|
405
|
+
RunPausedEventSchema,
|
|
406
|
+
RunFailedEventSchema,
|
|
407
|
+
RunSucceededEventSchema,
|
|
408
|
+
WorkspaceUpdatedEventSchema,
|
|
409
|
+
WorkspaceWarningEventSchema,
|
|
410
|
+
SpecTamperedEventSchema,
|
|
411
|
+
CheckpointEventSchema
|
|
412
|
+
]);
|
|
413
|
+
var PolicyDecisionSchema = z.object({
|
|
414
|
+
policy_id: z.string().min(1),
|
|
415
|
+
decision: z.enum(["allow", "deny", "approval_required"]),
|
|
416
|
+
reason: z.string().min(1).optional()
|
|
417
|
+
});
|
|
418
|
+
var ToolCallStartedSchema = z.object({
|
|
419
|
+
schema_version: z.literal(1),
|
|
420
|
+
kind: z.literal(TOOL_TRACE_KINDS.TOOL_CALL_STARTED),
|
|
421
|
+
receipt_id: z.string().min(1),
|
|
422
|
+
run_id: z.string().min(1),
|
|
423
|
+
task_id: z.string().min(1),
|
|
424
|
+
session_id: z.string().min(1),
|
|
425
|
+
timestamp: ISO_DATETIME_SCHEMA,
|
|
426
|
+
tool_name: z.string().min(1),
|
|
427
|
+
execution_mode: z.enum(TOOL_HANDLER_KIND_VALUES),
|
|
428
|
+
scope_requested: z.array(ToolScopeSchema),
|
|
429
|
+
scope_allowed: z.array(ToolScopeSchema),
|
|
430
|
+
scope_enforced: z.array(ToolScopeSchema),
|
|
431
|
+
input_hash: z.string().regex(SHA256_HEX_REGEX),
|
|
432
|
+
input_ref: z.string().min(1),
|
|
433
|
+
tool_version: z.string().regex(SEMVER_REGEX, SEMVER_MESSAGE),
|
|
434
|
+
pack_id: z.string().min(1).optional(),
|
|
435
|
+
pack_version: z.string().regex(SEMVER_REGEX, SEMVER_MESSAGE).optional(),
|
|
436
|
+
pack_integrity: z.string().optional(),
|
|
437
|
+
workspace_config_hash: z.string().regex(SHA256_HEX_REGEX),
|
|
438
|
+
runtime_version: z.string().min(1)
|
|
439
|
+
});
|
|
440
|
+
var ToolCallFinishedSchema = z.object({
|
|
441
|
+
schema_version: z.literal(1),
|
|
442
|
+
kind: z.literal(TOOL_TRACE_KINDS.TOOL_CALL_FINISHED),
|
|
443
|
+
receipt_id: z.string().min(1),
|
|
444
|
+
timestamp: ISO_DATETIME_SCHEMA,
|
|
445
|
+
result: z.enum(["success", "failure", "denied", "crashed"]),
|
|
446
|
+
duration_ms: z.number().int().nonnegative(),
|
|
447
|
+
output_hash: z.string().regex(SHA256_HEX_REGEX).optional(),
|
|
448
|
+
output_ref: z.string().min(1).optional(),
|
|
449
|
+
redaction_summary: z.string().min(1).optional(),
|
|
450
|
+
scope_enforcement_note: z.string().min(1).optional(),
|
|
451
|
+
policy_decisions: z.array(PolicyDecisionSchema),
|
|
452
|
+
artifacts_written: z.array(z.string().min(1)).optional()
|
|
453
|
+
});
|
|
454
|
+
var ToolTraceEntrySchema = z.discriminatedUnion("kind", [
|
|
455
|
+
ToolCallStartedSchema,
|
|
456
|
+
ToolCallFinishedSchema
|
|
457
|
+
]);
|
|
458
|
+
var ToolErrorSchema = z.object({
|
|
459
|
+
code: z.string().min(1),
|
|
460
|
+
message: z.string().min(1),
|
|
461
|
+
details: z.record(z.string(), z.unknown()).optional()
|
|
462
|
+
});
|
|
463
|
+
var ToolOutputSchema = z.object({
|
|
464
|
+
success: z.boolean(),
|
|
465
|
+
data: z.unknown().optional(),
|
|
466
|
+
error: ToolErrorSchema.optional(),
|
|
467
|
+
metadata: z.record(z.string(), z.unknown()).optional()
|
|
468
|
+
});
|
|
469
|
+
var ExecutionContextSchema = z.object({
|
|
470
|
+
run_id: z.string().min(1),
|
|
471
|
+
task_id: z.string().min(1),
|
|
472
|
+
session_id: z.string().min(1),
|
|
473
|
+
allowed_scopes: z.array(ToolScopeSchema),
|
|
474
|
+
metadata: z.record(z.string(), z.unknown()).optional()
|
|
475
|
+
});
|
|
476
|
+
var ZodSchemaSchema = z.custom((value) => value instanceof z.ZodType, {
|
|
477
|
+
message: "Expected a Zod schema"
|
|
478
|
+
});
|
|
479
|
+
var InProcessToolHandlerSchema = z.object({
|
|
480
|
+
kind: z.literal(TOOL_HANDLER_KINDS.IN_PROCESS),
|
|
481
|
+
fn: z.custom((value) => typeof value === "function", {
|
|
482
|
+
message: "Expected an async tool function"
|
|
483
|
+
})
|
|
484
|
+
});
|
|
485
|
+
var SubprocessToolHandlerSchema = z.object({
|
|
486
|
+
kind: z.literal(TOOL_HANDLER_KINDS.SUBPROCESS),
|
|
487
|
+
entry: z.string().min(1)
|
|
488
|
+
});
|
|
489
|
+
var ToolHandlerSchema = z.discriminatedUnion("kind", [
|
|
490
|
+
InProcessToolHandlerSchema,
|
|
491
|
+
SubprocessToolHandlerSchema
|
|
492
|
+
]);
|
|
493
|
+
var ToolCapabilitySchema = z.object({
|
|
494
|
+
name: z.string().min(1),
|
|
495
|
+
domain: z.string().min(1),
|
|
496
|
+
version: z.string().regex(SEMVER_REGEX, SEMVER_MESSAGE),
|
|
497
|
+
input_schema: ZodSchemaSchema,
|
|
498
|
+
output_schema: ZodSchemaSchema.optional(),
|
|
499
|
+
permission: z.enum(["read", "write", "admin"]),
|
|
500
|
+
required_scopes: z.array(ToolScopeSchema),
|
|
501
|
+
handler: ToolHandlerSchema,
|
|
502
|
+
description: z.string().min(1),
|
|
503
|
+
pack: z.string().min(1).optional()
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
// ../kernel/dist/pack/hash.js
|
|
507
|
+
import { createHash } from "crypto";
|
|
508
|
+
import { readdir, readFile } from "fs/promises";
|
|
509
|
+
import path from "path";
|
|
510
|
+
var NULL_BYTE_BUFFER = Buffer.from([0]);
|
|
511
|
+
var DEFAULT_EXCLUSIONS = ["node_modules/", `${GIT_DIR_NAME}/`, "dist/", ".DS_Store"];
|
|
512
|
+
function normalizeRelativePath(root, absolutePath) {
|
|
513
|
+
return path.relative(root, absolutePath).split(path.sep).join("/");
|
|
514
|
+
}
|
|
515
|
+
function shouldExclude(relativePath, exclusions) {
|
|
516
|
+
return exclusions.some((excluded) => {
|
|
517
|
+
if (excluded.endsWith("/")) {
|
|
518
|
+
return relativePath.startsWith(excluded);
|
|
519
|
+
}
|
|
520
|
+
return relativePath === excluded || relativePath.endsWith(`/${excluded}`);
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
async function collectFilesRecursive(root, directory) {
|
|
524
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
525
|
+
const sortedEntries = [...entries].sort((left, right) => left.name.localeCompare(right.name));
|
|
526
|
+
const files = [];
|
|
527
|
+
for (const entry of sortedEntries) {
|
|
528
|
+
const absolutePath = path.join(directory, entry.name);
|
|
529
|
+
const relativePath = normalizeRelativePath(root, absolutePath);
|
|
530
|
+
if (entry.isDirectory()) {
|
|
531
|
+
files.push(...await collectFilesRecursive(root, absolutePath));
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
534
|
+
files.push(relativePath);
|
|
535
|
+
}
|
|
536
|
+
return files;
|
|
537
|
+
}
|
|
538
|
+
async function listPackFiles(packRoot, exclusions = DEFAULT_EXCLUSIONS) {
|
|
539
|
+
const absoluteRoot = path.resolve(packRoot);
|
|
540
|
+
const allFiles = await collectFilesRecursive(absoluteRoot, absoluteRoot);
|
|
541
|
+
return allFiles.filter((relativePath) => !shouldExclude(relativePath, exclusions)).sort();
|
|
542
|
+
}
|
|
543
|
+
async function computeDeterministicPackHash(input) {
|
|
544
|
+
const absoluteRoot = path.resolve(input.packRoot);
|
|
545
|
+
const files = await listPackFiles(absoluteRoot, input.exclusions || DEFAULT_EXCLUSIONS);
|
|
546
|
+
const digestChunks = [];
|
|
547
|
+
for (const relativePath of files) {
|
|
548
|
+
const fileContents = await readFile(path.join(absoluteRoot, relativePath));
|
|
549
|
+
const fileHash = createHash(SHA256_ALGORITHM).update(fileContents).digest("hex");
|
|
550
|
+
digestChunks.push(Buffer.from(relativePath, UTF8_ENCODING));
|
|
551
|
+
digestChunks.push(NULL_BYTE_BUFFER);
|
|
552
|
+
digestChunks.push(Buffer.from(fileHash, UTF8_ENCODING));
|
|
553
|
+
digestChunks.push(NULL_BYTE_BUFFER);
|
|
554
|
+
}
|
|
555
|
+
return createHash(SHA256_ALGORITHM).update(digestChunks.length === 0 ? Buffer.alloc(0) : Buffer.concat(digestChunks)).digest("hex");
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// ../kernel/dist/pack/manifest.js
|
|
559
|
+
import { z as z2 } from "zod";
|
|
560
|
+
|
|
561
|
+
// ../kernel/dist/policy/policy-engine.js
|
|
562
|
+
var POLICY_TRIGGERS = {
|
|
563
|
+
ON_TOOL_REQUEST: "on_tool_request",
|
|
564
|
+
ON_CLAIM: "on_claim",
|
|
565
|
+
ON_COMPLETION: "on_completion",
|
|
566
|
+
ON_EVIDENCE_ADDED: "on_evidence_added"
|
|
567
|
+
};
|
|
568
|
+
var POLICY_LAYER_ORDER = ["workspace", "lane", "pack", "task"];
|
|
569
|
+
function layerOrderScore(level) {
|
|
570
|
+
const index = POLICY_LAYER_ORDER.indexOf(level);
|
|
571
|
+
return index < 0 ? POLICY_LAYER_ORDER.length : index;
|
|
572
|
+
}
|
|
573
|
+
function matchingRules(layer, context) {
|
|
574
|
+
return layer.rules.filter((rule) => {
|
|
575
|
+
if (rule.trigger !== context.trigger) {
|
|
576
|
+
return false;
|
|
577
|
+
}
|
|
578
|
+
if (!rule.when) {
|
|
579
|
+
return true;
|
|
580
|
+
}
|
|
581
|
+
return rule.when(context);
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
function canLoosen(layer) {
|
|
585
|
+
return layer.allow_loosening === true;
|
|
586
|
+
}
|
|
587
|
+
var PolicyEngine = class {
|
|
588
|
+
layers;
|
|
589
|
+
constructor(options) {
|
|
590
|
+
this.layers = [...options.layers].sort((left, right) => layerOrderScore(left.level) - layerOrderScore(right.level));
|
|
591
|
+
}
|
|
592
|
+
async evaluate(context) {
|
|
593
|
+
let effectiveDecision = "deny";
|
|
594
|
+
let hasInitializedDecision = false;
|
|
595
|
+
let hasHardDeny = false;
|
|
596
|
+
let hasApprovalRequired = false;
|
|
597
|
+
const warnings = [];
|
|
598
|
+
const decisions = [];
|
|
599
|
+
for (const layer of this.layers) {
|
|
600
|
+
if (!hasInitializedDecision) {
|
|
601
|
+
if (layer.default_decision) {
|
|
602
|
+
effectiveDecision = layer.default_decision;
|
|
603
|
+
}
|
|
604
|
+
hasInitializedDecision = true;
|
|
605
|
+
} else if (layer.default_decision) {
|
|
606
|
+
if (effectiveDecision === "deny" && layer.default_decision === "allow" && !canLoosen(layer)) {
|
|
607
|
+
warnings.push(`Policy layer "${layer.level}" attempted loosening default decision without explicit opt-in.`);
|
|
608
|
+
} else {
|
|
609
|
+
effectiveDecision = layer.default_decision;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
const layerRules = matchingRules(layer, context);
|
|
613
|
+
for (const rule of layerRules) {
|
|
614
|
+
decisions.push({
|
|
615
|
+
policy_id: rule.id,
|
|
616
|
+
decision: rule.decision,
|
|
617
|
+
reason: rule.reason
|
|
618
|
+
});
|
|
619
|
+
if (rule.decision === "deny") {
|
|
620
|
+
hasHardDeny = true;
|
|
621
|
+
effectiveDecision = "deny";
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
if (rule.decision === "approval_required") {
|
|
625
|
+
hasApprovalRequired = true;
|
|
626
|
+
if (effectiveDecision !== "deny" || canLoosen(layer)) {
|
|
627
|
+
effectiveDecision = "approval_required";
|
|
628
|
+
}
|
|
629
|
+
continue;
|
|
630
|
+
}
|
|
631
|
+
if (effectiveDecision === "deny" && !canLoosen(layer)) {
|
|
632
|
+
warnings.push(`Policy layer "${layer.level}" attempted loosening via rule "${rule.id}" without explicit opt-in.`);
|
|
633
|
+
continue;
|
|
634
|
+
}
|
|
635
|
+
effectiveDecision = "allow";
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
if (hasHardDeny) {
|
|
639
|
+
return { decision: "deny", decisions, warnings };
|
|
640
|
+
}
|
|
641
|
+
if (hasApprovalRequired) {
|
|
642
|
+
return { decision: "approval_required", decisions, warnings };
|
|
643
|
+
}
|
|
644
|
+
return { decision: effectiveDecision, decisions, warnings };
|
|
645
|
+
}
|
|
646
|
+
};
|
|
647
|
+
|
|
648
|
+
// ../kernel/dist/pack/manifest.js
|
|
649
|
+
var SEMVER_REGEX2 = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-.]+)?(?:\+[0-9A-Za-z-.]+)?$/;
|
|
650
|
+
var SEMVER_MESSAGE2 = "Expected semantic version";
|
|
651
|
+
var NULL_BYTE = "\0";
|
|
652
|
+
var SCOPE_TRAVERSAL_PATTERN = /(^|\/)\.\.(\/|$)/;
|
|
653
|
+
var BROAD_WILDCARD_SCOPE_PATTERNS = /* @__PURE__ */ new Set(["*", "**", "**/*", "./**", "./**/*"]);
|
|
654
|
+
var JsonSchemaObjectSchema = z2.record(z2.string(), z2.unknown());
|
|
655
|
+
var DomainPackToolSchema = z2.object({
|
|
656
|
+
name: z2.string().min(1),
|
|
657
|
+
entry: z2.string().min(1),
|
|
658
|
+
permission: z2.enum(["read", "write", "admin"]).default("read"),
|
|
659
|
+
required_scopes: z2.array(ToolScopeSchema).min(1),
|
|
660
|
+
internal_only: z2.boolean().optional(),
|
|
661
|
+
/** Optional JSON Schema for tool input validation. */
|
|
662
|
+
input_schema: JsonSchemaObjectSchema.optional(),
|
|
663
|
+
/** Optional JSON Schema for tool output validation. */
|
|
664
|
+
output_schema: JsonSchemaObjectSchema.optional()
|
|
665
|
+
});
|
|
666
|
+
function isBroadWildcardScopePattern(pattern) {
|
|
667
|
+
return BROAD_WILDCARD_SCOPE_PATTERNS.has(pattern.trim());
|
|
668
|
+
}
|
|
669
|
+
function hasUnsafeScopePattern(pattern) {
|
|
670
|
+
return pattern.includes(NULL_BYTE) || SCOPE_TRAVERSAL_PATTERN.test(pattern);
|
|
671
|
+
}
|
|
672
|
+
function validateDomainPackToolSafety(tool) {
|
|
673
|
+
const issues = [];
|
|
674
|
+
for (const scope of tool.required_scopes) {
|
|
675
|
+
if (scope.type !== "path") {
|
|
676
|
+
continue;
|
|
677
|
+
}
|
|
678
|
+
if (hasUnsafeScopePattern(scope.pattern)) {
|
|
679
|
+
issues.push(`scope pattern "${scope.pattern}" contains unsafe traversal or null-byte content`);
|
|
680
|
+
}
|
|
681
|
+
if ((tool.permission === "write" || tool.permission === "admin") && scope.access === "write" && isBroadWildcardScopePattern(scope.pattern)) {
|
|
682
|
+
issues.push(`scope pattern "${scope.pattern}" is too broad for ${tool.permission} permission and write access`);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
const inputSchemaType = tool.input_schema?.type;
|
|
686
|
+
if (inputSchemaType && inputSchemaType !== "object") {
|
|
687
|
+
issues.push(`input_schema.type must be "object" when provided, got "${String(inputSchemaType)}"`);
|
|
688
|
+
}
|
|
689
|
+
const outputSchemaType = tool.output_schema?.type;
|
|
690
|
+
if (outputSchemaType && outputSchemaType !== "object") {
|
|
691
|
+
issues.push(`output_schema.type must be "object" when provided, got "${String(outputSchemaType)}"`);
|
|
692
|
+
}
|
|
693
|
+
return issues;
|
|
694
|
+
}
|
|
695
|
+
var DomainPackPolicySchema = z2.object({
|
|
696
|
+
id: z2.string().min(1),
|
|
697
|
+
trigger: z2.enum([
|
|
698
|
+
POLICY_TRIGGERS.ON_TOOL_REQUEST,
|
|
699
|
+
POLICY_TRIGGERS.ON_CLAIM,
|
|
700
|
+
POLICY_TRIGGERS.ON_COMPLETION,
|
|
701
|
+
POLICY_TRIGGERS.ON_EVIDENCE_ADDED
|
|
702
|
+
]),
|
|
703
|
+
decision: z2.enum(["allow", "deny"]),
|
|
704
|
+
reason: z2.string().min(1).optional()
|
|
705
|
+
});
|
|
706
|
+
var DomainPackLaneTemplateSchema = z2.object({
|
|
707
|
+
id: z2.string().min(1),
|
|
708
|
+
title: z2.string().min(1).optional(),
|
|
709
|
+
description: z2.string().min(1).optional()
|
|
710
|
+
});
|
|
711
|
+
var DomainPackManifestSchema = z2.object({
|
|
712
|
+
id: z2.string().min(1),
|
|
713
|
+
version: z2.string().regex(SEMVER_REGEX2, SEMVER_MESSAGE2),
|
|
714
|
+
task_types: z2.array(z2.string().min(1)).min(1),
|
|
715
|
+
tools: z2.array(DomainPackToolSchema),
|
|
716
|
+
policies: z2.array(DomainPackPolicySchema),
|
|
717
|
+
evidence_types: z2.array(z2.string().min(1)).default([]),
|
|
718
|
+
state_aliases: z2.record(z2.string().min(1), z2.string().min(1)).default({}),
|
|
719
|
+
lane_templates: z2.array(DomainPackLaneTemplateSchema).default([]),
|
|
720
|
+
/** Root key in workspace.yaml that this pack owns for its configuration namespace. */
|
|
721
|
+
config_key: z2.string().min(1).optional(),
|
|
722
|
+
/** Path to a JSON Schema file (relative to pack root) describing the pack config shape. */
|
|
723
|
+
config_schema: z2.string().optional()
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
// ../kernel/dist/pack/pack-loader.js
|
|
727
|
+
import { builtinModules } from "module";
|
|
728
|
+
import path2 from "path";
|
|
729
|
+
import { access, mkdir, readFile as readFile2 } from "fs/promises";
|
|
730
|
+
import { homedir } from "os";
|
|
731
|
+
import YAML from "yaml";
|
|
732
|
+
var PACK_CACHE_DIR_NAME = "pack-cache";
|
|
733
|
+
var VERSION_TAG_PREFIX = "v";
|
|
734
|
+
var DEFAULT_REGISTRY_URL = "https://registry.lumenflow.dev";
|
|
735
|
+
var NODE_BUILTINS = new Set(builtinModules.map((moduleName) => moduleName.replace(/^node:/, "")));
|
|
736
|
+
var ALLOWED_BARE_IMPORT_SPECIFIERS = /* @__PURE__ */ new Set(["simple-git"]);
|
|
737
|
+
var IMPORT_SPECIFIER_PATTERNS = [
|
|
738
|
+
/\bimport\s+(?:[^'"]*?\sfrom\s*)?["']([^"']+)["']/,
|
|
739
|
+
/\bexport\s+[^'"]*?\sfrom\s*["']([^"']+)["']/,
|
|
740
|
+
/\bimport\(\s*["']([^"']+)["']\s*\)/
|
|
741
|
+
];
|
|
742
|
+
function isWithinRoot(root, candidatePath) {
|
|
743
|
+
const relative = path2.relative(root, candidatePath);
|
|
744
|
+
return relative === "" || !relative.startsWith("..") && !path2.isAbsolute(relative);
|
|
745
|
+
}
|
|
746
|
+
function isRuntimeSourceFile(relativePath) {
|
|
747
|
+
const normalizedPath = relativePath.replace(/\\/g, "/");
|
|
748
|
+
const extension = path2.extname(normalizedPath);
|
|
749
|
+
const isCodeFile = [".ts", ".tsx", ".mts", ".cts", ".js", ".mjs", ".cjs"].includes(extension);
|
|
750
|
+
if (!isCodeFile) {
|
|
751
|
+
return false;
|
|
752
|
+
}
|
|
753
|
+
if (normalizedPath.includes("/__tests__/")) {
|
|
754
|
+
return false;
|
|
755
|
+
}
|
|
756
|
+
return !/\.(test|spec)\.[cm]?[jt]sx?$/.test(normalizedPath);
|
|
757
|
+
}
|
|
758
|
+
function parseToolEntry(entry) {
|
|
759
|
+
const separator = entry.indexOf("#");
|
|
760
|
+
const modulePath = separator < 0 ? entry : entry.slice(0, separator);
|
|
761
|
+
const exportName = separator < 0 ? void 0 : entry.slice(separator + 1);
|
|
762
|
+
if (modulePath.trim().length === 0) {
|
|
763
|
+
throw new Error(`Pack tool entry "${entry}" is missing a module path.`);
|
|
764
|
+
}
|
|
765
|
+
if (exportName !== void 0 && exportName.trim().length === 0) {
|
|
766
|
+
throw new Error(`Pack tool entry "${entry}" has an empty export fragment.`);
|
|
767
|
+
}
|
|
768
|
+
return {
|
|
769
|
+
modulePath,
|
|
770
|
+
exportName
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
function resolvePackToolEntryPath(packRoot, entry) {
|
|
774
|
+
const absolutePackRoot = path2.resolve(packRoot);
|
|
775
|
+
const { modulePath, exportName } = parseToolEntry(entry);
|
|
776
|
+
const absoluteModulePath = path2.resolve(absolutePackRoot, modulePath);
|
|
777
|
+
if (!isWithinRoot(absolutePackRoot, absoluteModulePath)) {
|
|
778
|
+
throw new Error(`Pack tool entry "${entry}" resolves outside pack root.`);
|
|
779
|
+
}
|
|
780
|
+
return exportName ? `${absoluteModulePath}#${exportName}` : absoluteModulePath;
|
|
781
|
+
}
|
|
782
|
+
function extractImportSpecifiers(sourceCode) {
|
|
783
|
+
const specifiers = /* @__PURE__ */ new Set();
|
|
784
|
+
for (const pattern of IMPORT_SPECIFIER_PATTERNS) {
|
|
785
|
+
const globalPattern = new RegExp(pattern.source, "g");
|
|
786
|
+
for (const match of sourceCode.matchAll(globalPattern)) {
|
|
787
|
+
if (match[1]) {
|
|
788
|
+
specifiers.add(match[1]);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
return [...specifiers];
|
|
793
|
+
}
|
|
794
|
+
function isAllowedKernelImport(specifier) {
|
|
795
|
+
return specifier === "@lumenflow/kernel" || specifier.startsWith("@lumenflow/kernel/");
|
|
796
|
+
}
|
|
797
|
+
function validateImportSpecifier(options) {
|
|
798
|
+
const { specifier, sourceFilePath, packRoot } = options;
|
|
799
|
+
if (specifier.startsWith("node:")) {
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
if (NODE_BUILTINS.has(specifier)) {
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
if (isAllowedKernelImport(specifier)) {
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
if (specifier.startsWith("@lumenflow/")) {
|
|
809
|
+
throw new Error(`Import "${specifier}" in ${sourceFilePath} is not allowed; only @lumenflow/kernel and Node built-ins are permitted.`);
|
|
810
|
+
}
|
|
811
|
+
if (path2.isAbsolute(specifier)) {
|
|
812
|
+
throw new Error(`Import "${specifier}" in ${sourceFilePath} resolves outside pack root.`);
|
|
813
|
+
}
|
|
814
|
+
if (specifier.startsWith(".")) {
|
|
815
|
+
const absoluteFilePath = path2.resolve(packRoot, sourceFilePath);
|
|
816
|
+
const resolvedImport = path2.resolve(path2.dirname(absoluteFilePath), specifier);
|
|
817
|
+
if (!isWithinRoot(packRoot, resolvedImport)) {
|
|
818
|
+
throw new Error(`Import "${specifier}" in ${sourceFilePath} resolves outside pack root.`);
|
|
819
|
+
}
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
if (ALLOWED_BARE_IMPORT_SPECIFIERS.has(specifier)) {
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
throw new Error(`Bare package import "${specifier}" in ${sourceFilePath} is not allowed; only relative imports, @lumenflow/kernel, and Node built-ins are permitted.`);
|
|
826
|
+
}
|
|
827
|
+
async function validatePackImportBoundaries(packRoot, hashExclusions) {
|
|
828
|
+
const files = await listPackFiles(packRoot, hashExclusions);
|
|
829
|
+
const candidateFiles = files.filter((relativePath) => isRuntimeSourceFile(relativePath));
|
|
830
|
+
for (const relativePath of candidateFiles) {
|
|
831
|
+
const sourceCode = await readFile2(path2.join(packRoot, relativePath), UTF8_ENCODING);
|
|
832
|
+
const importSpecifiers = extractImportSpecifiers(sourceCode);
|
|
833
|
+
for (const specifier of importSpecifiers) {
|
|
834
|
+
validateImportSpecifier({
|
|
835
|
+
specifier,
|
|
836
|
+
sourceFilePath: relativePath,
|
|
837
|
+
packRoot
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
function resolvePackPin(workspaceSpec, packId) {
|
|
843
|
+
const pin = workspaceSpec.packs.find((candidate) => candidate.id === packId);
|
|
844
|
+
if (!pin) {
|
|
845
|
+
throw new Error(`Pack "${packId}" is not present in workspace PackPin entries.`);
|
|
846
|
+
}
|
|
847
|
+
return pin;
|
|
848
|
+
}
|
|
849
|
+
var PackLoader = class {
|
|
850
|
+
packsRoot;
|
|
851
|
+
manifestFileName;
|
|
852
|
+
hashExclusions;
|
|
853
|
+
runtimeEnvironment;
|
|
854
|
+
allowDevIntegrityInProduction;
|
|
855
|
+
packCacheDir;
|
|
856
|
+
gitClient;
|
|
857
|
+
registryClient;
|
|
858
|
+
defaultRegistryUrl;
|
|
859
|
+
constructor(options) {
|
|
860
|
+
this.packsRoot = path2.resolve(options.packsRoot);
|
|
861
|
+
this.manifestFileName = options.manifestFileName || PACK_MANIFEST_FILE_NAME;
|
|
862
|
+
this.hashExclusions = options.hashExclusions;
|
|
863
|
+
this.runtimeEnvironment = options.runtimeEnvironment ?? process.env.NODE_ENV ?? "development";
|
|
864
|
+
this.allowDevIntegrityInProduction = options.allowDevIntegrityInProduction ?? false;
|
|
865
|
+
this.packCacheDir = options.packCacheDir ?? path2.join(homedir(), LUMENFLOW_DIR_NAME, PACK_CACHE_DIR_NAME);
|
|
866
|
+
this.gitClient = options.gitClient;
|
|
867
|
+
this.registryClient = options.registryClient;
|
|
868
|
+
this.defaultRegistryUrl = options.defaultRegistryUrl ?? DEFAULT_REGISTRY_URL;
|
|
869
|
+
}
|
|
870
|
+
async load(input) {
|
|
871
|
+
const pin = resolvePackPin(input.workspaceSpec, input.packId);
|
|
872
|
+
const packRoot = await this.resolvePackRoot(pin);
|
|
873
|
+
return this.loadFromDisk(pin, packRoot, input);
|
|
874
|
+
}
|
|
875
|
+
/**
|
|
876
|
+
* Resolve the pack root directory based on the pin source.
|
|
877
|
+
* For local packs, resolves relative to packsRoot.
|
|
878
|
+
* For git packs, clones/pulls to the pack cache and checks out the version tag.
|
|
879
|
+
* For registry packs, fetches metadata and downloads tarball to the pack cache.
|
|
880
|
+
*/
|
|
881
|
+
async resolvePackRoot(pin) {
|
|
882
|
+
if (pin.source === "git") {
|
|
883
|
+
return this.resolveGitPackRoot(pin);
|
|
884
|
+
}
|
|
885
|
+
if (pin.source === "registry") {
|
|
886
|
+
return this.resolveRegistryPackRoot(pin);
|
|
887
|
+
}
|
|
888
|
+
return path2.resolve(this.packsRoot, pin.id);
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Resolve a git-sourced pack by cloning or pulling to the pack cache,
|
|
892
|
+
* then checking out the version tag.
|
|
893
|
+
*/
|
|
894
|
+
async resolveGitPackRoot(pin) {
|
|
895
|
+
if (!pin.url) {
|
|
896
|
+
throw new Error(`Pack "${pin.id}" has source: git but no url field. Add a url field to the PackPin to specify the git repository.`);
|
|
897
|
+
}
|
|
898
|
+
if (!this.gitClient) {
|
|
899
|
+
throw new Error(`Pack "${pin.id}" has source: git but no gitClient was provided to PackLoader. Pass a gitClient in PackLoaderOptions to load git-sourced packs.`);
|
|
900
|
+
}
|
|
901
|
+
const packCachePath = path2.join(this.packCacheDir, `${pin.id}@${pin.version}`);
|
|
902
|
+
await mkdir(this.packCacheDir, { recursive: true });
|
|
903
|
+
const alreadyCached = await this.gitClient.isRepo(packCachePath);
|
|
904
|
+
if (alreadyCached) {
|
|
905
|
+
await this.gitClient.pull(packCachePath);
|
|
906
|
+
} else {
|
|
907
|
+
await this.gitClient.clone(pin.url, packCachePath);
|
|
908
|
+
}
|
|
909
|
+
const versionTag = `${VERSION_TAG_PREFIX}${pin.version}`;
|
|
910
|
+
await this.gitClient.checkout(packCachePath, versionTag);
|
|
911
|
+
return packCachePath;
|
|
912
|
+
}
|
|
913
|
+
/**
|
|
914
|
+
* Resolve a registry-sourced pack by fetching metadata and downloading the tarball
|
|
915
|
+
* to the pack cache. Skips download if the pack is already cached.
|
|
916
|
+
*/
|
|
917
|
+
async resolveRegistryPackRoot(pin) {
|
|
918
|
+
if (!this.registryClient) {
|
|
919
|
+
throw new Error(`Pack "${pin.id}" has source: registry but no registryClient was provided to PackLoader. Pass a registryClient in PackLoaderOptions to load registry-sourced packs.`);
|
|
920
|
+
}
|
|
921
|
+
const packCachePath = path2.join(this.packCacheDir, `${pin.id}@${pin.version}`);
|
|
922
|
+
await mkdir(this.packCacheDir, { recursive: true });
|
|
923
|
+
const manifestCachePath = path2.join(packCachePath, this.manifestFileName);
|
|
924
|
+
const alreadyCached = await access(manifestCachePath).then(() => true).catch(() => false);
|
|
925
|
+
if (!alreadyCached) {
|
|
926
|
+
const registryUrl = pin.registry_url ?? this.defaultRegistryUrl;
|
|
927
|
+
const metadata = await this.registryClient.fetchMetadata(pin.id, pin.version, registryUrl);
|
|
928
|
+
await this.registryClient.downloadTarball(metadata.tarball_url, packCachePath);
|
|
929
|
+
}
|
|
930
|
+
return packCachePath;
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Load pack from a resolved on-disk directory.
|
|
934
|
+
* Handles manifest parsing, tool entry validation, import boundary checks,
|
|
935
|
+
* integrity verification, and dev-mode warnings.
|
|
936
|
+
*/
|
|
937
|
+
async loadFromDisk(pin, packRoot, input) {
|
|
938
|
+
const manifestPath = path2.join(packRoot, this.manifestFileName);
|
|
939
|
+
const manifestRaw = await readFile2(manifestPath, UTF8_ENCODING);
|
|
940
|
+
const manifest = DomainPackManifestSchema.parse(YAML.parse(manifestRaw));
|
|
941
|
+
if (manifest.id !== pin.id) {
|
|
942
|
+
throw new Error(`Pack manifest id mismatch: expected ${pin.id}, got ${manifest.id}`);
|
|
943
|
+
}
|
|
944
|
+
if (manifest.version !== pin.version) {
|
|
945
|
+
throw new Error(`Pack manifest version mismatch: expected ${pin.version}, got ${manifest.version}`);
|
|
946
|
+
}
|
|
947
|
+
for (const tool of manifest.tools) {
|
|
948
|
+
resolvePackToolEntryPath(packRoot, tool.entry);
|
|
949
|
+
}
|
|
950
|
+
await validatePackImportBoundaries(packRoot, this.hashExclusions);
|
|
951
|
+
const integrity = await computeDeterministicPackHash({
|
|
952
|
+
packRoot,
|
|
953
|
+
exclusions: this.hashExclusions
|
|
954
|
+
});
|
|
955
|
+
if (pin.integrity === "dev") {
|
|
956
|
+
if (this.runtimeEnvironment === "production" && !this.allowDevIntegrityInProduction) {
|
|
957
|
+
throw new Error(`Pack ${pin.id}@${pin.version} uses integrity: dev is not allowed in production.`);
|
|
958
|
+
}
|
|
959
|
+
input.onWorkspaceWarning?.({
|
|
960
|
+
schema_version: 1,
|
|
961
|
+
kind: KERNEL_EVENT_KINDS.WORKSPACE_WARNING,
|
|
962
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
963
|
+
message: `Pack ${pin.id}@${pin.version} loaded with integrity: dev (verification skipped).`
|
|
964
|
+
});
|
|
965
|
+
return {
|
|
966
|
+
pin,
|
|
967
|
+
manifest,
|
|
968
|
+
packRoot,
|
|
969
|
+
integrity
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
const expectedIntegrity = pin.integrity.startsWith(SHA256_INTEGRITY_PREFIX) ? pin.integrity.slice(SHA256_INTEGRITY_PREFIX.length) : pin.integrity;
|
|
973
|
+
if (integrity !== expectedIntegrity) {
|
|
974
|
+
throw new Error(`Pack integrity mismatch for ${pin.id}: expected ${expectedIntegrity}, got ${integrity}`);
|
|
975
|
+
}
|
|
976
|
+
return {
|
|
977
|
+
pin,
|
|
978
|
+
manifest,
|
|
979
|
+
packRoot,
|
|
980
|
+
integrity
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
};
|
|
984
|
+
|
|
985
|
+
// ../kernel/dist/pack/pack-manifest-resolver.js
|
|
986
|
+
import path3 from "path";
|
|
987
|
+
import { existsSync, readFileSync } from "fs";
|
|
988
|
+
import { homedir as homedir2 } from "os";
|
|
989
|
+
import YAML2 from "yaml";
|
|
990
|
+
var PACK_CACHE_DIR_NAME2 = "pack-cache";
|
|
991
|
+
var NODE_MODULES_DIR_NAME = "node_modules";
|
|
992
|
+
var DEFAULT_PACK_CACHE_DIR = path3.join(homedir2(), LUMENFLOW_DIR_NAME, PACK_CACHE_DIR_NAME2);
|
|
993
|
+
function resolveManifestPath(projectRoot, pack, packCacheDir) {
|
|
994
|
+
const source = pack.source;
|
|
995
|
+
if (source === "registry") {
|
|
996
|
+
return path3.join(projectRoot, NODE_MODULES_DIR_NAME, LUMENFLOW_SCOPE_NAME, PACKS_DIR_NAME, pack.id, PACK_MANIFEST_FILE_NAME);
|
|
997
|
+
}
|
|
998
|
+
if (source === "git") {
|
|
999
|
+
return path3.join(packCacheDir, `${pack.id}@${pack.version}`, PACK_MANIFEST_FILE_NAME);
|
|
1000
|
+
}
|
|
1001
|
+
if (pack.path) {
|
|
1002
|
+
return path3.join(projectRoot, pack.path, PACK_MANIFEST_FILE_NAME);
|
|
1003
|
+
}
|
|
1004
|
+
return path3.join(projectRoot, PACKAGES_DIR_NAME, LUMENFLOW_SCOPE_NAME, PACKS_DIR_NAME, pack.id, PACK_MANIFEST_FILE_NAME);
|
|
1005
|
+
}
|
|
1006
|
+
function resolvePackManifestPaths(input) {
|
|
1007
|
+
const result = /* @__PURE__ */ new Map();
|
|
1008
|
+
const { projectRoot, packs, packCacheDir } = input;
|
|
1009
|
+
if (!Array.isArray(packs)) {
|
|
1010
|
+
return result;
|
|
1011
|
+
}
|
|
1012
|
+
const effectiveCacheDir = packCacheDir ?? DEFAULT_PACK_CACHE_DIR;
|
|
1013
|
+
for (const pack of packs) {
|
|
1014
|
+
if (!pack || typeof pack !== "object" || !("id" in pack)) {
|
|
1015
|
+
continue;
|
|
1016
|
+
}
|
|
1017
|
+
const packId = String(pack.id);
|
|
1018
|
+
const manifestPath = resolveManifestPath(projectRoot, { ...pack, id: packId }, effectiveCacheDir);
|
|
1019
|
+
if (!manifestPath || !existsSync(manifestPath)) {
|
|
1020
|
+
continue;
|
|
1021
|
+
}
|
|
1022
|
+
try {
|
|
1023
|
+
const manifestContent = readFileSync(manifestPath, "utf8");
|
|
1024
|
+
const manifest = YAML2.parse(manifestContent);
|
|
1025
|
+
if (manifest && typeof manifest.config_key === "string") {
|
|
1026
|
+
result.set(manifest.config_key, packId);
|
|
1027
|
+
}
|
|
1028
|
+
} catch {
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
return result;
|
|
1032
|
+
}
|
|
1033
|
+
function resolvePackSchemaMetadata(input) {
|
|
1034
|
+
const result = /* @__PURE__ */ new Map();
|
|
1035
|
+
const { projectRoot, packs, packCacheDir } = input;
|
|
1036
|
+
if (!Array.isArray(packs)) {
|
|
1037
|
+
return result;
|
|
1038
|
+
}
|
|
1039
|
+
const effectiveCacheDir = packCacheDir ?? DEFAULT_PACK_CACHE_DIR;
|
|
1040
|
+
for (const pack of packs) {
|
|
1041
|
+
if (!pack || typeof pack !== "object" || !("id" in pack)) {
|
|
1042
|
+
continue;
|
|
1043
|
+
}
|
|
1044
|
+
const packId = String(pack.id);
|
|
1045
|
+
const manifestPath = resolveManifestPath(projectRoot, { ...pack, id: packId }, effectiveCacheDir);
|
|
1046
|
+
if (!manifestPath || !existsSync(manifestPath)) {
|
|
1047
|
+
continue;
|
|
1048
|
+
}
|
|
1049
|
+
try {
|
|
1050
|
+
const manifestContent = readFileSync(manifestPath, "utf8");
|
|
1051
|
+
const manifest = YAML2.parse(manifestContent);
|
|
1052
|
+
if (!manifest)
|
|
1053
|
+
continue;
|
|
1054
|
+
const configSchema = manifest.config_schema;
|
|
1055
|
+
if (typeof configSchema === "string" && configSchema.length > 0) {
|
|
1056
|
+
const packRoot = path3.dirname(manifestPath);
|
|
1057
|
+
const schemaAbsPath = path3.join(packRoot, configSchema);
|
|
1058
|
+
result.set(packId, { hasSchema: true, schemaPath: schemaAbsPath });
|
|
1059
|
+
} else {
|
|
1060
|
+
const configKey = manifest.config_key;
|
|
1061
|
+
if (typeof configKey === "string") {
|
|
1062
|
+
result.set(packId, { hasSchema: false });
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
} catch {
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
return result;
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
export {
|
|
1072
|
+
KERNEL_EVENT_KINDS,
|
|
1073
|
+
isTaskEventKind,
|
|
1074
|
+
isRunLifecycleEventKind,
|
|
1075
|
+
TOOL_TRACE_KINDS,
|
|
1076
|
+
UTF8_ENCODING,
|
|
1077
|
+
BASE64_ENCODING,
|
|
1078
|
+
SHA256_ALGORITHM,
|
|
1079
|
+
SHA256_HEX_REGEX,
|
|
1080
|
+
SHA256_INTEGRITY_PREFIX,
|
|
1081
|
+
WORKSPACE_FILE_NAME,
|
|
1082
|
+
PACKS_DIR_NAME,
|
|
1083
|
+
PACK_MANIFEST_FILE_NAME,
|
|
1084
|
+
PACKAGES_DIR_NAME,
|
|
1085
|
+
LUMENFLOW_SCOPE_NAME,
|
|
1086
|
+
LUMENFLOW_DIR_NAME,
|
|
1087
|
+
KERNEL_RUNTIME_ROOT_DIR_NAME,
|
|
1088
|
+
KERNEL_RUNTIME_TASKS_DIR_NAME,
|
|
1089
|
+
KERNEL_RUNTIME_EVENTS_DIR_NAME,
|
|
1090
|
+
KERNEL_RUNTIME_EVIDENCE_DIR_NAME,
|
|
1091
|
+
KERNEL_RUNTIME_EVENTS_FILE_NAME,
|
|
1092
|
+
KERNEL_RUNTIME_EVENTS_LOCK_FILE_NAME,
|
|
1093
|
+
RESERVED_FRAMEWORK_SCOPE_ROOT,
|
|
1094
|
+
RESERVED_FRAMEWORK_SCOPE_PREFIX,
|
|
1095
|
+
RESERVED_FRAMEWORK_SCOPE_GLOB,
|
|
1096
|
+
DEFAULT_WORKSPACE_CONFIG_HASH,
|
|
1097
|
+
DEFAULT_KERNEL_RUNTIME_VERSION,
|
|
1098
|
+
WORKSPACE_CONFIG_HASH_CONTEXT_KEYS,
|
|
1099
|
+
EXECUTION_METADATA_KEYS,
|
|
1100
|
+
KERNEL_POLICY_IDS,
|
|
1101
|
+
RUN_STATUSES,
|
|
1102
|
+
TOOL_HANDLER_KINDS,
|
|
1103
|
+
TOOL_ERROR_CODES,
|
|
1104
|
+
ToolScopeSchema,
|
|
1105
|
+
TaskSpecSchema,
|
|
1106
|
+
RunSchema,
|
|
1107
|
+
TaskStateSchema,
|
|
1108
|
+
WorkspaceControlPlaneConfigSchema,
|
|
1109
|
+
WorkspaceSpecSchema,
|
|
1110
|
+
validateWorkspaceRootKeys,
|
|
1111
|
+
KernelEventSchema,
|
|
1112
|
+
ToolTraceEntrySchema,
|
|
1113
|
+
ToolOutputSchema,
|
|
1114
|
+
ExecutionContextSchema,
|
|
1115
|
+
ToolCapabilitySchema,
|
|
1116
|
+
computeDeterministicPackHash,
|
|
1117
|
+
POLICY_TRIGGERS,
|
|
1118
|
+
PolicyEngine,
|
|
1119
|
+
isBroadWildcardScopePattern,
|
|
1120
|
+
validateDomainPackToolSafety,
|
|
1121
|
+
DomainPackManifestSchema,
|
|
1122
|
+
resolvePackToolEntryPath,
|
|
1123
|
+
validatePackImportBoundaries,
|
|
1124
|
+
PackLoader,
|
|
1125
|
+
resolvePackManifestPaths,
|
|
1126
|
+
resolvePackSchemaMetadata
|
|
1127
|
+
};
|