@lannguyensi/harness 0.6.0 → 0.8.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.
Files changed (139) hide show
  1. package/CHANGELOG.md +255 -0
  2. package/README.md +189 -148
  3. package/dist/cli/apply/apply.d.ts +13 -0
  4. package/dist/cli/apply/apply.js +59 -3
  5. package/dist/cli/apply/apply.js.map +1 -1
  6. package/dist/cli/apply/generate-codex-config.d.ts +6 -0
  7. package/dist/cli/apply/generate-codex-config.js +149 -0
  8. package/dist/cli/apply/generate-codex-config.js.map +1 -0
  9. package/dist/cli/apply/generate-settings.d.ts +15 -1
  10. package/dist/cli/apply/generate-settings.js +16 -1
  11. package/dist/cli/apply/generate-settings.js.map +1 -1
  12. package/dist/cli/apply/index.d.ts +2 -1
  13. package/dist/cli/apply/index.js +2 -1
  14. package/dist/cli/apply/index.js.map +1 -1
  15. package/dist/cli/approve/understanding.d.ts +39 -0
  16. package/dist/cli/approve/understanding.js +122 -0
  17. package/dist/cli/approve/understanding.js.map +1 -0
  18. package/dist/cli/describe.d.ts +1 -1
  19. package/dist/cli/describe.js +2 -0
  20. package/dist/cli/describe.js.map +1 -1
  21. package/dist/cli/doctor/codex.d.ts +34 -0
  22. package/dist/cli/doctor/codex.js +331 -0
  23. package/dist/cli/doctor/codex.js.map +1 -0
  24. package/dist/cli/doctor/format.js +29 -1
  25. package/dist/cli/doctor/format.js.map +1 -1
  26. package/dist/cli/doctor/index.d.ts +13 -1
  27. package/dist/cli/doctor/index.js +49 -1
  28. package/dist/cli/doctor/index.js.map +1 -1
  29. package/dist/cli/doctor/types.d.ts +35 -1
  30. package/dist/cli/doctor/types.js +12 -1
  31. package/dist/cli/doctor/types.js.map +1 -1
  32. package/dist/cli/explain.d.ts +10 -1
  33. package/dist/cli/explain.js +44 -18
  34. package/dist/cli/explain.js.map +1 -1
  35. package/dist/cli/index.js +315 -8
  36. package/dist/cli/index.js.map +1 -1
  37. package/dist/cli/list.d.ts +1 -1
  38. package/dist/cli/list.js +17 -0
  39. package/dist/cli/list.js.map +1 -1
  40. package/dist/cli/pack/add.d.ts +13 -0
  41. package/dist/cli/pack/add.js +71 -0
  42. package/dist/cli/pack/add.js.map +1 -0
  43. package/dist/cli/pack/hook-codex-pre-tool-use.d.ts +30 -0
  44. package/dist/cli/pack/hook-codex-pre-tool-use.js +149 -0
  45. package/dist/cli/pack/hook-codex-pre-tool-use.js.map +1 -0
  46. package/dist/cli/pack/hook-codex-stop.d.ts +31 -0
  47. package/dist/cli/pack/hook-codex-stop.js +332 -0
  48. package/dist/cli/pack/hook-codex-stop.js.map +1 -0
  49. package/dist/cli/pack/hook-codex-user-prompt-submit.d.ts +18 -0
  50. package/dist/cli/pack/hook-codex-user-prompt-submit.js +92 -0
  51. package/dist/cli/pack/hook-codex-user-prompt-submit.js.map +1 -0
  52. package/dist/cli/pack/hook-pre-tool-use.d.ts +32 -0
  53. package/dist/cli/pack/hook-pre-tool-use.js +181 -0
  54. package/dist/cli/pack/hook-pre-tool-use.js.map +1 -0
  55. package/dist/cli/pack/index.d.ts +4 -0
  56. package/dist/cli/pack/index.js +5 -0
  57. package/dist/cli/pack/index.js.map +1 -0
  58. package/dist/cli/pack/list.d.ts +10 -0
  59. package/dist/cli/pack/list.js +43 -0
  60. package/dist/cli/pack/list.js.map +1 -0
  61. package/dist/cli/pack/mutate.d.ts +14 -0
  62. package/dist/cli/pack/mutate.js +76 -0
  63. package/dist/cli/pack/mutate.js.map +1 -0
  64. package/dist/cli/pack/remove.d.ts +15 -0
  65. package/dist/cli/pack/remove.js +153 -0
  66. package/dist/cli/pack/remove.js.map +1 -0
  67. package/dist/cli/session-export/index.d.ts +46 -0
  68. package/dist/cli/session-export/index.js +169 -0
  69. package/dist/cli/session-export/index.js.map +1 -0
  70. package/dist/cli/session-export/redact.d.ts +22 -0
  71. package/dist/cli/session-export/redact.js +47 -0
  72. package/dist/cli/session-export/redact.js.map +1 -0
  73. package/dist/cli/session-export/transcript.d.ts +24 -0
  74. package/dist/cli/session-export/transcript.js +162 -0
  75. package/dist/cli/session-export/transcript.js.map +1 -0
  76. package/dist/cli/validate/checks.js +32 -0
  77. package/dist/cli/validate/checks.js.map +1 -1
  78. package/dist/policies/ledger-client.js +2 -1
  79. package/dist/policies/ledger-client.js.map +1 -1
  80. package/dist/policy-packs/builtin/permission-profiles.d.ts +11 -0
  81. package/dist/policy-packs/builtin/permission-profiles.js +74 -0
  82. package/dist/policy-packs/builtin/permission-profiles.js.map +1 -0
  83. package/dist/policy-packs/builtin/understanding-before-execution-runtime.d.ts +56 -0
  84. package/dist/policy-packs/builtin/understanding-before-execution-runtime.js +186 -0
  85. package/dist/policy-packs/builtin/understanding-before-execution-runtime.js.map +1 -0
  86. package/dist/policy-packs/builtin/understanding-before-execution.d.ts +15 -0
  87. package/dist/policy-packs/builtin/understanding-before-execution.js +254 -0
  88. package/dist/policy-packs/builtin/understanding-before-execution.js.map +1 -0
  89. package/dist/policy-packs/expand.d.ts +4 -0
  90. package/dist/policy-packs/expand.js +90 -0
  91. package/dist/policy-packs/expand.js.map +1 -0
  92. package/dist/policy-packs/index.d.ts +5 -0
  93. package/dist/policy-packs/index.js +5 -0
  94. package/dist/policy-packs/index.js.map +1 -0
  95. package/dist/policy-packs/permission-translator.d.ts +9 -0
  96. package/dist/policy-packs/permission-translator.js +76 -0
  97. package/dist/policy-packs/permission-translator.js.map +1 -0
  98. package/dist/policy-packs/registry.d.ts +11 -0
  99. package/dist/policy-packs/registry.js +20 -0
  100. package/dist/policy-packs/registry.js.map +1 -0
  101. package/dist/policy-packs/runtime.d.ts +8 -0
  102. package/dist/policy-packs/runtime.js +30 -0
  103. package/dist/policy-packs/runtime.js.map +1 -0
  104. package/dist/policy-packs/source.d.ts +6 -0
  105. package/dist/policy-packs/source.js +10 -0
  106. package/dist/policy-packs/source.js.map +1 -0
  107. package/dist/policy-packs/types.d.ts +41 -0
  108. package/dist/policy-packs/types.js +11 -0
  109. package/dist/policy-packs/types.js.map +1 -0
  110. package/dist/probes/mcp.js +2 -1
  111. package/dist/probes/mcp.js.map +1 -1
  112. package/dist/runtime/index.d.ts +1 -0
  113. package/dist/runtime/index.js +1 -0
  114. package/dist/runtime/index.js.map +1 -1
  115. package/dist/runtime/ledger-add.d.ts +16 -0
  116. package/dist/runtime/ledger-add.js +139 -0
  117. package/dist/runtime/ledger-add.js.map +1 -0
  118. package/dist/runtime/ledger-record.js +2 -1
  119. package/dist/runtime/ledger-record.js.map +1 -1
  120. package/dist/schema/audit.d.ts +71 -0
  121. package/dist/schema/audit.js +32 -0
  122. package/dist/schema/audit.js.map +1 -0
  123. package/dist/schema/index.d.ts +1893 -10
  124. package/dist/schema/index.js +27 -0
  125. package/dist/schema/index.js.map +1 -1
  126. package/dist/schema/permission-profiles.d.ts +2161 -0
  127. package/dist/schema/permission-profiles.js +60 -0
  128. package/dist/schema/permission-profiles.js.map +1 -0
  129. package/dist/schema/policy-packs.d.ts +52 -0
  130. package/dist/schema/policy-packs.js +35 -0
  131. package/dist/schema/policy-packs.js.map +1 -0
  132. package/dist/schema/tools.d.ts +8 -8
  133. package/dist/schema/workflows.d.ts +519 -0
  134. package/dist/schema/workflows.js +81 -0
  135. package/dist/schema/workflows.js.map +1 -0
  136. package/dist/version.d.ts +1 -0
  137. package/dist/version.js +3 -0
  138. package/dist/version.js.map +1 -0
  139. package/package.json +1 -1
@@ -0,0 +1,254 @@
1
+ // Builtin Policy Pack: `understanding-before-execution`.
2
+ //
3
+ // Bundles three hook contributions for Claude Code (UserPromptSubmit,
4
+ // Stop, PreToolUse), plus a per-mode instructions.md that documents what
5
+ // the pack is doing for human auditors. The actual prompt that the agent
6
+ // sees at UserPromptSubmit time is owned by `@lannguyensi/understanding-gate`
7
+ // (specifically `src/prompts/{full,fast-confirm,grill-me}.ts`); harness's
8
+ // instructions.md is the operator-facing summary, not the agent-injected
9
+ // text. Drift on instructions.md is therefore meaningful (someone edited
10
+ // the audit copy), distinct from drift on the package's own templates
11
+ // (which the package's own drift detection would handle on a future
12
+ // `understanding-gate init` reinstall).
13
+ import { profileToSettingsPermissions } from "../permission-translator.js";
14
+ import { DEFAULT_RUNTIME } from "../runtime.js";
15
+ import { isKnownProfileName, resolveProfile, KNOWN_PROFILE_NAMES, } from "./permission-profiles.js";
16
+ export const PACK_NAME = "understanding-before-execution";
17
+ const MODES = ["fast_confirm", "grill_me", "strict"];
18
+ export const DEFAULT_MODE = "grill_me";
19
+ const HOOK_NAME_PREFIX = `policy-pack:${PACK_NAME}`;
20
+ // Per-runtime hook surface. Claude Code keys on tool name (Edit|Write|Bash);
21
+ // Codex's write surface is `apply_patch` + `Bash`/`shell` (the task's
22
+ // in-scope list). The hook contract Codex feeds to the adapter is the
23
+ // same generic envelope harness publishes: `{ session_id, tool_name,
24
+ // raw_input, event }` on stdin, `{ decision }` on stdout, exit 2 on
25
+ // block. See dogfood/phase6-6/README.md for the wire format.
26
+ const PRE_TOOL_USE_MATCH_CLAUDE = "Edit|Write|Bash";
27
+ const PRE_TOOL_USE_MATCH_CODEX = "apply_patch|Bash|shell";
28
+ // UserPromptSubmit + Stop hooks point at `@lannguyensi/understanding-gate`
29
+ // bare bin names (npm i -g). The harness validator's checkHooks skips
30
+ // PATH lookup for non-rooted commands by design, so missing-bin shows
31
+ // up at runtime, not at lint. `harness doctor` (Phase 6 #4 follow-up)
32
+ // will add the presence check.
33
+ const BIN_USER_PROMPT_SUBMIT_CLAUDE = "understanding-gate-claude-hook";
34
+ const BIN_STOP_CLAUDE = "understanding-gate-claude-stop";
35
+ // PreToolUse blocker is the harness CLI itself (Phase 6 #4): it consults
36
+ // BOTH the evidence-ledger tag (canonical for harnessed sessions) AND
37
+ // the persisted JSON report under `.understanding-gate/reports/`
38
+ // (fallback for sessions without grounding-mcp wired). The npm package's
39
+ // own bin remains available for solo users; the harness blocker is
40
+ // strictly more powerful.
41
+ const PRE_TOOL_USE_COMMAND_CLAUDE = "harness pack hook pre-tool-use";
42
+ // Codex variants. The package `@lannguyensi/understanding-gate` does
43
+ // not yet ship Codex bins, so harness owns the adapter:
44
+ //
45
+ // - UserPromptSubmit-equivalent injector (Phase 6 #6).
46
+ // - Stop-equivalent capture into `.understanding-gate/reports/`
47
+ // (Phase 6 #6 follow-up).
48
+ // - PreToolUse blocker on apply_patch/Bash/shell (Phase 6 #6).
49
+ //
50
+ // Cross-runtime sessions can still approve from a Claude Code report:
51
+ // the ledger tag is the canonical source for harnessed sessions,
52
+ // independent of which runtime captured the report. The persisted-
53
+ // report directory is shared between runtimes, so a Codex stop that
54
+ // writes a report is approvable via `harness approve understanding`
55
+ // regardless of which runtime invokes the next tool call.
56
+ const COMMAND_USER_PROMPT_SUBMIT_CODEX = "harness pack hook codex-user-prompt-submit";
57
+ const COMMAND_STOP_CODEX = "harness pack hook codex-stop";
58
+ const COMMAND_PRE_TOOL_USE_CODEX = "harness pack hook codex-pre-tool-use";
59
+ export function isMode(value) {
60
+ return typeof value === "string" && MODES.includes(value);
61
+ }
62
+ export function resolveMode(pack) {
63
+ const raw = pack.config["mode"];
64
+ if (raw === undefined)
65
+ return { mode: DEFAULT_MODE, warning: null };
66
+ if (isMode(raw))
67
+ return { mode: raw, warning: null };
68
+ const warning = `policy_packs[${pack.name}].config.mode: unrecognised value ${JSON.stringify(raw)}, falling back to "${DEFAULT_MODE}". Allowed: ${MODES.join(", ")}.`;
69
+ return { mode: DEFAULT_MODE, warning };
70
+ }
71
+ function buildHooks(runtime) {
72
+ // Per-mode hook commands are identical (the mode is passed via the
73
+ // package's UNDERSTANDING_GATE_MODE env var, set elsewhere — out of
74
+ // scope for Phase 6 #2). What changes per mode is the instructions.md
75
+ // content + the actual injected prompt (owned by the npm package).
76
+ if (runtime === "codex") {
77
+ return [
78
+ {
79
+ name: `${HOOK_NAME_PREFIX}:codex:user-prompt-submit`,
80
+ event: "UserPromptSubmit",
81
+ command: COMMAND_USER_PROMPT_SUBMIT_CODEX,
82
+ blocking: false,
83
+ budget_ms: 5000,
84
+ description: "Codex adapter: inject the Understanding-Gate instruction template before the agent acts. Phase 6 #6.",
85
+ },
86
+ {
87
+ name: `${HOOK_NAME_PREFIX}:codex:stop`,
88
+ event: "Stop",
89
+ command: COMMAND_STOP_CODEX,
90
+ blocking: false,
91
+ budget_ms: 5000,
92
+ description: "Codex adapter: capture the agent's Understanding Report into .understanding-gate/reports/ as approvalStatus:pending. Phase 6 #6 follow-up.",
93
+ },
94
+ {
95
+ name: `${HOOK_NAME_PREFIX}:codex:pre-tool-use`,
96
+ event: "PreToolUse",
97
+ match: PRE_TOOL_USE_MATCH_CODEX,
98
+ command: COMMAND_PRE_TOOL_USE_CODEX,
99
+ blocking: "hard",
100
+ budget_ms: 5000,
101
+ description: "Codex adapter: block apply_patch/Bash/shell until an approved Understanding Report exists for the session. Consults both the evidence-ledger tag and the persisted JSON report.",
102
+ },
103
+ ];
104
+ }
105
+ return [
106
+ {
107
+ name: `${HOOK_NAME_PREFIX}:user-prompt-submit`,
108
+ event: "UserPromptSubmit",
109
+ command: BIN_USER_PROMPT_SUBMIT_CLAUDE,
110
+ blocking: false,
111
+ budget_ms: 5000,
112
+ description: "Inject the Understanding-Gate instruction template before the agent acts. Source: @lannguyensi/understanding-gate.",
113
+ },
114
+ {
115
+ name: `${HOOK_NAME_PREFIX}:stop`,
116
+ event: "Stop",
117
+ command: BIN_STOP_CLAUDE,
118
+ blocking: false,
119
+ budget_ms: 5000,
120
+ description: "Capture the agent's Understanding Report into .understanding-gate/reports/. Source: @lannguyensi/understanding-gate.",
121
+ },
122
+ {
123
+ name: `${HOOK_NAME_PREFIX}:pre-tool-use`,
124
+ event: "PreToolUse",
125
+ match: PRE_TOOL_USE_MATCH_CLAUDE,
126
+ command: PRE_TOOL_USE_COMMAND_CLAUDE,
127
+ blocking: "hard",
128
+ budget_ms: 5000,
129
+ description: "Block Edit/Write/Bash until an approved Understanding Report exists for the session. Consults both the evidence-ledger tag (understanding-approved:${SESSION_ID}) and the persisted JSON report.",
130
+ },
131
+ ];
132
+ }
133
+ function modeFriction(mode) {
134
+ switch (mode) {
135
+ case "fast_confirm":
136
+ return "low friction. The gate fires on prompts the classifier flags as execution-relevant. Brief Understanding Report; one-line approval.";
137
+ case "grill_me":
138
+ return "medium friction (default). The gate fires on any prompt the agent might respond to with a write. Full Understanding Report (assumptions, openQuestions, outOfScope, risks, verificationPlan). Push-back is encouraged.";
139
+ case "strict":
140
+ return "high friction. The gate fires on every prompt. Report MUST include verificationPlan and outOfScope; requiresHumanApproval is forced to true.";
141
+ }
142
+ }
143
+ function buildInstructions(pack, mode, runtime) {
144
+ const description = pack.description?.trim() ?? "";
145
+ const isCodex = runtime === "codex";
146
+ const injectorCmd = isCodex ? COMMAND_USER_PROMPT_SUBMIT_CODEX : BIN_USER_PROMPT_SUBMIT_CLAUDE;
147
+ const stopCmd = isCodex ? COMMAND_STOP_CODEX : BIN_STOP_CLAUDE;
148
+ const blockerCmd = isCodex ? COMMAND_PRE_TOOL_USE_CODEX : PRE_TOOL_USE_COMMAND_CLAUDE;
149
+ const blockerMatch = isCodex ? PRE_TOOL_USE_MATCH_CODEX : PRE_TOOL_USE_MATCH_CLAUDE;
150
+ const settingsArtefact = isCodex
151
+ ? "`harness.generated/codex/config.toml`"
152
+ : "harness-managed `settings.json`";
153
+ const stopBullet = `2. \`Stop\` capture (\`${stopCmd}\`): persists the emitted Understanding
154
+ Report under \`.understanding-gate/reports/\` for audit and downstream
155
+ approval consumption.
156
+ `;
157
+ const blockerOrdinal = "3";
158
+ return `# Policy Pack: ${PACK_NAME}
159
+
160
+ > Operator audit copy. The agent-facing prompt is injected at runtime by
161
+ > the \`${injectorCmd}\` UserPromptSubmit hook; that text lives
162
+ > in the \`@lannguyensi/understanding-gate\` package, not here. This file
163
+ > records WHAT the pack is doing and HOW it is configured so that
164
+ > \`harness diff --since-apply\` can flag operator-facing drift.
165
+
166
+ ## Runtime
167
+
168
+ ${runtime}
169
+
170
+ ## Mode
171
+
172
+ ${mode}
173
+
174
+ ${modeFriction(mode)}
175
+
176
+ ## Effect
177
+
178
+ While this pack is enabled, hooks are wired into the ${settingsArtefact}:
179
+
180
+ 1. \`UserPromptSubmit\` injector (\`${injectorCmd}\`): inserts the
181
+ Understanding-Gate instruction template into the agent's first response.
182
+ ${stopBullet}${blockerOrdinal}. \`PreToolUse\` blocker (\`${blockerCmd}\`, blocking: hard)
183
+ on \`${blockerMatch}\`: refuses the tool call until an approved
184
+ report exists for the session. Consults BOTH the evidence-ledger
185
+ tag (\`understanding-approved:\${SESSION_ID}\`, canonical for
186
+ harnessed sessions) AND the persisted JSON report under
187
+ \`.understanding-gate/reports/\` (fallback for sessions without
188
+ grounding-mcp wired). Either source approves.
189
+
190
+ ## Approval
191
+
192
+ The standalone blocker shipped in \`@lannguyensi/understanding-gate@>=0.2.0\`
193
+ checks the persisted JSON report's \`approvalStatus\`. Phase 6 #4 will
194
+ add a harness-side blocker that ALSO consults the evidence-ledger tag
195
+ \`understanding-approved:\${SESSION_ID}\` (canonical for harnessed
196
+ sessions), and \`harness approve understanding\` will round-trip both.
197
+ Until then, approval flows through the package's own CLI.
198
+
199
+ ## Pack metadata
200
+ ${description ? `\n> ${description.replace(/\n/g, "\n> ")}\n` : ""}
201
+ - Source: \`builtin\`
202
+ - Pack: \`${PACK_NAME}\`
203
+ - Mode: \`${mode}\`
204
+ - Runtime: \`${runtime}\`
205
+
206
+ ## See also
207
+
208
+ - \`docs/policy-packs/understanding-before-execution.md\` (full reference)
209
+ - \`docs/ROADMAP.md\` Phase 6 sub-task decomposition
210
+ `;
211
+ }
212
+ function resolvePermissionProfile(pack) {
213
+ const raw = pack.config["permission_profile"];
214
+ if (raw === undefined)
215
+ return { permissions: null, warning: null };
216
+ if (typeof raw !== "string") {
217
+ return {
218
+ permissions: null,
219
+ warning: `policy_packs[${pack.name}].config.permission_profile: expected a string, got ${typeof raw}; skipping permission contribution.`,
220
+ };
221
+ }
222
+ if (!isKnownProfileName(raw)) {
223
+ return {
224
+ permissions: null,
225
+ warning: `policy_packs[${pack.name}].config.permission_profile: unrecognised profile ${JSON.stringify(raw)}. Allowed: ${KNOWN_PROFILE_NAMES.join(", ")}. Skipping permission contribution.`,
226
+ };
227
+ }
228
+ const profile = resolveProfile(raw);
229
+ if (!profile)
230
+ return { permissions: null, warning: null };
231
+ return { permissions: profileToSettingsPermissions(profile), warning: null };
232
+ }
233
+ export function resolve(pack, runtime = DEFAULT_RUNTIME) {
234
+ const { mode, warning } = resolveMode(pack);
235
+ const hooks = buildHooks(runtime);
236
+ const instructionsContent = buildInstructions(pack, mode, runtime);
237
+ const files = [
238
+ {
239
+ relativePath: `policy-packs/${PACK_NAME}/instructions.md`,
240
+ content: instructionsContent,
241
+ },
242
+ ];
243
+ const warnings = [];
244
+ if (warning)
245
+ warnings.push(warning);
246
+ const profileResult = resolvePermissionProfile(pack);
247
+ if (profileResult.warning)
248
+ warnings.push(profileResult.warning);
249
+ const contribution = { hooks, files };
250
+ if (profileResult.permissions)
251
+ contribution.permissions = profileResult.permissions;
252
+ return { contribution, warnings };
253
+ }
254
+ //# sourceMappingURL=understanding-before-execution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"understanding-before-execution.js","sourceRoot":"","sources":["../../../src/policy-packs/builtin/understanding-before-execution.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Manifest } from "../schema/index.js";
2
+ import { type Runtime } from "./runtime.js";
3
+ import type { PackExpansionResult } from "./types.js";
4
+ export declare function expandPolicyPacks(manifest: Manifest, runtime?: Runtime): PackExpansionResult;
@@ -0,0 +1,90 @@
1
+ // Apply-time expansion of `policy_packs[]` entries.
2
+ //
3
+ // Walks the manifest's enabled packs, parses each `source:` string,
4
+ // resolves builtin packs through the registry, and aggregates their
5
+ // contributions (hooks + files). Unrecognised sources or unknown builtin
6
+ // names produce non-fatal warnings here; `harness validate` is the
7
+ // place that turns the same conditions into hard errors so the user
8
+ // sees them at lint time, not silently at apply time.
9
+ //
10
+ // Hook-name collision handling: pack hooks are namespaced
11
+ // (`policy-pack:<name>:<role>`) by the builtin definitions, so a user
12
+ // hook with a colliding name is the user's mistake. We surface that as
13
+ // a warning here rather than blowing up; the schema's duplicate-name
14
+ // superRefine will reject it on the augmented manifest's downstream
15
+ // re-parse if a caller re-validates.
16
+ import { resolveBuiltin } from "./registry.js";
17
+ import { DEFAULT_RUNTIME } from "./runtime.js";
18
+ import { parsePackSource } from "./source.js";
19
+ export function expandPolicyPacks(manifest, runtime = DEFAULT_RUNTIME) {
20
+ const out = { hooks: [], files: [], warnings: [], skipped: [] };
21
+ if (manifest.policy_packs.length === 0)
22
+ return out;
23
+ const existingHookNames = new Set(manifest.hooks.map((h) => h.name));
24
+ const seenPackHookNames = new Set();
25
+ const allowSet = new Set();
26
+ const askSet = new Set();
27
+ const denySet = new Set();
28
+ let anyPermissions = false;
29
+ for (const pack of manifest.policy_packs) {
30
+ if (!pack.enabled) {
31
+ out.skipped.push(pack.name);
32
+ continue;
33
+ }
34
+ const sourceParsed = parsePackSource(pack.source);
35
+ if (sourceParsed.kind === "unknown") {
36
+ out.warnings.push(`policy_packs[${pack.name}]: source ${JSON.stringify(pack.source)} is not recognised in v1 (only "builtin" resolves); skipping.`);
37
+ continue;
38
+ }
39
+ const resolved = resolveBuiltin(pack, runtime);
40
+ if (!resolved) {
41
+ out.warnings.push(`policy_packs[${pack.name}]: not a known builtin pack; skipping. See docs/policy-packs/ for supported names.`);
42
+ continue;
43
+ }
44
+ out.warnings.push(...resolved.warnings);
45
+ for (const hook of resolved.contribution.hooks) {
46
+ if (existingHookNames.has(hook.name)) {
47
+ out.warnings.push(`policy_packs[${pack.name}]: hook name "${hook.name}" collides with a manifest hooks[] entry; pack contribution dropped to avoid a duplicate-name failure.`);
48
+ continue;
49
+ }
50
+ if (seenPackHookNames.has(hook.name)) {
51
+ out.warnings.push(`policy_packs[${pack.name}]: hook name "${hook.name}" was already contributed by an earlier pack; second copy dropped.`);
52
+ continue;
53
+ }
54
+ seenPackHookNames.add(hook.name);
55
+ out.hooks.push(hook);
56
+ }
57
+ out.files.push(...resolved.contribution.files);
58
+ if (resolved.contribution.permissions) {
59
+ anyPermissions = true;
60
+ for (const p of resolved.contribution.permissions.allow)
61
+ allowSet.add(p);
62
+ for (const p of resolved.contribution.permissions.ask)
63
+ askSet.add(p);
64
+ for (const p of resolved.contribution.permissions.deny)
65
+ denySet.add(p);
66
+ }
67
+ }
68
+ if (anyPermissions) {
69
+ // Deny wins over ask wins over allow at merge time: a stricter
70
+ // intent from any pack should not be silently relaxed by a more
71
+ // permissive sibling. Concretely, a pattern present in deny is
72
+ // stripped from ask + allow; a pattern present in ask is stripped
73
+ // from allow.
74
+ for (const p of denySet) {
75
+ askSet.delete(p);
76
+ allowSet.delete(p);
77
+ }
78
+ for (const p of askSet) {
79
+ allowSet.delete(p);
80
+ }
81
+ const permissions = {
82
+ allow: [...allowSet].sort(),
83
+ ask: [...askSet].sort(),
84
+ deny: [...denySet].sort(),
85
+ };
86
+ out.permissions = permissions;
87
+ }
88
+ return out;
89
+ }
90
+ //# sourceMappingURL=expand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expand.js","sourceRoot":"","sources":["../../src/policy-packs/expand.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { expandPolicyPacks } from "./expand.js";
2
+ export { KNOWN_BUILTIN_PACKS, isBuiltinPackName, resolveBuiltin, type BuiltinPackName, type ResolveBuiltinResult, } from "./registry.js";
3
+ export { KNOWN_RUNTIMES, DEFAULT_RUNTIME, isRuntime, parseRuntime, type Runtime, } from "./runtime.js";
4
+ export { parsePackSource, type PackSourceKind, type PackSourceParseResult } from "./source.js";
5
+ export type { PackContribution, PackContributionFile, PackExpansionResult, } from "./types.js";
@@ -0,0 +1,5 @@
1
+ export { expandPolicyPacks } from "./expand.js";
2
+ export { KNOWN_BUILTIN_PACKS, isBuiltinPackName, resolveBuiltin, } from "./registry.js";
3
+ export { KNOWN_RUNTIMES, DEFAULT_RUNTIME, isRuntime, parseRuntime, } from "./runtime.js";
4
+ export { parsePackSource } from "./source.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/policy-packs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,GAGf,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,cAAc,EACd,eAAe,EACf,SAAS,EACT,YAAY,GAEb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAmD,MAAM,aAAa,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { PermissionActionKey, PermissionProfile } from "../schema/permission-profiles.js";
2
+ export interface SettingsPermissions {
3
+ allow: string[];
4
+ ask: string[];
5
+ deny: string[];
6
+ }
7
+ export declare function profileToSettingsPermissions(profile: PermissionProfile): SettingsPermissions;
8
+ /** Test seam — exposed for unit coverage of the action→pattern map. */
9
+ export declare function _internalPatternMap(): Record<PermissionActionKey, string[]>;
@@ -0,0 +1,76 @@
1
+ // Phase 6 #5 — translate abstract permission profile actions into
2
+ // Claude Code's settings.json permissions vocabulary.
3
+ //
4
+ // Mapping rules:
5
+ //
6
+ // Action key → tool patterns (matcher style)
7
+ // ---------- ----------------------------------------------- ----------------
8
+ // read ["Read", "Glob", "Grep"] bare tool names
9
+ // edit ["Edit", "Write", "MultiEdit"] bare tool names
10
+ // bash ["Bash"] bare tool name
11
+ // commit ["Bash(git commit*)"] Bash-prefix syntax
12
+ // push ["Bash(git push*)"] Bash-prefix syntax
13
+ // pr ["mcp__agent-tasks__pull_requests_create", MCP + bare gh
14
+ // "Bash(gh pr create*)"]
15
+ // deploy ["Bash(kubectl*)", "Bash(terraform destroy*)", Bash-prefix syntax
16
+ // "Bash(npm publish*)"]
17
+ //
18
+ // `allow` enum mapping:
19
+ //
20
+ // "true" / true → permissions.allow
21
+ // "false" / false → permissions.deny
22
+ // "ask" → permissions.ask
23
+ // "limited" → permissions.ask (v1 fallback — distinct
24
+ // semantics deferred to a
25
+ // Phase 6 #5 follow-up)
26
+ // "ask_or_deny" → permissions.ask (same fallback rationale)
27
+ const ACTION_TO_PATTERNS = {
28
+ read: ["Read", "Glob", "Grep"],
29
+ edit: ["Edit", "Write", "MultiEdit"],
30
+ bash: ["Bash"],
31
+ commit: ["Bash(git commit*)"],
32
+ push: ["Bash(git push*)"],
33
+ pr: ["mcp__agent-tasks__pull_requests_create", "Bash(gh pr create*)"],
34
+ deploy: ["Bash(kubectl*)", "Bash(terraform destroy*)", "Bash(npm publish*)"],
35
+ };
36
+ function bucketForAllow(value) {
37
+ switch (value) {
38
+ case "true":
39
+ return "allow";
40
+ case "false":
41
+ return "deny";
42
+ case "ask":
43
+ case "limited":
44
+ case "ask_or_deny":
45
+ return "ask";
46
+ }
47
+ }
48
+ export function profileToSettingsPermissions(profile) {
49
+ const allow = new Set();
50
+ const ask = new Set();
51
+ const deny = new Set();
52
+ const buckets = {
53
+ allow,
54
+ ask,
55
+ deny,
56
+ };
57
+ for (const key of Object.keys(profile.actions)) {
58
+ const rule = profile.actions[key];
59
+ if (!rule)
60
+ continue;
61
+ const target = bucketForAllow(rule.allow);
62
+ for (const pattern of ACTION_TO_PATTERNS[key]) {
63
+ buckets[target].add(pattern);
64
+ }
65
+ }
66
+ return {
67
+ allow: [...allow].sort(),
68
+ ask: [...ask].sort(),
69
+ deny: [...deny].sort(),
70
+ };
71
+ }
72
+ /** Test seam — exposed for unit coverage of the action→pattern map. */
73
+ export function _internalPatternMap() {
74
+ return ACTION_TO_PATTERNS;
75
+ }
76
+ //# sourceMappingURL=permission-translator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permission-translator.js","sourceRoot":"","sources":["../../src/policy-packs/permission-translator.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,sDAAsD;AACtD,EAAE;AACF,iBAAiB;AACjB,EAAE;AACF,mFAAmF;AACnF,oFAAoF;AACpF,mFAAmF;AACnF,mFAAmF;AACnF,kFAAkF;AAClF,sFAAsF;AACtF,sFAAsF;AACtF,iFAAiF;AACjF,2CAA2C;AAC3C,sFAAsF;AACtF,0CAA0C;AAC1C,EAAE;AACF,wBAAwB;AACxB,EAAE;AACF,yCAAyC;AACzC,wCAAwC;AACxC,uCAAuC;AACvC,gEAAgE;AAChE,iEAAiE;AACjE,+DAA+D;AAC/D,kEAAkE;AAclE,MAAM,kBAAkB,GAA0C;IAChE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IAC9B,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,WAAW,CAAC;IACpC,IAAI,EAAE,CAAC,MAAM,CAAC;IACd,MAAM,EAAE,CAAC,mBAAmB,CAAC;IAC7B,IAAI,EAAE,CAAC,iBAAiB,CAAC;IACzB,EAAE,EAAE,CAAC,wCAAwC,EAAE,qBAAqB,CAAC;IACrE,MAAM,EAAE,CAAC,gBAAgB,EAAE,0BAA0B,EAAE,oBAAoB,CAAC;CAC7E,CAAC;AAEF,SAAS,cAAc,CAAC,KAAsB;IAC5C,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,MAAM;YACT,OAAO,OAAO,CAAC;QACjB,KAAK,OAAO;YACV,OAAO,MAAM,CAAC;QAChB,KAAK,KAAK,CAAC;QACX,KAAK,SAAS,CAAC;QACf,KAAK,aAAa;YAChB,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,OAA0B;IAE1B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,MAAM,OAAO,GAAmD;QAC9D,KAAK;QACL,GAAG;QACH,IAAI;KACL,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAA0B,EAAE,CAAC;QACxE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1C,KAAK,MAAM,OAAO,IAAI,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9C,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE;QACxB,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,EAAE;QACpB,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE;KACvB,CAAC;AACJ,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,mBAAmB;IACjC,OAAO,kBAAkB,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { PolicyPack } from "../schema/index.js";
2
+ import { type Runtime } from "./runtime.js";
3
+ import type { PackContribution } from "./types.js";
4
+ export declare const KNOWN_BUILTIN_PACKS: readonly ["understanding-before-execution"];
5
+ export type BuiltinPackName = (typeof KNOWN_BUILTIN_PACKS)[number];
6
+ export declare function isBuiltinPackName(name: string): name is BuiltinPackName;
7
+ export interface ResolveBuiltinResult {
8
+ contribution: PackContribution;
9
+ warnings: string[];
10
+ }
11
+ export declare function resolveBuiltin(pack: PolicyPack, runtime?: Runtime): ResolveBuiltinResult | null;
@@ -0,0 +1,20 @@
1
+ // Registry of builtin policy-pack names.
2
+ //
3
+ // Phase 6 #2 ships exactly one builtin: `understanding-before-execution`.
4
+ // Future builtins are added here. Non-builtin sources (path/npm/git) are
5
+ // out of scope for v1; their resolution lands in a later sub-task.
6
+ import { PACK_NAME as UNDERSTANDING_BEFORE_EXECUTION, resolve as resolveUnderstandingBeforeExecution, } from "./builtin/understanding-before-execution.js";
7
+ import { DEFAULT_RUNTIME } from "./runtime.js";
8
+ export const KNOWN_BUILTIN_PACKS = [UNDERSTANDING_BEFORE_EXECUTION];
9
+ export function isBuiltinPackName(name) {
10
+ return KNOWN_BUILTIN_PACKS.includes(name);
11
+ }
12
+ export function resolveBuiltin(pack, runtime = DEFAULT_RUNTIME) {
13
+ if (!isBuiltinPackName(pack.name))
14
+ return null;
15
+ switch (pack.name) {
16
+ case UNDERSTANDING_BEFORE_EXECUTION:
17
+ return resolveUnderstandingBeforeExecution(pack, runtime);
18
+ }
19
+ }
20
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/policy-packs/registry.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,0EAA0E;AAC1E,yEAAyE;AACzE,mEAAmE;AAGnE,OAAO,EACL,SAAS,IAAI,8BAA8B,EAC3C,OAAO,IAAI,mCAAmC,GAC/C,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAAE,eAAe,EAAgB,MAAM,cAAc,CAAC;AAG7D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,8BAA8B,CAAU,CAAC;AAG7E,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAQ,mBAAyC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACnE,CAAC;AAOD,MAAM,UAAU,cAAc,CAC5B,IAAgB,EAChB,UAAmB,eAAe;IAElC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,QAAQ,IAAI,CAAC,IAAuB,EAAE,CAAC;QACrC,KAAK,8BAA8B;YACjC,OAAO,mCAAmC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ export declare const KNOWN_RUNTIMES: readonly ["claude-code", "codex"];
2
+ export type Runtime = (typeof KNOWN_RUNTIMES)[number];
3
+ export declare const DEFAULT_RUNTIME: Runtime;
4
+ export declare function isRuntime(value: unknown): value is Runtime;
5
+ export declare function parseRuntime(raw: string | undefined): {
6
+ runtime: Runtime;
7
+ warning: string | null;
8
+ };
@@ -0,0 +1,30 @@
1
+ // Phase 6 #6 — runtime target identifier threaded through policy-pack
2
+ // expansion. Selects which adapter shape a pack emits.
3
+ //
4
+ // `claude-code` (default): hook commands point at the `@lannguyensi/understanding-gate`
5
+ // claude-code bins and the harness PreToolUse blocker. Output of
6
+ // `harness apply` is the Claude Code `settings.json` shape under
7
+ // `harness.generated/settings.json`.
8
+ //
9
+ // `codex`: hook commands point at the harness-shipped Codex adapter
10
+ // subcommands (`harness pack hook codex-*`). Output of `harness apply`
11
+ // is a Codex-flavoured config artefact under
12
+ // `harness.generated/codex/`. Phase 6 #6 ships block + allow for the
13
+ // understanding-before-execution pack; cross-pack and additional
14
+ // runtimes are out of v1 scope.
15
+ export const KNOWN_RUNTIMES = ["claude-code", "codex"];
16
+ export const DEFAULT_RUNTIME = "claude-code";
17
+ export function isRuntime(value) {
18
+ return typeof value === "string" && KNOWN_RUNTIMES.includes(value);
19
+ }
20
+ export function parseRuntime(raw) {
21
+ if (raw === undefined)
22
+ return { runtime: DEFAULT_RUNTIME, warning: null };
23
+ if (isRuntime(raw))
24
+ return { runtime: raw, warning: null };
25
+ return {
26
+ runtime: DEFAULT_RUNTIME,
27
+ warning: `unrecognised runtime ${JSON.stringify(raw)}, falling back to "${DEFAULT_RUNTIME}". Allowed: ${KNOWN_RUNTIMES.join(", ")}.`,
28
+ };
29
+ }
30
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/policy-packs/runtime.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,uDAAuD;AACvD,EAAE;AACF,wFAAwF;AACxF,iEAAiE;AACjE,iEAAiE;AACjE,qCAAqC;AACrC,EAAE;AACF,oEAAoE;AACpE,uEAAuE;AACvE,6CAA6C;AAC7C,qEAAqE;AACrE,iEAAiE;AACjE,gCAAgC;AAEhC,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,aAAa,EAAE,OAAO,CAAU,CAAC;AAEhE,MAAM,CAAC,MAAM,eAAe,GAAY,aAAa,CAAC;AAEtD,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,cAAoC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC5F,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAuB;IAIlD,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC1E,IAAI,SAAS,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3D,OAAO;QACL,OAAO,EAAE,eAAe;QACxB,OAAO,EAAE,wBAAwB,IAAI,CAAC,SAAS,CAC7C,GAAG,CACJ,sBAAsB,eAAe,eAAe,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;KAClF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ export type PackSourceKind = "builtin" | "unknown";
2
+ export interface PackSourceParseResult {
3
+ kind: PackSourceKind;
4
+ raw: string;
5
+ }
6
+ export declare function parsePackSource(source: string): PackSourceParseResult;
@@ -0,0 +1,10 @@
1
+ // Pack `source:` strings parse here. v1 only resolves `builtin`; future
2
+ // values (`path:./foo`, `npm:@scope/pack@1.0.0`, `git:https://...`) are
3
+ // reserved for community-authored packs and surface as `kind: "unknown"`
4
+ // today, with the canonical-doc-pointer in the warning.
5
+ export function parsePackSource(source) {
6
+ if (source === "builtin")
7
+ return { kind: "builtin", raw: source };
8
+ return { kind: "unknown", raw: source };
9
+ }
10
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/policy-packs/source.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,wEAAwE;AACxE,yEAAyE;AACzE,wDAAwD;AASxD,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IAClE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { Hook } from "../schema/index.js";
2
+ export interface PackContributionFile {
3
+ /** Relative path under `harness.generated/`, including the policy-packs/ prefix. */
4
+ relativePath: string;
5
+ content: string;
6
+ }
7
+ /**
8
+ * Phase 6 #5 — permissions contributed by a pack's selected
9
+ * permission profile. Translated downstream into the Claude Code
10
+ * settings.json `permissions` block.
11
+ */
12
+ export interface PackPermissionsContribution {
13
+ allow: string[];
14
+ ask: string[];
15
+ deny: string[];
16
+ }
17
+ export interface PackContribution {
18
+ /** Hooks to merge into the manifest before settings.json generation. */
19
+ hooks: Hook[];
20
+ /** Files to write under `harness.generated/`. */
21
+ files: PackContributionFile[];
22
+ /** Optional permission contribution (Phase 6 #5). */
23
+ permissions?: PackPermissionsContribution;
24
+ }
25
+ export interface PackExpansionResult {
26
+ /** Combined hooks contributed by every enabled, resolvable pack. */
27
+ hooks: Hook[];
28
+ /** Combined files contributed by every enabled, resolvable pack. */
29
+ files: PackContributionFile[];
30
+ /**
31
+ * Combined permissions contributed by every enabled, resolvable
32
+ * pack (set-union per bucket; later contributions cannot relax a
33
+ * deny from an earlier pack). undefined when no pack contributed
34
+ * any permission entries.
35
+ */
36
+ permissions?: PackPermissionsContribution;
37
+ /** Non-fatal expansion warnings (e.g. unknown source, unknown name on a non-strict path). */
38
+ warnings: string[];
39
+ /** Names of packs that were skipped because `enabled: false`. */
40
+ skipped: string[];
41
+ }
@@ -0,0 +1,11 @@
1
+ // Shared types for the policy-pack expansion pipeline.
2
+ //
3
+ // A pack contribution is the data a builtin pack produces at apply time:
4
+ // a list of hooks to merge into the in-memory manifest before settings
5
+ // generation, plus a list of files to write under
6
+ // `harness.generated/policy-packs/<name>/`.
7
+ //
8
+ // The `Hook` shape mirrors the manifest's hooks[] entry exactly (so the
9
+ // existing generate-settings projection picks them up unchanged).
10
+ export {};
11
+ //# sourceMappingURL=types.js.map