@zaip-ai/cli 4.9.0 → 5.1.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 (213) hide show
  1. package/dist/services/adapter-hook-sources.d.ts +3 -0
  2. package/dist/services/adapter-hook-sources.d.ts.map +1 -1
  3. package/dist/services/adapter-hook-sources.js +3 -0
  4. package/dist/services/adapter-hook-sources.js.map +1 -1
  5. package/dist/services/adapters.d.ts +1 -1
  6. package/dist/services/adapters.d.ts.map +1 -1
  7. package/dist/services/adapters.js +5 -2
  8. package/dist/services/adapters.js.map +1 -1
  9. package/dist/services/adapters.test.js +1 -1
  10. package/dist/services/adapters.test.js.map +1 -1
  11. package/dist/services/codex-conversation-lifecycle-hook.d.ts.map +1 -1
  12. package/dist/services/codex-conversation-lifecycle-hook.js +16 -6
  13. package/dist/services/codex-conversation-lifecycle-hook.js.map +1 -1
  14. package/dist/services/codex-hook-activation.d.ts +1 -1
  15. package/dist/services/codex-hook-activation.d.ts.map +1 -1
  16. package/dist/services/codex-hook-activation.js +116 -10
  17. package/dist/services/codex-hook-activation.js.map +1 -1
  18. package/dist/services/codex-pre-tool-cli-capture-template.d.ts +2 -0
  19. package/dist/services/codex-pre-tool-cli-capture-template.d.ts.map +1 -0
  20. package/dist/services/codex-pre-tool-cli-capture-template.js +104 -0
  21. package/dist/services/codex-pre-tool-cli-capture-template.js.map +1 -0
  22. package/dist/services/codex-pre-tool-cloud-template.d.ts +2 -0
  23. package/dist/services/codex-pre-tool-cloud-template.d.ts.map +1 -0
  24. package/dist/services/codex-pre-tool-cloud-template.js +190 -0
  25. package/dist/services/codex-pre-tool-cloud-template.js.map +1 -0
  26. package/dist/services/codex-pre-tool-dependencies.test-support.d.ts +2 -0
  27. package/dist/services/codex-pre-tool-dependencies.test-support.d.ts.map +1 -0
  28. package/dist/services/codex-pre-tool-dependencies.test-support.js +9 -0
  29. package/dist/services/codex-pre-tool-dependencies.test-support.js.map +1 -0
  30. package/dist/services/codex-pre-tool-hook-fixture.test-support.d.ts +5 -0
  31. package/dist/services/codex-pre-tool-hook-fixture.test-support.d.ts.map +1 -0
  32. package/dist/services/codex-pre-tool-hook-fixture.test-support.js +19 -0
  33. package/dist/services/codex-pre-tool-hook-fixture.test-support.js.map +1 -0
  34. package/dist/services/codex-pre-tool-hook-template-bootstrap.test.d.ts +2 -0
  35. package/dist/services/codex-pre-tool-hook-template-bootstrap.test.d.ts.map +1 -0
  36. package/dist/services/codex-pre-tool-hook-template-bootstrap.test.js +107 -0
  37. package/dist/services/codex-pre-tool-hook-template-bootstrap.test.js.map +1 -0
  38. package/dist/services/codex-pre-tool-hook-template.d.ts.map +1 -1
  39. package/dist/services/codex-pre-tool-hook-template.js +96 -210
  40. package/dist/services/codex-pre-tool-hook-template.js.map +1 -1
  41. package/dist/services/codex-pre-tool-hook-template.test.js +32 -80
  42. package/dist/services/codex-pre-tool-hook-template.test.js.map +1 -1
  43. package/dist/services/codex-pre-tool-host-context-template.d.ts +2 -0
  44. package/dist/services/codex-pre-tool-host-context-template.d.ts.map +1 -0
  45. package/dist/services/codex-pre-tool-host-context-template.js +139 -0
  46. package/dist/services/codex-pre-tool-host-context-template.js.map +1 -0
  47. package/dist/services/codex-pre-tool-support-template.d.ts.map +1 -1
  48. package/dist/services/codex-pre-tool-support-template.js +61 -101
  49. package/dist/services/codex-pre-tool-support-template.js.map +1 -1
  50. package/dist/services/codex-subagent-hook-template.d.ts +1 -1
  51. package/dist/services/codex-subagent-hook-template.d.ts.map +1 -1
  52. package/dist/services/codex-subagent-hook-template.js +13 -2
  53. package/dist/services/codex-subagent-hook-template.js.map +1 -1
  54. package/dist/services/codex-validation-runtime-template.d.ts.map +1 -1
  55. package/dist/services/codex-validation-runtime-template.js +10 -4
  56. package/dist/services/codex-validation-runtime-template.js.map +1 -1
  57. package/dist/services/runtime-template-test-support.d.ts +1 -0
  58. package/dist/services/runtime-template-test-support.d.ts.map +1 -1
  59. package/dist/services/runtime-template-test-support.js +23 -2
  60. package/dist/services/runtime-template-test-support.js.map +1 -1
  61. package/dist/services/runtime-template.test.js +4 -23
  62. package/dist/services/runtime-template.test.js.map +1 -1
  63. package/package.json +1 -1
  64. package/templates/.agents/README-ENG.md +58 -7
  65. package/templates/.agents/README.md +46 -10
  66. package/templates/.agents/config/agents/discovery.json +1 -1
  67. package/templates/.agents/dashboard/.zaip-managed.json +174 -86
  68. package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-BW7Vy1cp.js → CostCalculationGuidePage-uR-asJv_.js} +1 -1
  69. package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-Cp_hEVd8.js → DashboardHelpDialog-CngnpoLL.js} +87 -13
  70. package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-Prcs-ydy.js → PricingSettingsDialog-Bszw3ekd.js} +1 -1
  71. package/templates/.agents/dashboard/apps/frontend/dist/assets/{ProjectSettingsPage-Cu40wAFF.js → ProjectSettingsPage-IJ1znG4w.js} +1 -1
  72. package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-Bh3YBd3C.js → TraceabilityWorkspace-CsBpHqq_.js} +1 -1
  73. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-B0Jwz_rk.js +68 -0
  74. package/templates/.agents/dashboard/apps/frontend/dist/assets/{dashboard-localization-CF7B1Hjn.js → dashboard-localization-D41g5rdo.js} +58 -7
  75. package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-DOhy6D2-.js → icons-vendor-CjGGux6h.js} +1 -1
  76. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-Bedlm0f7.js +2 -0
  77. package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-CkPC-yMz.js → react-vendor-B9jZSAKf.js} +1 -1
  78. package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-BEdGoIDm.js → traceability-DFpwb0TN.js} +1 -1
  79. package/templates/.agents/dashboard/apps/frontend/dist/index.html +5 -5
  80. package/templates/.agents/dashboard/apps/frontend/package.json +2 -2
  81. package/templates/.agents/dashboard/apps/frontend/src/AppDashboardContent.tsx +3 -0
  82. package/templates/.agents/dashboard/apps/frontend/src/AppOverlays.tsx +16 -7
  83. package/templates/.agents/dashboard/apps/frontend/src/__tests__/app-composition-support.ts +1 -0
  84. package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +1 -1
  85. package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +2 -0
  86. package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-documents.navigation.test.tsx +125 -0
  87. package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-documents.ts +67 -9
  88. package/templates/.agents/dashboard/apps/frontend/src/use-dashboard-app-model.tsx +15 -15
  89. package/templates/.agents/dashboard/apps/frontend/src/use-dashboard-locale.ts +18 -0
  90. package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
  91. package/templates/.agents/dashboard/modules/cost-monitor/src/contracts.ts +10 -3
  92. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.run-page.test.ts +5 -1
  93. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostGroupsTable.period-values.test.tsx +2 -2
  94. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables-keeps-legacy-codex-identity-fields-blank.test.ts +5 -5
  95. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +36 -43
  96. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-loaders.ts +1 -0
  97. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-table-formatters.ts +6 -4
  98. package/templates/.agents/dashboard/modules/cost-monitor/src/server/aggregate.ts +2 -2
  99. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.ts +1 -1
  100. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.ts +11 -25
  101. package/templates/.agents/dashboard/modules/cost-monitor/src/server/cost-summary-defaults.ts +26 -0
  102. package/templates/.agents/dashboard/modules/operations/package.json +1 -1
  103. package/templates/.agents/dashboard/modules/operations/src/contracts.ts +11 -16
  104. package/templates/.agents/dashboard/modules/operations/src/planning-contracts.ts +14 -0
  105. package/templates/.agents/dashboard/modules/operations/src/react/DecisionTable.tsx +65 -0
  106. package/templates/.agents/dashboard/modules/operations/src/react/EntityTables.tsx +5 -71
  107. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +4 -39
  108. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewTopPanel.navigation.test.tsx +150 -0
  109. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewTopPanel.tsx +7 -3
  110. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +14 -43
  111. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageOverview.tsx +3 -0
  112. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-contract.ts +51 -0
  113. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +12 -3
  114. package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +1 -0
  115. package/templates/.agents/dashboard/modules/operations/src/react/use-operations-default-range.ts +16 -0
  116. package/templates/.agents/dashboard/modules/operations/src/react/use-operations-filter-sync.ts +66 -0
  117. package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
  118. package/templates/.agents/dashboard/packages/branding/package.json +1 -1
  119. package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
  120. package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
  121. package/templates/.agents/dashboard/packages/local-runtime/dashboard-build-fingerprint.mjs +87 -0
  122. package/templates/.agents/dashboard/packages/local-runtime/dashboard-build-fingerprint.test.mjs +48 -0
  123. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +193 -191
  124. package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +169 -169
  125. package/templates/.agents/dashboard/packages/local-runtime/package.json +1 -1
  126. package/templates/.agents/dashboard/packages/local-runtime/scripts/build-frontend.mjs +29 -0
  127. package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +5 -0
  128. package/templates/.agents/dashboard/packages/local-runtime/server.mjs +193 -191
  129. package/templates/.agents/dashboard/packages/local-runtime/src/active-capture-failure.test.ts +38 -0
  130. package/templates/.agents/dashboard/packages/local-runtime/src/active-capture-failure.ts +35 -0
  131. package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.test.ts +53 -2
  132. package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.ts +18 -1
  133. package/templates/.agents/dashboard/packages/local-runtime/src/manifest-runs.ts +8 -2
  134. package/templates/.agents/dashboard/packages/local-runtime/src/server-capture-projection-order.test.ts +118 -0
  135. package/templates/.agents/dashboard/packages/local-runtime/src/server-cost-run-search.test.ts +90 -0
  136. package/templates/.agents/dashboard/packages/local-runtime/src/server-cost-run-search.ts +86 -0
  137. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-routes.ts +8 -1
  138. package/templates/.agents/dashboard/packages/local-runtime/src/server-projection-loaders.ts +13 -0
  139. package/templates/.agents/dashboard/packages/local-runtime/src/server-projections.ts +30 -74
  140. package/templates/.agents/dashboard/packages/local-runtime/src/server-route-handlers.ts +42 -0
  141. package/templates/.agents/dashboard/packages/local-runtime/src/server-routes.test.ts +60 -0
  142. package/templates/.agents/dashboard/packages/local-runtime/src/server-run-projections.test.ts +12 -2
  143. package/templates/.agents/dashboard/packages/local-runtime/src/server-telemetry-command.test.ts +29 -4
  144. package/templates/.agents/dashboard/packages/local-runtime/src/server-telemetry-refresh.ts +7 -0
  145. package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +51 -54
  146. package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +28 -45
  147. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-filter-matrix.test.ts +5 -0
  148. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-invocation-page.test.ts +49 -0
  149. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-invocation-page.ts +44 -1
  150. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-cached-cost-page.ts +11 -10
  151. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-summary.ts +1 -1
  152. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-work-item-index.test.ts +18 -1
  153. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-build.mjs +12 -5
  154. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-paths.mjs +8 -0
  155. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +1 -0
  156. package/templates/.agents/dashboard/packages/ui/package.json +1 -1
  157. package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
  158. package/templates/.agents/dashboard/tests/e2e/qualify-top-five-trace.mjs +53 -0
  159. package/templates/.agents/dashboard/tests/e2e/verify-top-five-served.mjs +78 -0
  160. package/templates/.agents/design/.zaip-managed.json +14 -6
  161. package/templates/.agents/design/apps/catalog/dist/assets/index-BGxXxXTo.js +72 -0
  162. package/templates/.agents/design/apps/catalog/dist/index.html +1 -1
  163. package/templates/.agents/design/apps/catalog/package.json +1 -1
  164. package/templates/.agents/design/apps/catalog/src/components/TopEntitiesSpecimen.tsx +45 -0
  165. package/templates/.agents/design/apps/catalog/src/pages/ComponentsPage.tsx +3 -1
  166. package/templates/.agents/design/apps/catalog/src/stories/Components.stories.tsx +2 -0
  167. package/templates/.agents/design/packages/local-runtime/package.json +1 -1
  168. package/templates/.agents/requirements/autonomous-assurance.md +11 -2
  169. package/templates/.agents/requirements/cloud-hostinger-autonomy.md +1 -1
  170. package/templates/.agents/requirements/comparative-audit.md +1 -1
  171. package/templates/.agents/requirements/context-engine.md +1 -1
  172. package/templates/.agents/requirements/cost-observability.md +1 -1
  173. package/templates/.agents/requirements/dashboard-launch.md +1 -1
  174. package/templates/.agents/requirements/data-export.md +1 -1
  175. package/templates/.agents/requirements/design-system.md +1 -1
  176. package/templates/.agents/requirements/execution-engine.md +1 -1
  177. package/templates/.agents/requirements/kanban-dashboard.md +1 -1
  178. package/templates/.agents/requirements/model-orchestration.md +1 -1
  179. package/templates/.agents/requirements/public-distribution.md +1 -1
  180. package/templates/.agents/requirements/software-architecture.md +1 -1
  181. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  182. package/templates/.agents/requirements/work-lifecycle.md +2 -1
  183. package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
  184. package/templates/.agents/rules/run-lifecycle-closure.md +2 -1
  185. package/templates/.agents/rules/workflow.md +1 -0
  186. package/templates/.agents/runtime/VERSION +1 -1
  187. package/templates/.agents/runtime/bin/zaip.mjs +1178 -764
  188. package/templates/.agents/runtime/checksums.sha256 +6 -6
  189. package/templates/.agents/runtime/manifest.json +1 -1
  190. package/templates/.agents/runtime/pnpm-lock.sha256 +1 -1
  191. package/templates/.agents/runtime/provenance.json +5 -5
  192. package/templates/.agents/runtime/sbom.cdx.json +59 -59
  193. package/templates/.agents/skills/zaip-skill-execution/SKILL.md +1 -1
  194. package/templates/.agents/skills/zaip-skill-execution/references/controlled-release-recovery.md +14 -0
  195. package/templates/.agents/skills/zaip-skill-execution/references/runtime-governance.md +1 -1
  196. package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +5 -1
  197. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/deploy-contract-cli.test.mjs +53 -0
  198. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/deploy-contract.mjs +12 -0
  199. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/deploy-contract.test.mjs +26 -32
  200. package/templates/.agents/skills/zaip-skill-maintenance-enter/SKILL.md +23 -0
  201. package/templates/.agents/skills/zaip-skill-maintenance-enter/agents/openai.yaml +4 -0
  202. package/templates/.agents/skills/zaip-skill-maintenance-enter/scripts/maintenance.mjs +213 -0
  203. package/templates/.agents/skills/zaip-skill-maintenance-enter/scripts/maintenance.test.mjs +207 -0
  204. package/templates/.agents/skills/zaip-skill-maintenance-exit/SKILL.md +21 -0
  205. package/templates/.agents/skills/zaip-skill-maintenance-exit/agents/openai.yaml +4 -0
  206. package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +2 -0
  207. package/templates/.agents/skills/zaip-skill-release-qualification/references/local-preparation.md +37 -8
  208. package/templates/.agents/zaip-aios/VERSION +1 -1
  209. package/templates/.agents/zaip-aios/guides/10-seguranca.md +2 -2
  210. package/templates/.agents/zaip-aios/guides/26-qualidade-e-release.md +38 -0
  211. package/templates/template-manifest.json +259 -135
  212. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-Co2Jiuzh.js +0 -68
  213. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-qVSJnJ0_.js +0 -2
@@ -0,0 +1,213 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import {
3
+ closeSync,
4
+ existsSync,
5
+ lstatSync,
6
+ mkdirSync,
7
+ openSync,
8
+ readFileSync,
9
+ realpathSync,
10
+ renameSync,
11
+ unlinkSync,
12
+ writeFileSync,
13
+ } from "node:fs";
14
+ import { dirname, resolve } from "node:path";
15
+ import { pathToFileURL } from "node:url";
16
+ import { parseDocument } from "../../zaip-skill-github-deploy/scripts/yaml-parser.mjs";
17
+
18
+ const hash = (value) => createHash("sha256").update(value).digest("hex");
19
+
20
+ function physical(root, parts, create = false) {
21
+ let current = root;
22
+ for (const part of parts) {
23
+ current = resolve(current, part);
24
+ if (create && !existsSync(current)) mkdirSync(current);
25
+ if (lstatSync(current).isSymbolicLink()) throw Error(`Linked maintenance path: ${current}`);
26
+ }
27
+ return current;
28
+ }
29
+
30
+ function atomic(path, content, expected) {
31
+ if (existsSync(path) && lstatSync(path).isSymbolicLink()) throw Error("Linked output rejected");
32
+ const temporary = resolve(dirname(path), `.maintenance-${randomUUID()}.tmp`);
33
+ try {
34
+ writeFileSync(temporary, content, {
35
+ flag: "wx",
36
+ mode: existsSync(path) ? lstatSync(path).mode & 0o777 : 0o600,
37
+ });
38
+ if (expected !== undefined && readFileSync(path, "utf8") !== expected)
39
+ throw Error("Configuration changed concurrently; retry after coordinating writers");
40
+ renameSync(temporary, path);
41
+ } finally {
42
+ if (existsSync(temporary)) unlinkSync(temporary);
43
+ }
44
+ }
45
+
46
+ function inspect(source) {
47
+ if (Buffer.byteLength(source) > 65536) throw Error("Project policy exceeds the hook input limit");
48
+ const doc = parseDocument(source, { strict: true, uniqueKeys: true });
49
+ if (doc.errors.length || doc.warnings.length) throw Error("Invalid or unsupported project YAML");
50
+ // Accept the canonical block form only. Do not execute JavaScript from --root.
51
+ for (const name of ["zaip", "tracking"]) {
52
+ const pair = doc.contents?.items?.find((item) => item.key?.value === name);
53
+ const section = pair?.value;
54
+ const enabled = section?.items?.find((item) => item.key?.value === "enabled");
55
+ const key = pair?.key;
56
+ if (
57
+ !key?.range ||
58
+ !enabled?.key?.range ||
59
+ section.flow ||
60
+ section.anchor ||
61
+ section.tag ||
62
+ source.slice(key.range[0], key.range[1]) !== name ||
63
+ (key.range[0] > 0 && source[key.range[0] - 1] !== "\n") ||
64
+ !new RegExp("^" + name + ":[ \\t]*(?:#[^\\r\\n]*)?\\r?\\n").test(
65
+ source.slice(key.range[0]),
66
+ ) ||
67
+ source.slice(enabled.key.range[0], enabled.key.range[1]) !== "enabled"
68
+ ) {
69
+ throw Error("Use canonical unquoted zaip/tracking blocks with literal enabled keys");
70
+ }
71
+ const lineStart = source.lastIndexOf("\n", enabled.key.range[0] - 1) + 1;
72
+ if (
73
+ !/^ +$/.test(source.slice(lineStart, enabled.key.range[0])) ||
74
+ !enabled.value?.range ||
75
+ !/^: +$/.test(source.slice(enabled.key.range[1], enabled.value.range[0]))
76
+ ) {
77
+ throw Error("Use canonical enabled: true/false on one indented line");
78
+ }
79
+ }
80
+ const nodes = ["zaip", "tracking"].map((key) => doc.getIn([key, "enabled"], true));
81
+ for (const node of nodes) {
82
+ if (
83
+ !node ||
84
+ typeof node.value !== "boolean" ||
85
+ node.anchor ||
86
+ node.tag ||
87
+ !node.range ||
88
+ !/^(true|false)$/.test(source.slice(node.range[0], node.range[1]))
89
+ ) {
90
+ throw Error("zaip.enabled and tracking.enabled must be explicit literal booleans");
91
+ }
92
+ }
93
+ const policy = { governance: nodes[0].value, tracking: nodes[1].value };
94
+ return { nodes, policy };
95
+ }
96
+
97
+ export async function maintenance(action, directory = process.cwd()) {
98
+ if (!["enter", "exit", "status"].includes(action))
99
+ throw Error("Use enter, exit or status [--root <directory>]");
100
+ const root = realpathSync(resolve(directory));
101
+ const config = physical(root, [".agents", "config", "project.yaml"]);
102
+ const hook = physical(root, [".codex", "hooks", "zaip-hook-activation.mjs"]);
103
+ const hookSource = readFileSync(hook, "utf8");
104
+ if (
105
+ !hookSource.includes("export function parseHookPolicies(") ||
106
+ !hookSource.includes("export async function hookPolicies(")
107
+ )
108
+ throw Error(
109
+ "Update the four hooks to support independent governance and tracking before maintenance",
110
+ );
111
+ let source = readFileSync(config, "utf8");
112
+ let parsed = inspect(source);
113
+ const result = (state, changed) => ({
114
+ action,
115
+ root,
116
+ zaip_enabled: parsed.policy.governance,
117
+ tracking_enabled: parsed.policy.tracking,
118
+ phase: state?.phase ?? null,
119
+ changed,
120
+ config_sha256: hash(source),
121
+ telemetry: "verify_native_hook_observation",
122
+ hook_check: "interface_presence_only",
123
+ });
124
+ if (action === "status") {
125
+ const path = resolve(root, ".local/zaip-maintenance/state.json");
126
+ if (!existsSync(path)) return result(null, false);
127
+ physical(root, [".local", "zaip-maintenance", "state.json"]);
128
+ const state = JSON.parse(readFileSync(path, "utf8"));
129
+ if (state.schema_version !== 1 || state.root !== root)
130
+ throw Error("Invalid maintenance receipt");
131
+ return result(state, false);
132
+ }
133
+ const local = physical(root, [".local", "zaip-maintenance"], true);
134
+ const lock = resolve(local, "transition.lock");
135
+ let fd;
136
+ try {
137
+ fd = openSync(lock, "wx", 0o600);
138
+ } catch (error) {
139
+ if (error.code === "EEXIST")
140
+ throw Error(
141
+ "Maintenance transition locked; inspect transition.lock and coordinate its owner",
142
+ );
143
+ throw error;
144
+ }
145
+ try {
146
+ writeFileSync(fd, JSON.stringify({ pid: process.pid, created_at: new Date().toISOString() }));
147
+ source = readFileSync(config, "utf8");
148
+ parsed = inspect(source);
149
+ const statePath = resolve(local, "state.json");
150
+ let state = null;
151
+ if (existsSync(statePath)) {
152
+ physical(root, [".local", "zaip-maintenance", "state.json"]);
153
+ state = JSON.parse(readFileSync(statePath, "utf8"));
154
+ if (state.schema_version !== 1 || state.root !== root)
155
+ throw Error("Invalid maintenance receipt");
156
+ }
157
+ const desired = action === "exit";
158
+ const phase = desired ? "inactive" : "active";
159
+ if (state?.phase === phase && parsed.policy.governance === desired && parsed.policy.tracking)
160
+ return result(state, false);
161
+ if (!state || (action === "enter" && state.phase === "inactive")) {
162
+ state = {
163
+ schema_version: 1,
164
+ root,
165
+ started_at: new Date().toISOString(),
166
+ previous: {
167
+ zaip_enabled: parsed.policy.governance,
168
+ tracking_enabled: parsed.policy.tracking,
169
+ },
170
+ initial_config_sha256: hash(source),
171
+ };
172
+ }
173
+ state.phase = desired ? "exiting" : "entering";
174
+ atomic(statePath, `${JSON.stringify(state, null, 2)}\n`);
175
+ let next = source;
176
+ const replacements = parsed.nodes
177
+ .map((node, index) => ({
178
+ start: node.range[0],
179
+ end: node.range[1],
180
+ value: String(index === 0 ? desired : true),
181
+ }))
182
+ .sort((a, b) => b.start - a.start);
183
+ for (const edit of replacements)
184
+ next = next.slice(0, edit.start) + edit.value + next.slice(edit.end);
185
+ inspect(next);
186
+ const changed = next !== source;
187
+ if (changed) atomic(config, next, source);
188
+ source = readFileSync(config, "utf8");
189
+ parsed = inspect(source);
190
+ if (parsed.policy.governance !== desired || !parsed.policy.tracking)
191
+ throw Error("Transition verification failed");
192
+ state.phase = phase;
193
+ state.updated_at = new Date().toISOString();
194
+ state.config_sha256 = hash(source);
195
+ atomic(statePath, `${JSON.stringify(state, null, 2)}\n`);
196
+ return result(state, changed);
197
+ } finally {
198
+ closeSync(fd);
199
+ unlinkSync(lock);
200
+ }
201
+ }
202
+
203
+ if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
204
+ const [action, flag, directory, ...extra] = process.argv.slice(2);
205
+ try {
206
+ if (extra.length || (flag !== undefined && (flag !== "--root" || !directory)))
207
+ throw Error("Use enter, exit or status [--root <directory>]");
208
+ console.log(JSON.stringify(await maintenance(action, directory)));
209
+ } catch (error) {
210
+ console.error(`Maintenance transition failed: ${error.message}`);
211
+ process.exitCode = 1;
212
+ }
213
+ }
@@ -0,0 +1,207 @@
1
+ import assert from "node:assert/strict";
2
+ import { spawnSync } from "node:child_process";
3
+ import {
4
+ copyFileSync,
5
+ existsSync,
6
+ mkdirSync,
7
+ mkdtempSync,
8
+ readFileSync,
9
+ rmSync,
10
+ symlinkSync,
11
+ writeFileSync,
12
+ } from "node:fs";
13
+ import { tmpdir } from "node:os";
14
+ import { resolve } from "node:path";
15
+ import { test } from "node:test";
16
+ import { maintenance } from "./maintenance.mjs";
17
+
18
+ const sourceRoot = resolve(import.meta.dirname, "../../../..");
19
+ // Public-template tests use the installed hook contract from the builder workspace.
20
+ const hookRoot = existsSync(resolve(sourceRoot, ".codex/hooks/zaip-hook-activation.mjs"))
21
+ ? sourceRoot
22
+ : resolve(sourceRoot, "../../../..");
23
+ const original =
24
+ "# preserved\r\nzaip:\r\n enabled: true # governance\r\ntracking:\r\n enabled: true\r\n storage_mode: tracked_sanitized\r\nproject:\r\n name: original\r\n";
25
+ function fixture(t, source = original) {
26
+ const root = mkdtempSync(resolve(tmpdir(), "zaip-maintenance-test-"));
27
+ t.after(() => rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 50 }));
28
+ mkdirSync(resolve(root, ".agents/config"), { recursive: true });
29
+ mkdirSync(resolve(root, ".codex/hooks"), { recursive: true });
30
+ const config = resolve(root, ".agents/config/project.yaml");
31
+ writeFileSync(config, source);
32
+ copyFileSync(
33
+ resolve(hookRoot, ".codex/hooks/zaip-hook-activation.mjs"),
34
+ resolve(root, ".codex/hooks/zaip-hook-activation.mjs"),
35
+ );
36
+ return {
37
+ root,
38
+ config,
39
+ read: () => readFileSync(config, "utf8"),
40
+ state: resolve(root, ".local/zaip-maintenance/state.json"),
41
+ };
42
+ }
43
+
44
+ test("enter and exit retain telemetry, comments and CRLF; repetition is idempotent", async (t) => {
45
+ const f = fixture(t);
46
+ const entered = await maintenance("enter", f.root);
47
+ assert.equal(entered.zaip_enabled, false);
48
+ assert.equal(entered.tracking_enabled, true);
49
+ assert.equal(
50
+ f.read(),
51
+ original.replace("enabled: true # governance", "enabled: false # governance"),
52
+ );
53
+ const state = readFileSync(f.state, "utf8");
54
+ assert.equal((await maintenance("status", f.root)).phase, "active");
55
+ assert.equal((await maintenance("enter", f.root)).changed, false);
56
+ assert.equal(readFileSync(f.state, "utf8"), state);
57
+ assert.equal((await maintenance("exit", f.root)).zaip_enabled, true);
58
+ assert.equal(f.read(), original);
59
+ assert.equal((await maintenance("exit", f.root)).changed, false);
60
+ });
61
+
62
+ test("exit preserves configuration edits made during maintenance", async (t) => {
63
+ const f = fixture(t);
64
+ await maintenance("enter", f.root);
65
+ writeFileSync(f.config, f.read().replace("name: original", "name: changed"));
66
+ await maintenance("exit", f.root);
67
+ assert.equal(f.read(), original.replace("name: original", "name: changed"));
68
+ });
69
+
70
+ test("manual disabled state and disabled tracking become active telemetry and exit restores governance", async (t) => {
71
+ const f = fixture(t, original.replaceAll("enabled: true", "enabled: false"));
72
+ const entered = await maintenance("enter", f.root);
73
+ assert.equal(entered.zaip_enabled, false);
74
+ assert.equal(entered.tracking_enabled, true);
75
+ assert.equal((await maintenance("exit", f.root)).zaip_enabled, true);
76
+ assert.equal(f.read(), original);
77
+ });
78
+
79
+ test("exit without a prior receipt supports manual maintenance", async (t) => {
80
+ const f = fixture(
81
+ t,
82
+ original.replace("enabled: true # governance", "enabled: false # governance"),
83
+ );
84
+ assert.equal((await maintenance("exit", f.root)).tracking_enabled, true);
85
+ assert.equal(f.read(), original);
86
+ });
87
+
88
+ test("status never changes configuration or creates local state", async (t) => {
89
+ const f = fixture(t);
90
+ assert.equal((await maintenance("status", f.root)).zaip_enabled, true);
91
+ assert.equal(existsSync(resolve(f.root, ".local")), false);
92
+ assert.equal(f.read(), original);
93
+ });
94
+
95
+ test("never executes hook code supplied by the target directory", async (t) => {
96
+ const f = fixture(t);
97
+ writeFileSync(
98
+ resolve(f.root, ".codex/hooks/zaip-hook-activation.mjs"),
99
+ 'throw Error("Target code must not execute");\nexport function parseHookPolicies() {}\nexport async function hookPolicies() {}\n',
100
+ );
101
+ assert.equal((await maintenance("status", f.root)).zaip_enabled, true);
102
+ assert.equal((await maintenance("enter", f.root)).tracking_enabled, true);
103
+ assert.equal((await maintenance("exit", f.root)).zaip_enabled, true);
104
+ });
105
+
106
+ for (const [label, source] of [
107
+ ["string boolean", original.replace("enabled: true # governance", 'enabled: "true"')],
108
+ ["duplicate control", original.replace("zaip:", "zaip:\n enabled: false")],
109
+ ["missing tracking", "zaip:\n enabled: true\n"],
110
+ ["malformed YAML", `${original}broken: [\n`],
111
+ ["alias control", original.replace("enabled: true # governance", "enabled: &flag true")],
112
+ ["hook-incompatible key", original.replace("zaip:", '"zaip":')],
113
+ ["explicit enabled key", original.replace("enabled: true # governance", "? enabled\r\n : true")],
114
+ ["space before colon", original.replace("enabled: true # governance", "enabled : true")],
115
+ ]) {
116
+ test(`rejects ${label} before mutation`, async (t) => {
117
+ const f = fixture(t, source);
118
+ await assert.rejects(maintenance("enter", f.root));
119
+ assert.equal(f.read(), source);
120
+ assert.equal(existsSync(resolve(f.root, ".local")), false);
121
+ });
122
+ }
123
+
124
+ test("contention refuses a second transition without touching the owner lock", async (t) => {
125
+ const f = fixture(t);
126
+ const dir = resolve(f.root, ".local/zaip-maintenance");
127
+ mkdirSync(dir, { recursive: true });
128
+ const lock = resolve(dir, "transition.lock");
129
+ writeFileSync(lock, "existing owner");
130
+ await assert.rejects(maintenance("enter", f.root), /locked/);
131
+ assert.equal(readFileSync(lock, "utf8"), "existing owner");
132
+ assert.equal(f.read(), original);
133
+ });
134
+
135
+ test("interrupted receipt can be reconciled without resetting the original snapshot", async (t) => {
136
+ const f = fixture(t);
137
+ await maintenance("enter", f.root);
138
+ const state = JSON.parse(readFileSync(f.state, "utf8"));
139
+ state.phase = "entering";
140
+ writeFileSync(f.state, JSON.stringify(state));
141
+ assert.equal((await maintenance("enter", f.root)).changed, false);
142
+ assert.equal(
143
+ JSON.parse(readFileSync(f.state, "utf8")).initial_config_sha256,
144
+ state.initial_config_sha256,
145
+ );
146
+ assert.equal((await maintenance("exit", f.root)).zaip_enabled, true);
147
+ });
148
+
149
+ test("linked configuration directories cannot mutate another project", async (t) => {
150
+ const target = fixture(t);
151
+ const f = fixture(t);
152
+ rmSync(resolve(f.root, ".agents/config"), { recursive: true });
153
+ symlinkSync(
154
+ resolve(target.root, ".agents/config"),
155
+ resolve(f.root, ".agents/config"),
156
+ "junction",
157
+ );
158
+ t.after(() => {
159
+ if (existsSync(resolve(f.root, ".agents/config"))) rmSync(resolve(f.root, ".agents/config"));
160
+ });
161
+ await assert.rejects(maintenance("enter", f.root), /Linked/);
162
+ assert.equal(target.read(), original);
163
+ });
164
+
165
+ test("CLI works from another cwd with an explicit root and rejects extra arguments", (t) => {
166
+ const f = fixture(t);
167
+ const script = resolve(import.meta.dirname, "maintenance.mjs");
168
+ const run = (...args) =>
169
+ spawnSync(process.execPath, [script, ...args], {
170
+ cwd: tmpdir(),
171
+ encoding: "utf8",
172
+ windowsHide: true,
173
+ });
174
+ const entered = run("enter", "--root", f.root);
175
+ assert.equal(entered.status, 0, entered.stderr);
176
+ assert.equal(JSON.parse(entered.stdout).tracking_enabled, true);
177
+ const before = f.read();
178
+ assert.equal(run("exit", "--root", f.root, "extra").status, 1);
179
+ assert.equal(f.read(), before);
180
+ assert.equal(run("exit", "--root", f.root).status, 0);
181
+ });
182
+
183
+ test("installed helper runs without node_modules or the builder checkout", (t) => {
184
+ const f = fixture(t);
185
+ const script = resolve(
186
+ f.root,
187
+ ".agents/skills/zaip-skill-maintenance-enter/scripts/maintenance.mjs",
188
+ );
189
+ const parser = resolve(f.root, ".agents/skills/zaip-skill-github-deploy/scripts/yaml-parser.mjs");
190
+ mkdirSync(resolve(script, ".."), { recursive: true });
191
+ mkdirSync(resolve(parser, ".."), { recursive: true });
192
+ copyFileSync(resolve(import.meta.dirname, "maintenance.mjs"), script);
193
+ copyFileSync(
194
+ resolve(import.meta.dirname, "../../zaip-skill-github-deploy/scripts/yaml-parser.mjs"),
195
+ parser,
196
+ );
197
+ for (const action of ["enter", "exit"]) {
198
+ const result = spawnSync(process.execPath, [script, action], {
199
+ cwd: f.root,
200
+ encoding: "utf8",
201
+ windowsHide: true,
202
+ });
203
+ assert.equal(result.status, 0, result.stderr);
204
+ assert.equal(JSON.parse(result.stdout).tracking_enabled, true);
205
+ }
206
+ assert.equal(f.read(), original);
207
+ });
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: zaip-skill-maintenance-exit
3
+ description: Finish authorized ZAIP maintenance by reactivating governance, retaining telemetry, and verifying the next native hook invocation.
4
+ ---
5
+
6
+ # Sair da manutenção
7
+
8
+ Use ao concluir manutenção autorizada ou quando o usuário pedir reativação. Funciona também após desativação manual sem recibo prévio. No agente principal, termine ou coordene os escritores de manutenção antes de reativar a governança compartilhada do projeto.
9
+
10
+ 1. Execute na raiz, com o Node do host:
11
+
12
+ ```text
13
+ node .agents/skills/zaip-skill-maintenance-enter/scripts/maintenance.mjs exit
14
+ ```
15
+
16
+ O [script compartilhado](../zaip-skill-maintenance-enter/scripts/maintenance.mjs) também aceita `status` e `--root <diretório>`. Depende da skill de entrada e do parser YAML distribuído; não exige Node instalado no projeto.
17
+ 2. Exija `zaip_enabled: true` e `tracking_enabled: true` na saída. A saída reativa ZAIP mesmo quando ele já estava desligado antes da entrada, e mantém tracking ligado. Ela altera somente esses booleanos no arquivo atual: preserva edições de configuração feitas durante a manutenção. Não restaure um backup integral nem desligue tracking ao sair. Repetir a saída é seguro.
18
+ 3. Faça uma nova chamada nativa de leitura. Confira `.local/hooks/activation/PreToolUse.json` e o recibo de observação da sessão/turno realmente vistos. Se os hooks estiverem desligados na interface, peça sua reativação e deixe a validação pendente; não falsifique recibos. Não execute comandos destrutivos, de energia do computador ou publicações como teste.
19
+ 4. A partir da chamada seguinte, volte a aplicar a governança ativa. Informe estado final, testes observados e qualquer lacuna de telemetria. Não declare encerramento de Tasks/SPECs históricas nem totais finais de consumo sem prova.
20
+
21
+ Se houver falha, execute `status` e leia o erro. A gravação atômica mantém a configuração anterior quando a substituição falha; uma interrupção posterior pode deixar a transição aplicada e o recibo pendente. Repita a mesma operação após resolver a causa. Lock ocupado impede transições simultâneas: verifique o processo registrado, sem apagar um lock de processo ativo. Nunca desligue os hooks ou tracking para contornar o erro.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Sair da manutenção"
3
+ short_description: "Reativa o ZAIP preservando a telemetria"
4
+ default_prompt: "Use $zaip-skill-maintenance-exit para sair da manutenção e verificar o ZAIP ativo."
@@ -71,6 +71,8 @@ The framework release cut uses `node scripts/release-cycle-gate.mjs freeze --rep
71
71
 
72
72
  For an authorized Task-first request that combines a product fix and its release in one direct Task root, use the explicit `--integrated-task` freeze option with that Task and active root Run. The Task must be critical, target the current release, own the release-cycle config scope and have a delivery Execution bound to its Change. `audit` and `advance` authenticate its committed Task and Run start, while all other current-release work, secondary worktrees and remote branches still block. This route avoids creating a second root Run or asking the user for a new turn solely to publish already authorized work. Do not use it for a delegated SPEC release Task or as a general waiver for release checks.
73
73
 
74
+ For an authorized SPEC whose final critical Task combines implementation and publication, use the separate explicit `--integrated-spec-task` option with its delegated delivery Run. It requires the exact active macro Run, SPEC, Change and delivery Execution, a unique terminal Task in the committed DAG, all predecessors completed, the current target release and the literal `.agents/config/release-cycle.json` write scope. The persisted `integrated_spec_task` mode is rechecked at audit and advance; unknown modes fail closed. It cannot be combined with `--integrated-task`, which remains exclusive to direct Task roots. Broad product scopes alone never grant this mode. Clean candidate, committed coordinator records, unrelated open-work exclusion, exact-SHA CI, signed artifact and npm gates remain mandatory.
75
+
74
76
  For the one-time 4.5→4.6 recovery, `adopt-published` requires the published 4.5 tag to be an ancestor of remote `main`, remote `main` to be an ancestor of clean local `main`, and observed stable GitHub Release/npm integrity. Pass the exact owner `--owner-spec`, `--owner-execution`, `--owner-run`, planned `--release-task` and active delegated Task orchestrator `--actor-run`. That actor must own the release Task's unique direct predecessor; all earlier DAG Tasks must be completed. Only the actor Task, planned release Task and owner SPEC are exempt from the open-work gate. After review/Evidence and a clean metadata checkpoint, perform adoption while that predecessor Task and its actor Run are still active. Then use `spec retarget-release SPEC --from 4.5 --to 4.6 --run DELEGATED_TASK_RUN` with the same actor Run. Close the predecessor Task through Gui only after retarget; start the release Task afterward. The revision records adoption SHA and actor Run, and the release Task's missing target resolves through its owner SPEC. Do not edit records directly to retarget.
75
77
 
76
78
  After exact Release, npm and candidate CI are observed, `advance --from N.N --to NEXT --sha CANDIDATE --ci-run-id ID` opens the next cycle while the coordinator remains active. Bind Task/SPEC Evidence to the immutable published candidate before Gui, then close Task and parent SPEC. Make one reviewed metadata-only closure commit; push that exact local main SHA through `scripts/local-release-deploy.mjs push-closure` with published SHA, expected remote SHA and the exact metadata path inventory. The tag remains on the published candidate. Confirm CI on the new main SHA; local closure alone is not complete publication. This contract does not prove provider deployment.
@@ -6,7 +6,7 @@ Preparation does not authorize publication. Use guarded delivery only for the re
6
6
 
7
7
  The project-owned `.agents/config/deploy-policy.json` (schema version 1, `default_mode: auto|commits|release`) is separate from the builder's signed qualification policy below. Installing skills in a consumer never grants builder capability or requires builder keys/protected settings.
8
8
  Store keys, trust stores, receipts and artifacts outside the repository. Commit and synchronize first;
9
- every gate is bound to the resulting clean SHA. Repair changes require a new candidate.
9
+ every gate is bound to the resulting clean SHA. Before expensive gates, validate the active coordinator route: release-only, direct `--integrated-task`, or final SPEC `--integrated-spec-task` as defined in the canonical qualification skill. Repair changes require a new candidate.
10
10
  Qualification uses an independent local Git clone at that exact SHA, with copied
11
11
  objects and complete commit history, not a worktree sharing the caller's registry.
12
12
  This prevents dashboard source discovery from importing the main checkout or other
@@ -15,7 +15,7 @@ unchanged. Cleanup retries transient Windows locks and preserves the original ga
15
15
  error if cleanup also fails. A cleanup failure never produces a success receipt.
16
16
 
17
17
  When the ZAIP Codex PreToolUse hook is enabled, run release preparation, verification and
18
- guarded delivery as separate literal commands. Its external-path exception is limited to
18
+ guarded delivery as separate literal commands. In repository-restricted profiles, its external-path exception is limited to
19
19
  the reviewed release helpers, the declared SHA and version, the matching candidate
20
20
  directory under `~/.codex/release-candidates/zaip-aios/`, and key material under
21
21
  `~/.codex/release-keys/zaip-aios/<key-id>/`. It does not permit arbitrary home
@@ -24,10 +24,19 @@ unrelated path or compound command is an intentional safety decision, not a fail
24
24
  release gate. Persistent repository edits additionally require a current Task Run with
25
25
  the exact Codex thread and turn correlation.
26
26
 
27
+ The configured `zaip-aios-full-access` profile also permits ordinary external
28
+ read/write/execute, working-directory, and network access. The restrictions above
29
+ describe the narrow exception for repository-restricted profiles, not a blanket
30
+ denial of configured full access. Neither profile bypasses secret protection,
31
+ destructive-operation controls, lifecycle authority, stricter child permissions,
32
+ or the ban on computer power/session actions. Release helpers still verify
33
+ their exact repository, candidate, signing material, receipt, and authorization.
34
+
27
35
  For native `exec_command`, the hook validates both the chat's `cwd` and the command's
28
36
  explicit absolute `workdir`. A registered worktree may be the execution root even
29
37
  when the chat remains in the primary checkout. Unregistered roots, links, relative
30
- overrides and missing exact worktree Run authority remain blocked; a primary
38
+ overrides remain subject to the configured access profile. Missing exact worktree
39
+ Run authority for governed product mutations remains blocked; a primary
31
40
  checkout's Task is never a global fallback for mutations in another checkout.
32
41
 
33
42
  Some hosts present these commands as `Bash` without exposing a workdir override.
@@ -35,14 +44,15 @@ In that case, invoke the literal reviewed helper from the chat checkout and pass
35
44
  the registered worktree in `--repository`. Only the helper may target that explicit
36
45
  root, after physical-root, Git registration and common-directory verification;
37
46
  its own preflight checks the exact clean SHA before any gate. This is not an
38
- exception for arbitrary commands or filesystem access.
47
+ exception for arbitrary commands or filesystem access in a restricted profile.
39
48
 
40
49
  ## Verified builder signing material
41
50
 
42
51
  The following key and protected-policy requirements apply only to the verified ZAIP builder, not ordinary consumer GitHub releases.
43
52
 
44
53
  The signing key ID is the trusted identity, not a filename. Resolve it with
45
- `gh variable get ZAIP_LOCAL_RELEASE_TRUSTED_KEY_ID --repo zaip-ai/zaip-aios`.
54
+ `gh variable get ZAIP_LOCAL_RELEASE_TRUSTED_KEY_ID` from the verified builder
55
+ checkout after checking its configured origin.
46
56
  By default, the private key lives at
47
57
  `~/.codex/release-keys/zaip-aios/<key-id>/release-private.pem` and its local
48
58
  trust store at `~/.codex/release-keys/zaip-aios/<key-id>/trust/` on the current
@@ -173,8 +183,11 @@ node scripts/local-release-preparation.mjs stage-inputs --sha <40-character-sha>
173
183
 
174
184
  `stage-inputs` accepts no source, receipt, output, home, key or policy path flags. It
175
185
  derives the candidate directory, verifies clean `main`, canonical origin, the signed
176
- receipt, v4.6 essential profile, trusted `maintainer-v4` key and policy digest, the
177
- exact release inventory, and a direct human request resolved as builder Release 4.6.
186
+ receipt, the selected essential profile, trusted `maintainer-v4` key and policy digest,
187
+ the exact release inventory, and a direct human request resolved as that builder Release.
188
+ Explicit major transitions such as `4.9 → 5.0` are supported. The inventory must
189
+ start at the highest canonical stable ancestor tag below the requested version;
190
+ prerelease, unmerged, future and stale-range tags cannot substitute for it.
178
191
  It installs `deploy-request.txt`, `release-notes.md`, `release-inventory.json` and
179
192
  `deploy-contract.json` inside that candidate directory with complete-byte readback,
180
193
  idempotent retry and conflict rejection. The protected release helper reads the
@@ -191,11 +204,27 @@ node scripts/local-release-deploy.mjs --repository <absolute-repository> --expec
191
204
  `--dry-run` prepares and verifies without sending. The live command verifies again around
192
205
  delivery, sends the exact SHA, verifies the remote, creates a draft GitHub Release, uploads all
193
206
  four assets and publishes the release. Existing incompatible tags/assets fail without overwrite.
194
- The helper never invokes local npm publication.
207
+ The helper never invokes local npm publication. Durable `release-stage-*.json`
208
+ observations bind SHA/version/receipt digest and never replace fresh verification.
209
+ A retry recognizes an exact remote push, uploads only absent matching assets and
210
+ does not republish an already public matching Release. Conflicts fail closed.
211
+ The four assets must be regular files in the real candidate directory. The helper
212
+ observes npm version, latest and exact TGZ SRI with bounded propagation retries.
195
213
  Notes and inventory must satisfy [the release notes contract](../../zaip-skill-github-deploy/references/release-notes.md).
196
214
  For the first release, replace `--from` with explicit `--initial`. The helper validates the notes
197
215
  against the Git range before push and compares the draft and published bodies with those notes.
198
216
 
217
+ After release-cycle advancement and formal closure, the single metadata-only commit uses:
218
+
219
+ ```text
220
+ node scripts/local-release-deploy.mjs push-closure --repository ROOT --expected-repository zaip-ai/zaip-aios --branch main --version N.N --published-sha CANDIDATE --closure-sha CLOSURE --expected-remote-sha CANDIDATE --metadata-paths-file REVIEWED_JSON --receipt RECEIPT --tarball TGZ --policy POLICY --trust-store TRUST --notes-file NOTES --output-dir CANDIDATE_DIR
221
+ ```
222
+
223
+ This rechecks the valid signed receipt against the immutable published Git tree,
224
+ exact Release assets/body/latest, registry SRI/latest, recorded published CI and
225
+ reviewed metadata diff. Remote main may already equal CLOSURE after interruption;
226
+ retry then observes its CI without another push. Receipt expiry remains enforced.
227
+
199
228
  ## Installed consumer: independent GitHub release
200
229
 
201
230
  Auto mode defaults to commits plus push in a consumer. It needs scoped project checks and
@@ -1 +1 @@
1
- 4.9
1
+ 5.1
@@ -17,7 +17,7 @@ sistema operacional.
17
17
  execução de comandos dentro do perfil. Isso não é uma autorização de negócio ou
18
18
  de escopo: deploy, push/publicação, ações remotas, gastos, exclusões relevantes
19
19
  e mudanças fora do objetivo continuam exigindo pedido explícito do usuário no
20
- turno atual. Apps e MCPs podem manter seu próprio
20
+ contexto vigente da sessão; a autorização continua válida enquanto seu escopo não mudar. Apps e MCPs podem manter seu próprio
21
21
  `default_tools_approval_mode = "approve"`; esse ajuste é independente da
22
22
  política de aprovação de comandos.
23
23
 
@@ -141,7 +141,7 @@ O acesso completo é mitigado por defesa em profundidade, mas nenhuma camada tor
141
141
  `zaip-aios-full-access` equivalente ao perfil restrito:
142
142
 
143
143
  1. **Autorização explícita do usuário:** mudanças externas, destrutivas, publicação, deploy,
144
- gasto e mutações remotas exigem pedido explícito no turno atual.
144
+ gasto e mutações remotas exigem pedido explícito válido no contexto da sessão.
145
145
  2. **Escopo do repositório:** `AGENTS.md`, Rules e skills limitam o trabalho ao objetivo e
146
146
  proíbem inferir autoridade adicional a partir do acesso técnico.
147
147
  3. **Hook `PreToolUse` ativo nos dois perfis:** valida comandos e patches antes da execução; bloqueia escapes do
@@ -64,6 +64,18 @@ inválida ou integridade diferente impedem publicar. Após uma publicação
64
64
  autorizada, a confirmação do mesmo tarball usa retry finito de propagação.
65
65
  Esse controle não publica automaticamente quando a qualificação local passa.
66
66
 
67
+ Na v5.0, o publisher mantém checkpoints por SHA, versão e hash do recibo para
68
+ prepare/push/CI/assets/Release/npm/closure. A retomada sempre consulta o estado
69
+ remoto e revalida a assinatura: efeitos já confirmados não são reenviados.
70
+ Assets são quatro arquivos regulares no diretório real do candidato, com digest
71
+ exato no GitHub; links simbólicos e conflitos bloqueiam. A transição explícita
72
+ `4.9 → 5.0` usa a maior tag estável canônica ancestral como início do inventário.
73
+ O fechamento exige recibo/TGZ/política/trust/notas/diretório, confere a árvore Git
74
+ publicada e SRI/latest npm e aceita somente um commit revisado de metadados.
75
+ Se `main` já estiver nesse fechamento, apenas observa seu CI. A validade temporal
76
+ do recibo permanece obrigatória. Consulte a referência canônica
77
+ `zaip-skill-release-qualification/references/local-preparation.md` para os comandos.
78
+
67
79
  | Objetivo | Comando da raiz e alcance |
68
80
  | --- | --- |
69
81
  | Preparar artefatos | `corepack pnpm release:artifacts` compila e gera runtime/template. Não publica nem qualifica por si só. |
@@ -249,6 +261,30 @@ com testes de correção e uma release publicada não comprovam economia ou SLA.
249
261
  Não repita automaticamente a matriz histórica falha: preserve o diagnóstico e
250
262
  defina uma medição independente com artefatos identificados e falhas observadas.
251
263
 
264
+ ## Evolução de confiabilidade e documentação
265
+
266
+ A [matriz de evolução](https://github.com/zaip-ai/zaip-aios/blob/main/docs/quality/v50-documentacao-editorial.md)
267
+ vincula as dez frentes aos seus comandos, provas, rollback e limitações.
268
+ READMEs PT/EN descrevem o mesmo contrato: `essential-v3` por padrão,
269
+ `full-v2` somente quando selecionado, CI na `main` exata antes da Release,
270
+ smoke Linux do TGZ assinado antes do npm e confirmação da integridade publicada.
271
+ Preparar e validar localmente não comprovam publicação ou ativação dos hooks.
272
+
273
+ Uma Task explicitamente editorial `lite` aceita README literal ou Markdown
274
+ em escopo documental estreito, como `docs/quality/**`; `docs/**` amplo,
275
+ código, configuração e controles de agente não recebem a exceção. A dispensa
276
+ da Decision de seis etapas conserva candidato, check, Evidence, revisão e Gui.
277
+ Alterar esse mecanismo continua sendo trabalho crítico quando houver sinal de
278
+ segurança. `draft` persiste blueprints; `ready` materializa Tasks `planned`;
279
+ `execute` inicia o menor grão autorizado, sem inferir conclusão dos blueprints.
280
+
281
+ O resolver reconhece o pedido direto de retomar a SPEC até finalizar as Tasks
282
+ e publicar a versão explícita. Citação, negação, pergunta ou condição de
283
+ aprovação não concedem publicação. O override vale somente para o pedido.
284
+ Manutenção usa o mesmo `maintenance.mjs` da skill de entrada com `enter|exit`;
285
+ tracking fica ligado e a saída exige observação nativa. `full-access` conserva
286
+ proteções de segredos, destruição, lifecycle, filhos restritos e energia do PC.
287
+
252
288
  ## Ciclo corrente, limpeza e CI da main antes da Release
253
289
 
254
290
  O manifesto versionado `.agents/config/release-cycle.json` identifica `current_release` e estado `open`/`frozen` (4.5 e 4.5.0 são normalizados). Drafts de PRD/SPEC futuros são permitidos; ready/execução, novas Tasks e código exigem o release corrente. Depois de conciliar Tasks atuais, prove `main`, branches, worktrees e registros antes do candidato. Branch/worktree isolados são fechados com backup local recuperável; checkout compartilhado com diff de proveniência mista bloqueia. A existência de `main` ou de um teste verde isolado não qualifica a release.
@@ -262,3 +298,5 @@ Para congelar, use `node scripts/release-cycle-gate.mjs freeze --repository ROOT
262
298
  Nos modos ativos, depois das provas de publicação, registre validações e Evidence, realize revisão quando exigida e obtenha Gui como último filho. O host autorizado persiste a decisão real e o fechamento. Um commit posterior somente de records/metadata pode guardar esse encerramento; ele não requalifica o produto nem move a tag. O contrato executável está em `scripts/release-cycle-coordination.mjs` e `scripts/release-cycle-gate.mjs` no repositório mantenedor.
263
299
 
264
300
  Com candidato limpo em SHA exato, execute `node scripts/release-cycle-gate.mjs audit --repository ROOT --version VERSAO --sha SHA`. O deploy crítico/de release executa os checks locais nesse SHA, envia apenas `main` ao GitHub e espera `pre-main-candidate.yml` verde para o push exato antes da Release. Falha local bloqueia o push; falha de CI ou credenciais bloqueia a Release e exige reparo autorizado em `main`. Após observar tag, GitHub Release, main e CI exatos, `node scripts/release-cycle-gate.mjs advance --repository ROOT --from VERSAO --to PROXIMA --sha SHA --ci-run-id ID` registra a transição. As outras Tasks correntes devem estar terminais; somente a coordenação ativa validada acima pode permanecer aberta. Cada superfície, inclusive npm ou provedor, tem prova própria. O avanço não conclui automaticamente a Task de coordenação nem permite iniciar trabalho futuro antes da transição auditada.
301
+
302
+ Uma Task final de SPEC que combine implementação e publicação usa o modo explícito `--integrated-spec-task`, descrito na skill canônica de qualificação. Verifique essa elegibilidade antes dos gates caros; mantenha os predecessores concluídos e as provas válidas. Consulte [o diagnóstico v5.0](https://github.com/zaip-ai/zaip-aios/blob/main/docs/quality/v50-retrabalho-e-publicacao.md).