@zaip-ai/cli 4.1.0 → 4.3.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 (179) hide show
  1. package/dist/commands/init.d.ts.map +1 -1
  2. package/dist/commands/init.js +3 -1
  3. package/dist/commands/init.js.map +1 -1
  4. package/dist/services/adapter-hook-sources.d.ts +1 -0
  5. package/dist/services/adapter-hook-sources.d.ts.map +1 -1
  6. package/dist/services/adapter-hook-sources.js +1 -0
  7. package/dist/services/adapter-hook-sources.js.map +1 -1
  8. package/dist/services/adapters.d.ts +2 -2
  9. package/dist/services/adapters.d.ts.map +1 -1
  10. package/dist/services/adapters.js +14 -73
  11. package/dist/services/adapters.js.map +1 -1
  12. package/dist/services/adapters.test.js +1 -0
  13. package/dist/services/adapters.test.js.map +1 -1
  14. package/dist/services/agent-adapters.d.ts.map +1 -1
  15. package/dist/services/agent-adapters.js +3 -7
  16. package/dist/services/agent-adapters.js.map +1 -1
  17. package/dist/services/agent-adapters.test.js +43 -11
  18. package/dist/services/agent-adapters.test.js.map +1 -1
  19. package/dist/services/codex-config-template.js +2 -2
  20. package/dist/services/codex-conversation-lifecycle-hook.d.ts.map +1 -1
  21. package/dist/services/codex-conversation-lifecycle-hook.js +38 -14
  22. package/dist/services/codex-conversation-lifecycle-hook.js.map +1 -1
  23. package/dist/services/codex-hook-activation.d.ts +4 -0
  24. package/dist/services/codex-hook-activation.d.ts.map +1 -0
  25. package/dist/services/codex-hook-activation.js +64 -0
  26. package/dist/services/codex-hook-activation.js.map +1 -0
  27. package/dist/services/codex-model-policy.d.ts +4 -0
  28. package/dist/services/codex-model-policy.d.ts.map +1 -0
  29. package/dist/services/codex-model-policy.js +24 -0
  30. package/dist/services/codex-model-policy.js.map +1 -0
  31. package/dist/services/codex-native-tool-authority-template.d.ts +2 -0
  32. package/dist/services/codex-native-tool-authority-template.d.ts.map +1 -0
  33. package/dist/services/codex-native-tool-authority-template.js +89 -0
  34. package/dist/services/codex-native-tool-authority-template.js.map +1 -0
  35. package/dist/services/codex-pre-tool-hook-template.d.ts.map +1 -1
  36. package/dist/services/codex-pre-tool-hook-template.js +68 -126
  37. package/dist/services/codex-pre-tool-hook-template.js.map +1 -1
  38. package/dist/services/codex-pre-tool-hook-template.test.js +262 -1
  39. package/dist/services/codex-pre-tool-hook-template.test.js.map +1 -1
  40. package/dist/services/codex-pre-tool-support-template.d.ts +2 -0
  41. package/dist/services/codex-pre-tool-support-template.d.ts.map +1 -0
  42. package/dist/services/codex-pre-tool-support-template.js +401 -0
  43. package/dist/services/codex-pre-tool-support-template.js.map +1 -0
  44. package/dist/services/codex-subagent-hook-template.d.ts +1 -1
  45. package/dist/services/codex-subagent-hook-template.d.ts.map +1 -1
  46. package/dist/services/codex-subagent-hook-template.js +46 -10
  47. package/dist/services/codex-subagent-hook-template.js.map +1 -1
  48. package/dist/services/codex-validation-runtime-template.d.ts +3 -0
  49. package/dist/services/codex-validation-runtime-template.d.ts.map +1 -0
  50. package/dist/services/codex-validation-runtime-template.js +18 -0
  51. package/dist/services/codex-validation-runtime-template.js.map +1 -0
  52. package/dist/services/codex-windows-hook-command.d.ts.map +1 -1
  53. package/dist/services/codex-windows-hook-command.js +4 -2
  54. package/dist/services/codex-windows-hook-command.js.map +1 -1
  55. package/dist/services/codex-windows-hook-command.test.js +22 -0
  56. package/dist/services/codex-windows-hook-command.test.js.map +1 -1
  57. package/dist/services/developer-identity-fixture.d.ts +3 -0
  58. package/dist/services/developer-identity-fixture.d.ts.map +1 -0
  59. package/dist/services/developer-identity-fixture.js +17 -0
  60. package/dist/services/developer-identity-fixture.js.map +1 -0
  61. package/dist/services/global-codex-config-fixtures.d.ts +12 -0
  62. package/dist/services/global-codex-config-fixtures.d.ts.map +1 -0
  63. package/dist/services/global-codex-config-fixtures.js +38 -0
  64. package/dist/services/global-codex-config-fixtures.js.map +1 -0
  65. package/dist/services/global-codex-config-migration.test.d.ts +2 -0
  66. package/dist/services/global-codex-config-migration.test.d.ts.map +1 -0
  67. package/dist/services/global-codex-config-migration.test.js +301 -0
  68. package/dist/services/global-codex-config-migration.test.js.map +1 -0
  69. package/dist/services/global-codex-config-transaction.d.ts +15 -0
  70. package/dist/services/global-codex-config-transaction.d.ts.map +1 -0
  71. package/dist/services/global-codex-config-transaction.js +89 -0
  72. package/dist/services/global-codex-config-transaction.js.map +1 -0
  73. package/dist/services/global-codex-config-transaction.test.d.ts +2 -0
  74. package/dist/services/global-codex-config-transaction.test.d.ts.map +1 -0
  75. package/dist/services/global-codex-config-transaction.test.js +145 -0
  76. package/dist/services/global-codex-config-transaction.test.js.map +1 -0
  77. package/dist/services/global-codex-config.d.ts +10 -11
  78. package/dist/services/global-codex-config.d.ts.map +1 -1
  79. package/dist/services/global-codex-config.js +226 -108
  80. package/dist/services/global-codex-config.js.map +1 -1
  81. package/dist/services/global-codex-config.test.js +6 -6
  82. package/dist/services/global-codex-config.test.js.map +1 -1
  83. package/dist/services/hook-readiness.d.ts +7 -0
  84. package/dist/services/hook-readiness.d.ts.map +1 -0
  85. package/dist/services/hook-readiness.js +17 -0
  86. package/dist/services/hook-readiness.js.map +1 -0
  87. package/dist/services/logger.d.ts +2 -0
  88. package/dist/services/logger.d.ts.map +1 -1
  89. package/dist/services/logger.js +15 -1
  90. package/dist/services/logger.js.map +1 -1
  91. package/dist/services/logger.test.js +3 -0
  92. package/dist/services/logger.test.js.map +1 -1
  93. package/dist/services/managed-adapter.d.ts +6 -0
  94. package/dist/services/managed-adapter.d.ts.map +1 -0
  95. package/dist/services/managed-adapter.js +63 -0
  96. package/dist/services/managed-adapter.js.map +1 -0
  97. package/dist/services/runtime-template.test.js +3 -0
  98. package/dist/services/runtime-template.test.js.map +1 -1
  99. package/dist/types.d.ts +2 -0
  100. package/dist/types.d.ts.map +1 -1
  101. package/package.json +1 -1
  102. package/templates/.agents/README.md +8 -0
  103. package/templates/.agents/config/agents/discovery.json +1 -1
  104. package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +1 -2
  105. package/templates/.agents/config/clients/codex/agents/zaip-agent-brand-strategist.toml +1 -2
  106. package/templates/.agents/config/clients/codex/agents/zaip-agent-builder.toml +1 -2
  107. package/templates/.agents/config/clients/codex/agents/zaip-agent-cloud-engineer.toml +1 -2
  108. package/templates/.agents/config/clients/codex/agents/zaip-agent-data-analyst.toml +1 -2
  109. package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +1 -2
  110. package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +1 -2
  111. package/templates/.agents/config/clients/codex/agents/zaip-agent-general-operations.toml +1 -2
  112. package/templates/.agents/config/clients/codex/agents/zaip-agent-governance-compliance.toml +1 -2
  113. package/templates/.agents/config/clients/codex/agents/zaip-agent-growth-strategist.toml +1 -2
  114. package/templates/.agents/config/clients/codex/agents/zaip-agent-marketing-analyst.toml +1 -2
  115. package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +1 -2
  116. package/templates/.agents/config/clients/codex/agents/zaip-agent-refactoring-specialist.toml +1 -2
  117. package/templates/.agents/config/clients/codex/agents/zaip-agent-sales-specialist.toml +1 -2
  118. package/templates/.agents/config/clients/codex/agents/zaip-agent-task-executor.toml +1 -2
  119. package/templates/.agents/config/clients/codex/agents/zaip-agent-website-developer.toml +1 -2
  120. package/templates/.agents/config/clients/codex/agents/zaip-agent-writer.toml +1 -2
  121. package/templates/.agents/dashboard/.zaip-managed.json +40 -32
  122. package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-DlN5EMmD.js → DashboardHelpDialog-CkQ_y8kg.js} +60 -1
  123. package/templates/.agents/dashboard/apps/frontend/dist/assets/{ProjectSettingsPage-BRdoeTWk.js → ProjectSettingsPage-doIMhei7.js} +1 -1
  124. package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-B_5u4Xnp.js → TraceabilityWorkspace-C_4ftjyB.js} +1 -1
  125. package/templates/.agents/dashboard/apps/frontend/dist/assets/{index-C4rLXrz_.js → index-Rbmpz4UO.js} +2 -2
  126. package/templates/.agents/dashboard/apps/frontend/dist/index.html +1 -1
  127. package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
  128. package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
  129. package/templates/.agents/dashboard/modules/operations/package.json +1 -1
  130. package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
  131. package/templates/.agents/dashboard/packages/branding/package.json +1 -1
  132. package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
  133. package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
  134. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +176 -176
  135. package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +135 -135
  136. package/templates/.agents/dashboard/packages/local-runtime/package.json +1 -1
  137. package/templates/.agents/dashboard/packages/local-runtime/server.mjs +176 -176
  138. package/templates/.agents/dashboard/packages/local-runtime/src/server-operation-detail.test.ts +106 -0
  139. package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +0 -13
  140. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-counts-every-root-execution-day-returns.test.ts +17 -230
  141. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-counts-fixture.test-support.ts +239 -0
  142. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.test.mjs +28 -8
  143. package/templates/.agents/dashboard/packages/ui/package.json +1 -1
  144. package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
  145. package/templates/.agents/design/.zaip-managed.json +3 -3
  146. package/templates/.agents/design/apps/catalog/package.json +1 -1
  147. package/templates/.agents/design/packages/local-runtime/package.json +1 -1
  148. package/templates/.agents/requirements/autonomous-assurance.md +1 -1
  149. package/templates/.agents/requirements/cloud-hostinger-autonomy.md +1 -1
  150. package/templates/.agents/requirements/comparative-audit.md +1 -1
  151. package/templates/.agents/requirements/context-engine.md +1 -1
  152. package/templates/.agents/requirements/cost-observability.md +1 -1
  153. package/templates/.agents/requirements/dashboard-launch.md +1 -1
  154. package/templates/.agents/requirements/data-export.md +1 -1
  155. package/templates/.agents/requirements/design-system.md +1 -1
  156. package/templates/.agents/requirements/execution-engine.md +1 -1
  157. package/templates/.agents/requirements/kanban-dashboard.md +1 -1
  158. package/templates/.agents/requirements/model-orchestration.md +1 -1
  159. package/templates/.agents/requirements/public-distribution.md +1 -1
  160. package/templates/.agents/requirements/software-architecture.md +1 -1
  161. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  162. package/templates/.agents/requirements/work-lifecycle.md +1 -1
  163. package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
  164. package/templates/.agents/rules/astra-diagnostic.md +1 -1
  165. package/templates/.agents/runtime/VERSION +1 -1
  166. package/templates/.agents/runtime/bin/zaip.mjs +769 -213
  167. package/templates/.agents/runtime/checksums.sha256 +5 -5
  168. package/templates/.agents/runtime/manifest.json +1 -1
  169. package/templates/.agents/runtime/provenance.json +4 -4
  170. package/templates/.agents/runtime/sbom.cdx.json +1 -1
  171. package/templates/.agents/skills/zaip-skill-execution/SKILL.md +1 -1
  172. package/templates/.agents/skills/zaip-skill-execution/references/correction-cycle.md +26 -0
  173. package/templates/.agents/skills/zaip-skill-execution/references/runtime-governance.md +2 -0
  174. package/templates/.agents/skills/zaip-skill-release-qualification/references/local-preparation.md +31 -1
  175. package/templates/.agents/skills/zaip-skill-setup/SKILL.md +26 -1
  176. package/templates/.agents/skills/zaip-skill-task/references/commit-policy.md +8 -1
  177. package/templates/.agents/zaip-aios/VERSION +1 -1
  178. package/templates/.agents/zaip-aios/guides/14-troubleshooting.md +52 -1
  179. package/templates/template-manifest.json +95 -87
@@ -5,9 +5,12 @@ import { lstat, readFile, realpath } from "node:fs/promises";
5
5
  import { dirname, isAbsolute, relative, resolve } from "node:path";
6
6
  import { fileURLToPath, pathToFileURL } from "node:url";
7
7
  import { promisify } from "node:util";
8
-
8
+ import { captureCliTurn, checkDestructivePatterns, gitInvocation, inside, isLiteralReadSequence, requiresShellMutationRun, reviewedContextReadPaths, reviewedReleasePaths, rewriteCliInput, selectHookExecutionWorkspace, shellSyntax, tokenizeLiteralCommand, validateInlineExecution } from "./zaip-pre-tool-support.mjs";
9
9
  const execute = promisify(execFile);
10
- const repositoryRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
10
+ const nativeAuthority = await import("./zaip-native-tool-authority.mjs").catch(() => null);
11
+ const activation = await import("./zaip-hook-activation.mjs").catch(() => null);
12
+ const installedRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
13
+ let repositoryRoot = installedRoot;
11
14
  const deletionCommandPattern = /\b(?:Remove-Item|rm|rmdir|rd|del|erase)\b/i;
12
15
  const allowedExplicitNetworkHosts = new Set([
13
16
  "127.0.0.1", "api.github.com", "github.com", "localhost", "objects.githubusercontent.com", "::1",
@@ -66,7 +69,7 @@ const destructivePatterns = [
66
69
  reason: "Remote, SSH, and credential configuration changes are blocked.",
67
70
  },
68
71
  {
69
- pattern: /\bgh\b[\s\S]*\s--repo(?:=|\s)/i,
72
+ pattern: /\bgh(?:\.exe)?\b[\s\S]*\s(?:--repo|-R)(?:=|\s|(?=[A-Za-z0-9]))/i,
70
73
  reason: "GitHub CLI commands must target the current repository.",
71
74
  },
72
75
  {
@@ -94,13 +97,17 @@ const destructivePatterns = [
94
97
  reason: "OS persistence and service changes are blocked.",
95
98
  },
96
99
  {
97
- pattern: /\b(?:diskpart|bcdedit|fsutil|takeown|icacls|Set-Acl|chmod|chown)\b|(?:^|[\s;&|"'(])format(?:\.com)?\b|\bcipher\s+\/w\b/i,
100
+ pattern: /\b(?:diskpart|bcdedit|fsutil|takeown|icacls|Set-Acl|chmod|chown)\b|(?:^|[;&|({\r\n])\s*(?:&\s*)?["']?format(?:\.(?:com|exe))?["']?(?=\s|$)|\bcipher\s+\/w\b/i,
98
101
  reason: "Disk, boot, ownership, and access-control changes are blocked.",
99
102
  },
100
103
  {
101
104
  pattern: /\b(?:runas|sudo|gsudo)\b|Start-Process[\s\S]*-Verb\s+RunAs|\bSet-ExecutionPolicy\b/i,
102
105
  reason: "Privilege escalation and persistent execution-policy changes are blocked.",
103
106
  },
107
+ {
108
+ pattern: /\b(?:Start-Process|saps)\b[^\r\n;|]*(?:[$(]|\b(?:-FilePath\s+)?['"]?git(?:\.exe)?['"]?(?:\s|$))/i,
109
+ reason: "Dynamic or indirect Git process launch is blocked; use a reviewed repository script.",
110
+ },
104
111
  {
105
112
  pattern: /\b(?:winget|choco|scoop)\s+(?:install|uninstall|upgrade)\b|\b(?:npm|pnpm|yarn)\s+(?:install|add|remove|uninstall)[\s\S]*(?:--global|-g)\b/i,
106
113
  reason: "System-wide package changes are blocked.",
@@ -110,7 +117,7 @@ const destructivePatterns = [
110
117
  reason: "Non-loopback listeners are blocked.",
111
118
  },
112
119
  {
113
- pattern: /\bgh\s+(?:pr\s+(?:create|merge|close|reopen)|issue\s+(?:create|close|reopen|delete)|release\s+(?:create|delete|upload)|repo\s+(?:create|delete|archive)|api\b[\s\S]*(?:--method|-X)\s*(?:POST|PUT|PATCH|DELETE))\b/i,
120
+ pattern: /\bgh(?:\.exe)?\s+(?:pr\s+(?:create|merge|close|reopen)|issue\s+(?:create|close|reopen|delete)|release\s+(?:create|delete|upload)|repo\s+(?:create|delete|archive)|api\b[\s\S]*(?:(?:--method|-X)(?:=|\s*)(?:POST|PUT|PATCH|DELETE)\b|(?:--field|--raw-field|--input)(?:=|\s+)|(?:^|\s)-[fF](?:=|\s+)))/i,
114
121
  reason: "Unreviewed GitHub mutations are blocked; use the bounded deploy workflow.",
115
122
  },
116
123
  {
@@ -120,23 +127,21 @@ const destructivePatterns = [
120
127
  ];
121
128
 
122
129
  function deny(reason) {
130
+ activation?.recordActivation(repositoryRoot, event, "denied");
123
131
  writeSync(
124
132
  1,
125
133
  JSON.stringify({
126
134
  hookSpecificOutput: {
127
135
  hookEventName: "PreToolUse",
128
136
  permissionDecision: "deny",
129
- permissionDecisionReason: "ZAIP safety policy: " + reason,
137
+ permissionDecisionReason: "ZAIP safety policy: " + reason + " [tool=" + String(event?.tool_name ?? "unknown").slice(0, 80) + "; session=" + String(event?.session_id ?? "missing").slice(0, 80) + "; turn=" + String(event?.turn_id ?? "missing").slice(0, 80) + "]",
130
138
  },
131
139
  }) + "\n",
132
140
  );
133
141
  process.exit(0);
134
142
  }
135
143
 
136
- function isWithinRepository(path) {
137
- const candidate = relative(repositoryRoot, resolve(path));
138
- return candidate === "" || (!candidate.startsWith("..") && !isAbsolute(candidate));
139
- }
144
+ const isWithinRepository = path => inside(path, repositoryRoot);
140
145
 
141
146
  function repositoryPath(path) {
142
147
  return relative(repositoryRoot, resolve(path)).replaceAll("\\", "/");
@@ -168,56 +173,52 @@ function explicitPathCandidates(command) {
168
173
  }
169
174
  return [...candidates].map(unquote).filter(Boolean);
170
175
  }
171
-
172
- function validateExplicitFilesystemReferences(command, cwd) {
173
- if (homeReferencePattern.test(command)) {
176
+ function validateExplicitFilesystemReferences(command, cwd, reviewedPaths = []) {
177
+ const checked = reviewedPaths.reduce((text, path) => text.replaceAll(path, "REVIEWED_RELEASE_PATH"), command);
178
+ if (homeReferencePattern.test(checked)) {
174
179
  deny("Direct user-profile path references are blocked; use repository-scoped paths.");
175
180
  }
176
- if (credentialReferencePattern.test(command) || sensitiveEnvironmentPattern.test(command)) {
181
+ if (credentialReferencePattern.test(checked) || sensitiveEnvironmentPattern.test(checked)) {
177
182
  deny("Direct credential and secret access is blocked.");
178
183
  }
179
- if (/\b(?:Get-ChildItem|gci|dir)\s+Env:|\b(?:printenv|set)\s*$/i.test(command) || /GetEnvironmentVariables\s*\(/i.test(command)) {
184
+ if (/\b(?:Get-ChildItem|gci|dir)\s+Env:|\b(?:printenv|set)\s*$/i.test(checked) || /GetEnvironmentVariables\s*\(/i.test(checked)) {
180
185
  deny("Bulk environment enumeration is blocked.");
181
186
  }
182
- if (/\\\\[^\\\s"']+[\\/]/.test(command)) {
187
+ if (/(?:^|[\s"'=(,]|-[A-Za-z][A-Za-z0-9_-]*:)(?:(?:\\\\){1,2}|\/\/)[^\\/\s"']+[\\/]/.test(checked)) {
183
188
  deny("UNC and network filesystem paths are blocked.");
184
189
  }
185
- if (/(?:^|[\s"'=])\/(?:etc|home|Users|root|var|opt|private|mnt|proc|sys|dev|tmp)(?:[\/\s"']|$)/i.test(command)) {
190
+ const osPathCommand = checked.replace(/^(node\s+\.agents[\\/]runtime[\\/]bin[\\/]zaip\.mjs\s+subagent\s+capture-terminal\b[^;&|\x60\r\n]*?)--agent-id\s+\/root\/[a-z][a-z0-9_]*_zaip_agent(?:_[a-z0-9]+)?(?=\s|$)(?=[^;&|\x60\r\n]*$)/, "$1--agent-id zaip-agent");
191
+ if (/(?:^|[\s"'=])\/(?:etc|home|Users|root|var|opt|private|mnt|proc|sys|dev|tmp)(?:[\/\s"']|$)/i.test(osPathCommand)) {
186
192
  deny("Explicit operating-system paths outside the repository are blocked.");
187
193
  }
188
- for (const candidate of explicitPathCandidates(command)) {
194
+ if (process.platform === "win32" && /(?:^|[\s"'=(,])\\(?!\\)[^\s\\/"'<>|;]+(?:\\[^\s"'<>|;]+|\.[A-Za-z0-9]{1,10})/.test(checked)) {
195
+ deny("Drive-rooted filesystem paths outside the repository are blocked.");
196
+ }
197
+ for (const candidate of explicitPathCandidates(checked)) {
189
198
  if (process.platform !== "win32" && /^[A-Za-z]:[\\/]/.test(candidate)) deny("Explicit filesystem path escapes the repository boundary.");
190
199
  const absolute = resolve(cwd, candidate);
191
200
  if (!isWithinRepository(absolute)) {
192
- deny("Explicit filesystem path escapes the repository boundary.");
201
+ deny("Explicit filesystem path escapes the repository boundary. Validated workspace: " + repositoryRoot + "; tool: " + event.tool_name + "; workdir override: " + (typeof event.tool_input?.workdir === "string"));
193
202
  }
194
203
  }
195
204
  }
196
-
197
- function validateInlineExecution(command) {
198
- const inlinePatterns = [
199
- /\b(?:node|deno)\s+(?:-e|--eval)\b/i,
200
- /\b(?:python(?:3)?|ruby|perl|php)\s+(?:-c|-e)\b/i,
201
- /\bdeno\s+eval\b/i,
202
- /\b(?:powershell|pwsh)(?:\.exe)?\b[\s\S]*\s-(?:Command|EncodedCommand|enc)\b/i,
203
- /\bcmd(?:\.exe)?\s+\/c\b/i,
204
- /\|\s*(?:node|deno|python(?:3)?|ruby|perl|php|powershell|pwsh|cmd)\b/i,
205
- /\b(?:Invoke-Expression|iex)\b/i,
206
- ];
207
- if (inlinePatterns.some((pattern) => pattern.test(command))) {
208
- deny("Inline or piped interpreter execution is blocked; use a reviewed repository script.");
209
- }
210
- }
211
-
212
205
  async function validateGitPublication(command) {
206
+ if (/(?:^|[;&|\r\n])\s*(?:(?:&\s*)?(?:['"]git(?:\.exe)?['"]|\(\s*['"]git(?:\.exe)?['"]\s*\))|(?:env|command)\s+git(?:\.exe)?\b)/i.test(command) ||
207
+ /&\s*\(\s*Get-Command\s+git(?:\.exe)?\b/i.test(command) ||
208
+ /(?:^|[\s;&|])&\s*\$[A-Za-z_]/i.test(command) || /\b(?:Set-Alias|New-Alias)\b[^\r\n;]*\bgit\b/i.test(command)) {
209
+ deny("Indirect Git execution is blocked; use a single literal command.");
210
+ }
211
+ if (/\(\s*git(?:\.exe)?\b/i.test(command)) {
212
+ deny("Nested Git execution is blocked; use a single literal command.");
213
+ }
213
214
  const tokens = tokenizeLiteralCommand(command);
214
215
  if (tokens === null) {
215
- if (/(?:^|[;&|]\s*)git(?:\.exe)?\b/i.test(command)) {
216
+ if (/(?:^|[;&|\r\n(])\s*git(?:\.exe)?\b/i.test(command)) {
216
217
  deny("Git commands must be a single literal command; separate commands before requesting execution.");
217
218
  }
218
219
  return;
219
220
  }
220
- const invocation = gitInvocation(tokens);
221
+ const invocation = gitInvocation(tokens, deny);
221
222
  if (invocation === null) return;
222
223
  const { subcommand, arguments: arguments_ } = invocation;
223
224
  if (subcommand === "commit" && arguments_.some((value) => /^(?:--amend|--no-verify|-n)/i.test(value))) {
@@ -331,39 +332,6 @@ function isSafeBranchName(branch) {
331
332
  return typeof branch === "string" && branch.length <= 255 && /^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(branch) && !branch.includes("..") && !branch.includes("//") && !branch.includes("@{") && !branch.endsWith(".") && !branch.endsWith("/") && !branch.split("/").some((segment) => segment.startsWith(".") || segment.endsWith(".lock"));
332
333
  }
333
334
 
334
- function gitInvocation(tokens) {
335
- if (tokens === null || !/^(?:git|git\.exe)$/i.test(tokens[0] ?? "")) return null;
336
- let index = 1;
337
- while (index < tokens.length && tokens[index].startsWith("-")) {
338
- const rawOption = tokens[index];
339
- const option = rawOption.toLowerCase();
340
- if (option === "--version" || option === "--help") return null;
341
- if (option === "--no-pager" || option === "--literal-pathspecs") {
342
- index += 1;
343
- continue;
344
- }
345
- if (
346
- rawOption === "-c" ||
347
- rawOption.startsWith("-c") ||
348
- option.startsWith("--config") ||
349
- option === "--git-dir" ||
350
- option === "--work-tree" ||
351
- option === "--namespace"
352
- ) {
353
- deny("Git global configuration and repository-routing overrides are blocked.");
354
- }
355
- if (rawOption === "-C" || rawOption.startsWith("-C")) {
356
- const directory = rawOption === "-C" ? tokens[index + 1] : rawOption.slice(2);
357
- if (directory !== ".") deny("Git working-directory overrides outside the repository root are blocked.");
358
- index += rawOption === "-C" ? 2 : 1;
359
- continue;
360
- }
361
- deny("Unknown Git global option is blocked.");
362
- }
363
- const subcommand = tokens[index]?.toLowerCase();
364
- return subcommand === undefined ? null : { subcommand, arguments: tokens.slice(index + 1) };
365
- }
366
-
367
335
  function validateExplicitNetwork(command) {
368
336
  if (/(?:^|[;&|]\s*)\b(?:ssh|scp|sftp|rsync|ftp|telnet|nc|ncat)\b/i.test(command)) {
369
337
  deny("Direct remote-shell and file-transfer clients are blocked.");
@@ -546,43 +514,6 @@ async function validateCloudRunner(command) {
546
514
  return true;
547
515
  }
548
516
 
549
- function tokenizeLiteralCommand(command) {
550
- if (
551
- command.includes("\r") ||
552
- command.includes("\n") ||
553
- command.includes(";") ||
554
- command.includes("|") ||
555
- command.includes("&") ||
556
- command.includes(String.fromCharCode(96))
557
- ) return null;
558
-
559
- const tokens = [];
560
- let token = "";
561
- let quote = null;
562
- let started = false;
563
- for (const character of command) {
564
- if (quote !== null) {
565
- if (character === quote) quote = null;
566
- else token += character;
567
- } else if (character === "'" || character === '"') {
568
- quote = character;
569
- started = true;
570
- } else if (/\s/.test(character)) {
571
- if (started) {
572
- tokens.push(token);
573
- token = "";
574
- started = false;
575
- }
576
- } else {
577
- token += character;
578
- started = true;
579
- }
580
- }
581
- if (quote !== null) return null;
582
- if (started) tokens.push(token);
583
- return tokens;
584
- }
585
-
586
517
  function deletionTargets(command) {
587
518
  const tokens = tokenizeLiteralCommand(command);
588
519
  if (tokens === null || tokens.length < 2) return null;
@@ -652,7 +583,7 @@ async function validateShellDeletion(command, cwd) {
652
583
  for (const target of targets) await validateDeletionPath(target, cwd);
653
584
  }
654
585
 
655
- function validatePatch(command) {
586
+ async function validatePatch(command) {
656
587
  const headers = [...command.matchAll(/^\*\*\* (Add|Update|Delete) File:\s*(.+)$|^\*\*\* Move to:\s*(.+)$/gm)];
657
588
  const lifecycleRecordTouched = headers.some((match) => {
658
589
  const candidate = (match[2] ?? match[3]).trim().replace(/^["']|["']$/g, "");
@@ -665,28 +596,27 @@ function validatePatch(command) {
665
596
  const candidate = (match[2] ?? match[3]).trim().replace(/^["']|["']$/g, "");
666
597
  const absolute = resolve(repositoryRoot, candidate);
667
598
  if (!isWithinRepository(absolute)) deny("Patch path escapes the repository boundary.");
599
+ if (!await nativeAuthority?.isSafePatchPath(absolute, repositoryRoot)) deny("Patch path traverses a link or could not be safely verified.");
668
600
  if (repositoryPath(absolute) === "") deny("Patching the repository root is blocked.");
669
601
  if (isGitPath(absolute)) {
670
602
  deny("Direct edits to protected Git control files are blocked.");
671
603
  }
672
604
  }
673
605
  }
674
-
675
- const lifecycleExemptPathPattern = /^(?:\.agents\/records|\.local)\//;
676
- const shellMutationPattern = /\b(?:Set-Content|Add-Content|Out-File|New-Item|Copy-Item|Move-Item|Remove-Item|git\s+apply|npm\s+version|pnpm\s+version)\b/i;
677
-
606
+ const lifecycleExemptPathPattern = /^\.local\/(?!(?:codex-hook-|codex-telemetry-spool\/|runs\/))/;
678
607
  function patchPaths(command) {
679
608
  return [...command.matchAll(/^\*\*\* (?:Add|Update|Delete) File:\s*(.+)$|^\*\*\* Move to:\s*(.+)$/gm)].map(
680
609
  (match) => repositoryPath(resolve(repositoryRoot, (match[1] ?? match[2]).trim().replace(/^["']|["']$/g, ""))),
681
610
  );
682
611
  }
683
612
 
684
- function requiresOrchestratorRun(event, command) {
613
+ async function requiresOrchestratorRun(event, command) {
685
614
  if (event.tool_name === "apply_patch") {
686
615
  const paths = patchPaths(command);
687
616
  return paths.length === 0 || paths.some((path) => !lifecycleExemptPathPattern.test(path));
688
617
  }
689
618
  if (event.tool_name === "Edit" || event.tool_name === "Write") {
619
+ if (!await nativeAuthority?.isSafePatchPath(resolve(event.cwd ?? repositoryRoot, command), repositoryRoot)) deny("File write path traverses a link or could not be safely verified.");
690
620
  return !lifecycleExemptPathPattern.test(repositoryPath(resolve(event.cwd ?? repositoryRoot, command)));
691
621
  }
692
622
  // Only single literal writes claim exemptions; compound commands remain gated.
@@ -701,23 +631,25 @@ function requiresOrchestratorRun(event, command) {
701
631
  }
702
632
  if (valid && options.has("-literalpath") && options.has("-value")) {
703
633
  const path = repositoryPath(resolve(event.cwd ?? repositoryRoot, options.get("-literalpath")));
634
+ if (!await nativeAuthority?.isSafePatchPath(resolve(repositoryRoot, path), repositoryRoot)) deny("Shell write path traverses a link or could not be safely verified.");
704
635
  if (lifecycleExemptPathPattern.test(path)) return false;
705
636
  }
706
637
  }
707
- return shellMutationPattern.test(command);
638
+ return requiresShellMutationRun(command, tokens, event.cwd ?? repositoryRoot, repositoryRoot);
708
639
  }
709
640
 
710
641
  async function boundedCanonicalText(path, maximumBytes) {
711
642
  const info = await lstat(path);
712
643
  if (!info.isFile() || info.isSymbolicLink() || info.size > maximumBytes) throw new Error("Unsafe Run lookup file");
713
644
  const physical = await realpath(path);
714
- if (!isWithinRepository(physical) || physical.toLowerCase() !== resolve(path).toLowerCase()) throw new Error("Run lookup must not follow links");
645
+ const identity = value => process.platform === "win32" ? value.toLowerCase() : value;
646
+ if (!isWithinRepository(physical) || identity(physical) !== identity(resolve(path))) throw new Error("Run lookup must not follow links");
715
647
  return readFile(path, "utf8");
716
648
  }
717
649
 
718
650
  async function hasCurrentTaskOrchestratorRun(event) {
719
- const threadId = event.session_id ?? process.env.CODEX_THREAD_ID;
720
- const turnId = event.turn_id ?? process.env.CODEX_TURN_ID;
651
+ const threadId = event.session_id;
652
+ const turnId = event.turn_id;
721
653
  if (typeof threadId !== "string" || typeof turnId !== "string" || !threadId || !turnId) return false;
722
654
  if ((event.session_id && process.env.CODEX_THREAD_ID && event.session_id !== process.env.CODEX_THREAD_ID) ||
723
655
  (event.turn_id && process.env.CODEX_TURN_ID && event.turn_id !== process.env.CODEX_TURN_ID)) return false;
@@ -726,7 +658,7 @@ async function hasCurrentTaskOrchestratorRun(event) {
726
658
  const digest = createHash("sha256").update(JSON.stringify(["codex", threadId, turnId, null, null])).digest("hex");
727
659
  const correlation = JSON.parse(await boundedCanonicalText(resolve(repositoryRoot, ".local/codex-telemetry-spool/v1/correlations", digest + ".json"), 65536));
728
660
  const id = correlation.run_id;
729
- const dated = typeof id === "string" ? /^RUN-(\d{4})-(\d{2})-(\d{2})-[A-Z0-9-]+-[A-Z0-9]{4}$/.exec(id) : null;
661
+ const dated = typeof id === "string" ? /^RUN-(\d{4})-(\d{2})-(\d{2})-[A-Z0-9-]+-[A-Z0-9]{2,16}$/.exec(id) : null;
730
662
  if (!dated || correlation.schema_version !== 1 || correlation.thread_id !== threadId || correlation.turn_id !== turnId || correlation.agent_path !== null) return false;
731
663
  const candidates = [
732
664
  ".agents/records/runs/" + dated[1] + "/" + dated[2] + "/" + id + ".jsonl",
@@ -766,11 +698,13 @@ try {
766
698
  deny("Malformed hook input was rejected.");
767
699
  }
768
700
 
769
- if (typeof event.cwd !== "string" || !isWithinRepository(event.cwd)) {
701
+ const toolInput = event?.tool_input;
702
+ try { const scope = await selectHookExecutionWorkspace(installedRoot, event); repositoryRoot = scope.repositoryRoot; event = { ...event, cwd: scope.cwd }; }
703
+ catch (error) { deny(error.message); }
704
+ if (!isWithinRepository(event.cwd)) {
770
705
  deny("Tool execution outside the ZAIP-AIOS repository is blocked.");
771
706
  }
772
707
 
773
- const toolInput = event?.tool_input;
774
708
  const commandFromCmd = toolInput?.cmd;
775
709
  const commandFromCommand = toolInput?.command;
776
710
  if (typeof commandFromCmd === "string" && typeof commandFromCommand === "string" && commandFromCmd !== commandFromCommand) {
@@ -779,22 +713,30 @@ if (typeof commandFromCmd === "string" && typeof commandFromCommand === "string"
779
713
  const command = typeof commandFromCmd === "string" ? commandFromCmd : commandFromCommand;
780
714
  if (typeof command !== "string") deny("A matched tool call without a command was rejected.");
781
715
 
782
- if (requiresOrchestratorRun(event, command) && !(await hasCurrentTaskOrchestratorRun(event))) {
716
+ if (await requiresOrchestratorRun(event, command) && !(await hasCurrentTaskOrchestratorRun(event)) &&
717
+ !(await nativeAuthority?.hasNativeDelegatedPatch(event, repositoryRoot, boundedCanonicalText))) {
783
718
  deny("Persistent mutation requires the exact active Task Run and its verified thread/turn correlation. Capture or reconcile this turn before retrying; no global Task fallback is allowed.");
784
719
  }
785
720
 
786
- if (event.tool_name === "apply_patch") validatePatch(command);
721
+ if (event.tool_name === "apply_patch") await validatePatch(command);
787
722
  else {
788
- validateExplicitFilesystemReferences(command, event.cwd);
789
- validateInlineExecution(command);
723
+ const reviewedPaths = [
724
+ ...await reviewedReleasePaths(command, event.cwd, repositoryRoot, credentialReferencePattern, deny),
725
+ ...await reviewedContextReadPaths(command, credentialReferencePattern), ...await (nativeAuthority?.reviewedValidationRuntimePaths?.(command, tokenizeLiteralCommand) ?? []),
726
+ ];
727
+ validateExplicitFilesystemReferences(command, event.cwd, reviewedPaths);
728
+ validateInlineExecution(command, deny);
729
+ if (!isLiteralReadSequence(command)) {
790
730
  await validateGitPublication(command);
791
731
  await validateCloudRunner(command);
792
732
  validateDirectCloudProviderMutation(command);
793
733
  validateExplicitNetwork(command);
794
734
  await validateShellDeletion(command, event.cwd);
795
- for (const entry of destructivePatterns) {
796
- if (entry.pattern.test(command)) deny(entry.reason);
735
+ checkDestructivePatterns(command, destructivePatterns, deny);
797
736
  }
737
+ try { const updated = await captureCliTurn(repositoryRoot, event, command); if (updated) writeSync(1, JSON.stringify(rewriteCliInput(toolInput, updated, commandFromCmd)) + "\n"); }
738
+ catch (error) { deny(error.message); }
798
739
  }
740
+ activation?.recordActivation(repositoryRoot, event, "allowed");
799
741
  `;
800
742
  //# sourceMappingURL=codex-pre-tool-hook-template.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"codex-pre-tool-hook-template.js","sourceRoot":"","sources":["../../src/services/codex-pre-tool-hook-template.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8xB5C,CAAC"}
1
+ {"version":3,"file":"codex-pre-tool-hook-template.js","sourceRoot":"","sources":["../../src/services/codex-pre-tool-hook-template.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAouB5C,CAAC"}