nexakit 0.0.0-stage → 0.2.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 (438) hide show
  1. package/.claude-plugin/marketplace.json +28 -0
  2. package/LICENSE +26 -0
  3. package/README.md +79 -2
  4. package/agents/claude/docs-researcher.md +9 -0
  5. package/agents/claude/implementation-tutor.md +9 -0
  6. package/agents/claude/project-explorer.md +9 -0
  7. package/agents/claude/quality-reviewer.md +9 -0
  8. package/agents/claude/requirements-analyst.md +9 -0
  9. package/agents/claude/solution-architect.md +9 -0
  10. package/agents/codex/docs-researcher.toml +10 -0
  11. package/agents/codex/implementation-tutor.toml +10 -0
  12. package/agents/codex/project-explorer.toml +10 -0
  13. package/agents/codex/quality-reviewer.toml +10 -0
  14. package/agents/codex/requirements-analyst.toml +11 -0
  15. package/agents/codex/solution-architect.toml +10 -0
  16. package/assets/brand/README.md +38 -0
  17. package/assets/brand/agent-toolkit-mark.png +0 -0
  18. package/assets/brand/agent-toolkit-mark.svg +13 -0
  19. package/assets/brand/agent-toolkit-tui-hero.png +0 -0
  20. package/assets/brand/nexakit-readme-hero.png +0 -0
  21. package/assets/brand/nexakit-readme-hero.svg +21 -0
  22. package/assets/runtime/package-lock.json +1425 -0
  23. package/bin/agent-task.js +14 -0
  24. package/bin/agent-toolkit-gemini.js +13 -0
  25. package/bin/agent-toolkit-inbox.js +14 -0
  26. package/bin/agent-toolkit-mcp.js +17 -0
  27. package/bin/agent-toolkit.js +13 -0
  28. package/bin/nexakit.js +13 -0
  29. package/bin/project-memory-mcp.js +22 -0
  30. package/bin/project-memory.js +7 -0
  31. package/catalogs/skills/api-design-principles/LICENSE.txt +21 -0
  32. package/catalogs/skills/api-design-principles/SKILL.md +110 -0
  33. package/catalogs/skills/api-design-principles/assets/api-design-checklist.md +155 -0
  34. package/catalogs/skills/api-design-principles/assets/rest-api-template.py +185 -0
  35. package/catalogs/skills/api-design-principles/references/details.md +413 -0
  36. package/catalogs/skills/api-design-principles/references/graphql-schema-design.md +589 -0
  37. package/catalogs/skills/api-design-principles/references/rest-best-practices.md +408 -0
  38. package/catalogs/skills/nodejs-backend-patterns/LICENSE.txt +21 -0
  39. package/catalogs/skills/nodejs-backend-patterns/SKILL.md +45 -0
  40. package/catalogs/skills/nodejs-backend-patterns/references/advanced-patterns.md +430 -0
  41. package/catalogs/skills/nodejs-backend-patterns/references/details.md +599 -0
  42. package/catalogs/skills/supabase-postgres-best-practices/CHANGELOG.md +73 -0
  43. package/catalogs/skills/supabase-postgres-best-practices/LICENSE.txt +21 -0
  44. package/catalogs/skills/supabase-postgres-best-practices/SKILL.md +64 -0
  45. package/catalogs/skills/supabase-postgres-best-practices/references/_contributing.md +170 -0
  46. package/catalogs/skills/supabase-postgres-best-practices/references/_sections.md +39 -0
  47. package/catalogs/skills/supabase-postgres-best-practices/references/_template.md +34 -0
  48. package/catalogs/skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -0
  49. package/catalogs/skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -0
  50. package/catalogs/skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -0
  51. package/catalogs/skills/supabase-postgres-best-practices/references/conn-limits.md +44 -0
  52. package/catalogs/skills/supabase-postgres-best-practices/references/conn-pooling.md +41 -0
  53. package/catalogs/skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -0
  54. package/catalogs/skills/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -0
  55. package/catalogs/skills/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -0
  56. package/catalogs/skills/supabase-postgres-best-practices/references/data-pagination.md +50 -0
  57. package/catalogs/skills/supabase-postgres-best-practices/references/data-upsert.md +50 -0
  58. package/catalogs/skills/supabase-postgres-best-practices/references/lock-advisory.md +56 -0
  59. package/catalogs/skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -0
  60. package/catalogs/skills/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -0
  61. package/catalogs/skills/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -0
  62. package/catalogs/skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -0
  63. package/catalogs/skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -0
  64. package/catalogs/skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -0
  65. package/catalogs/skills/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -0
  66. package/catalogs/skills/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -0
  67. package/catalogs/skills/supabase-postgres-best-practices/references/query-index-types.md +48 -0
  68. package/catalogs/skills/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -0
  69. package/catalogs/skills/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -0
  70. package/catalogs/skills/supabase-postgres-best-practices/references/schema-constraints.md +80 -0
  71. package/catalogs/skills/supabase-postgres-best-practices/references/schema-data-types.md +46 -0
  72. package/catalogs/skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -0
  73. package/catalogs/skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -0
  74. package/catalogs/skills/supabase-postgres-best-practices/references/schema-partitioning.md +55 -0
  75. package/catalogs/skills/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -0
  76. package/catalogs/skills/supabase-postgres-best-practices/references/security-privileges.md +54 -0
  77. package/catalogs/skills/supabase-postgres-best-practices/references/security-rls-basics.md +50 -0
  78. package/catalogs/skills/supabase-postgres-best-practices/references/security-rls-performance.md +63 -0
  79. package/catalogs/skills/vercel-composition-patterns/AGENTS.md +946 -0
  80. package/catalogs/skills/vercel-composition-patterns/LICENSE.txt +27 -0
  81. package/catalogs/skills/vercel-composition-patterns/README.md +60 -0
  82. package/catalogs/skills/vercel-composition-patterns/SKILL.md +89 -0
  83. package/catalogs/skills/vercel-composition-patterns/metadata.json +11 -0
  84. package/catalogs/skills/vercel-composition-patterns/rules/_sections.md +29 -0
  85. package/catalogs/skills/vercel-composition-patterns/rules/_template.md +24 -0
  86. package/catalogs/skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
  87. package/catalogs/skills/vercel-composition-patterns/rules/architecture-compound-components.md +112 -0
  88. package/catalogs/skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md +87 -0
  89. package/catalogs/skills/vercel-composition-patterns/rules/patterns-explicit-variants.md +100 -0
  90. package/catalogs/skills/vercel-composition-patterns/rules/react19-no-forwardref.md +42 -0
  91. package/catalogs/skills/vercel-composition-patterns/rules/state-context-interface.md +191 -0
  92. package/catalogs/skills/vercel-composition-patterns/rules/state-decouple-implementation.md +113 -0
  93. package/catalogs/skills/vercel-composition-patterns/rules/state-lift-state.md +125 -0
  94. package/catalogs/skills/vercel-react-best-practices/AGENTS.md +3810 -0
  95. package/catalogs/skills/vercel-react-best-practices/LICENSE.txt +27 -0
  96. package/catalogs/skills/vercel-react-best-practices/README.md +123 -0
  97. package/catalogs/skills/vercel-react-best-practices/SKILL.md +149 -0
  98. package/catalogs/skills/vercel-react-best-practices/metadata.json +15 -0
  99. package/catalogs/skills/vercel-react-best-practices/rules/_sections.md +46 -0
  100. package/catalogs/skills/vercel-react-best-practices/rules/_template.md +28 -0
  101. package/catalogs/skills/vercel-react-best-practices/rules/advanced-effect-event-deps.md +56 -0
  102. package/catalogs/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  103. package/catalogs/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
  104. package/catalogs/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  105. package/catalogs/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
  106. package/catalogs/skills/vercel-react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
  107. package/catalogs/skills/vercel-react-best-practices/rules/async-defer-await.md +82 -0
  108. package/catalogs/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
  109. package/catalogs/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
  110. package/catalogs/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  111. package/catalogs/skills/vercel-react-best-practices/rules/bundle-analyzable-paths.md +63 -0
  112. package/catalogs/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +60 -0
  113. package/catalogs/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
  114. package/catalogs/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
  115. package/catalogs/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  116. package/catalogs/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
  117. package/catalogs/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
  118. package/catalogs/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
  119. package/catalogs/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  120. package/catalogs/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  121. package/catalogs/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
  122. package/catalogs/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  123. package/catalogs/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  124. package/catalogs/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
  125. package/catalogs/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  126. package/catalogs/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  127. package/catalogs/skills/vercel-react-best-practices/rules/js-flatmap-filter.md +60 -0
  128. package/catalogs/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  129. package/catalogs/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  130. package/catalogs/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
  131. package/catalogs/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  132. package/catalogs/skills/vercel-react-best-practices/rules/js-request-idle-callback.md +105 -0
  133. package/catalogs/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  134. package/catalogs/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  135. package/catalogs/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  136. package/catalogs/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  137. package/catalogs/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
  138. package/catalogs/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  139. package/catalogs/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  140. package/catalogs/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  141. package/catalogs/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  142. package/catalogs/skills/vercel-react-best-practices/rules/rendering-resource-hints.md +85 -0
  143. package/catalogs/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +68 -0
  144. package/catalogs/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  145. package/catalogs/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  146. package/catalogs/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  147. package/catalogs/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  148. package/catalogs/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  149. package/catalogs/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  150. package/catalogs/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
  151. package/catalogs/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  152. package/catalogs/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  153. package/catalogs/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  154. package/catalogs/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  155. package/catalogs/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +82 -0
  156. package/catalogs/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  157. package/catalogs/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
  158. package/catalogs/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  159. package/catalogs/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +59 -0
  160. package/catalogs/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  161. package/catalogs/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  162. package/catalogs/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  163. package/catalogs/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  164. package/catalogs/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  165. package/catalogs/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  166. package/catalogs/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +149 -0
  167. package/catalogs/skills/vercel-react-best-practices/rules/server-no-shared-module-state.md +50 -0
  168. package/catalogs/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  169. package/catalogs/skills/vercel-react-best-practices/rules/server-parallel-nested-fetching.md +34 -0
  170. package/catalogs/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  171. package/catalogs/skills/webapp-testing/LICENSE.txt +202 -0
  172. package/catalogs/skills/webapp-testing/SKILL.md +96 -0
  173. package/catalogs/skills/webapp-testing/examples/console_logging.py +35 -0
  174. package/catalogs/skills/webapp-testing/examples/element_discovery.py +40 -0
  175. package/catalogs/skills/webapp-testing/examples/static_html_automation.py +33 -0
  176. package/catalogs/skills/webapp-testing/scripts/with_server.py +106 -0
  177. package/catalogs/skills.json +1115 -0
  178. package/docs/skills/evidencias/2026-10-28-evaluacion-inicial-mcp-seguridad.md +118 -0
  179. package/docs/skills/evidencias/2026-10-28-incorporacion-mcp-seguridad.json +152 -0
  180. package/docs/skills/evidencias/2026-10-28-recomendador-preparacion.md +50 -0
  181. package/package.json +73 -4
  182. package/plugins/nexakit-modelo/.claude-plugin/plugin.json +1 -0
  183. package/plugins/nexakit-modelo/hooks/hooks.json +1 -0
  184. package/plugins/nexakit-modelo/hooks/register.js +48 -0
  185. package/plugins/nexakit-modelo/hooks/status.js +8 -0
  186. package/plugins/nexakit-modelo/tests/register.test.ts +21 -0
  187. package/plugins/nexakit-panel/.claude-plugin/plugin.json +1 -0
  188. package/plugins/nexakit-panel/README.md +20 -0
  189. package/plugins/nexakit-panel/hooks/hooks.json +1 -0
  190. package/plugins/nexakit-panel/hooks/lienzo.js +382 -0
  191. package/plugins/nexakit-panel/hooks/panel.js +279 -0
  192. package/plugins/nexakit-panel/hooks/register.tsx +248 -0
  193. package/plugins/nexakit-panel/tests/lienzo.test.ts +142 -0
  194. package/plugins/nexakit-panel/tests/panel.test.ts +240 -0
  195. package/plugins/nexakit-panel/tests/register.test.ts +167 -0
  196. package/plugins/nexakit-panel/types/index.d.ts +41 -0
  197. package/plugins/nexakit-sesion/.claude-plugin/plugin.json +1 -0
  198. package/plugins/nexakit-sesion/README.md +12 -0
  199. package/plugins/nexakit-sesion/hooks/aviso.js +38 -0
  200. package/plugins/nexakit-sesion/hooks/hooks.json +1 -0
  201. package/plugins/nexakit-sesion/hooks/register.js +28 -0
  202. package/plugins/nexakit-sesion/tests/register.test.ts +96 -0
  203. package/plugins/niveles/.claude-plugin/plugin.json +5 -0
  204. package/plugins/niveles/agents/nivel-alto.md +13 -0
  205. package/plugins/niveles/agents/nivel-exigente.md +13 -0
  206. package/plugins/niveles/agents/nivel-ligero.md +13 -0
  207. package/plugins/niveles/agents/nivel-normal.md +13 -0
  208. package/schemas/agent-client-adapter.schema.json +786 -0
  209. package/schemas/agent-client-auth-diagnostic.schema.json +801 -0
  210. package/schemas/agent-client-isolated-variant.schema.json +105 -0
  211. package/schemas/agent-client-isolated-verification.schema.json +99 -0
  212. package/schemas/agent-client-managed-preferences-invocation.schema.json +67 -0
  213. package/schemas/agent-client-managed-preferences.schema.json +63 -0
  214. package/schemas/agent-client-native-diagnostics.schema.json +85 -0
  215. package/schemas/agent-client-native-evaluation.schema.json +171 -0
  216. package/schemas/agent-client-native-preflight.schema.json +90 -0
  217. package/schemas/agent-client-output.schema.json +551 -0
  218. package/schemas/agent-client-runtime-fixture.schema.json +90 -0
  219. package/schemas/agent-client-runtime-local.schema.json +95 -0
  220. package/schemas/agent-client-runtime.schema.json +1288 -0
  221. package/schemas/agent-client-selective-config.schema.json +77 -0
  222. package/schemas/agent-client-supervised-local.schema.json +135 -0
  223. package/schemas/agent-client-supervised.schema.json +186 -0
  224. package/schemas/agent-model-preference.schema.json +573 -0
  225. package/schemas/agent-model-selection.schema.json +311 -0
  226. package/schemas/agent-task-approvals.schema.json +362 -0
  227. package/schemas/agent-task-prepare.schema.json +1324 -0
  228. package/schemas/agent-task-verify.schema.json +198 -0
  229. package/schemas/project-memory-update.schema.json +33 -0
  230. package/schemas/project-memory.schema.json +298 -0
  231. package/schemas/skill-catalog.schema.json +246 -0
  232. package/schemas/task-workflow-plan-output.schema.json +35 -0
  233. package/scripts/prepare-package.js +6 -0
  234. package/scripts/validate-skill-catalog.js +41 -0
  235. package/skills/cerrar-avisens/SKILL.md +12 -0
  236. package/skills/cerrar-memoria/SKILL.md +96 -0
  237. package/skills/cerrar-memoria/references/cierre.md +76 -0
  238. package/skills/decision-records/SKILL.md +27 -0
  239. package/skills/decision-records/agents/openai.yaml +7 -0
  240. package/skills/decision-records/references/adr-template.md +35 -0
  241. package/skills/differential-review/LICENSE.txt +427 -0
  242. package/skills/differential-review/SKILL.md +225 -0
  243. package/skills/differential-review/adversarial.md +203 -0
  244. package/skills/differential-review/agents/openai.yaml +6 -0
  245. package/skills/differential-review/assets/trail-of-bits-mark.svg +1 -0
  246. package/skills/differential-review/methodology.md +234 -0
  247. package/skills/differential-review/patterns.md +300 -0
  248. package/skills/differential-review/reporting.md +369 -0
  249. package/skills/elegir-modelo/SKILL.md +68 -0
  250. package/skills/elegir-modelo/modelos.mjs +108 -0
  251. package/skills/frontend-design/LICENSE.txt +177 -0
  252. package/skills/frontend-design/SKILL.md +71 -0
  253. package/skills/gemini/SKILL.md +52 -0
  254. package/skills/imagen/SKILL.md +12 -0
  255. package/skills/investigar/SKILL.md +11 -0
  256. package/skills/mcp-builder/LICENSE.txt +202 -0
  257. package/skills/mcp-builder/SKILL.md +236 -0
  258. package/skills/mcp-builder/reference/evaluation.md +602 -0
  259. package/skills/mcp-builder/reference/mcp_best_practices.md +249 -0
  260. package/skills/mcp-builder/reference/node_mcp_server.md +970 -0
  261. package/skills/mcp-builder/reference/python_mcp_server.md +719 -0
  262. package/skills/mcp-builder/scripts/connections.py +151 -0
  263. package/skills/mcp-builder/scripts/evaluation.py +373 -0
  264. package/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
  265. package/skills/mcp-builder/scripts/requirements.txt +2 -0
  266. package/skills/ordenar-proyecto/SKILL.md +56 -0
  267. package/skills/project-handoff/SKILL.md +53 -0
  268. package/skills/project-handoff/agents/openai.yaml +7 -0
  269. package/skills/project-handoff/references/handoff-template.md +35 -0
  270. package/skills/quality-gate/LICENSE.txt +26 -0
  271. package/skills/quality-gate/SKILL.md +44 -0
  272. package/skills/quality-gate/agents/openai.yaml +7 -0
  273. package/skills/quality-gate/references/review-checklist.md +42 -0
  274. package/skills/revisar/SKILL.md +11 -0
  275. package/skills/revisar-skill/LICENSE-find-skills.txt +26 -0
  276. package/skills/revisar-skill/SKILL.md +94 -0
  277. package/skills/revision-cruzada/SKILL.md +59 -0
  278. package/skills/web-design-guidelines/AGENTS.md +156 -0
  279. package/skills/web-design-guidelines/LICENSE.txt +21 -0
  280. package/skills/web-design-guidelines/SKILL.md +29 -0
  281. package/src/agent-models.js +131 -0
  282. package/src/brand.js +117 -0
  283. package/src/claude-code-runner.js +642 -0
  284. package/src/cli-executable.js +88 -0
  285. package/src/cli.js +778 -0
  286. package/src/client-adapter-plan.js +271 -0
  287. package/src/client-auth-diagnostic-parser.js +211 -0
  288. package/src/client-auth-diagnostic.js +257 -0
  289. package/src/client-isolated-variant.js +106 -0
  290. package/src/client-isolated-verification.js +130 -0
  291. package/src/client-local-platform.js +14 -0
  292. package/src/client-managed-preferences-invocation.js +209 -0
  293. package/src/client-managed-preferences.js +78 -0
  294. package/src/client-native-access.js +134 -0
  295. package/src/client-native-diagnostics.js +253 -0
  296. package/src/client-native-evaluation.js +106 -0
  297. package/src/client-native-preflight-files.js +68 -0
  298. package/src/client-native-preflight.js +95 -0
  299. package/src/client-output-json.js +118 -0
  300. package/src/client-output-parser.js +278 -0
  301. package/src/client-runtime-admission.js +80 -0
  302. package/src/client-runtime-coordinator.js +70 -0
  303. package/src/client-runtime-core.js +92 -0
  304. package/src/client-runtime-fixture-permit.js +20 -0
  305. package/src/client-runtime-fixture-protocol.js +39 -0
  306. package/src/client-runtime-state.js +67 -0
  307. package/src/client-runtime-store-files.js +91 -0
  308. package/src/client-runtime-store.js +239 -0
  309. package/src/client-runtime-supervisor.js +146 -0
  310. package/src/client-selective-config.js +195 -0
  311. package/src/client-selective-files.js +126 -0
  312. package/src/client-supervised-codes.js +32 -0
  313. package/src/client-supervised-contract.js +52 -0
  314. package/src/client-supervised-coordinator.js +36 -0
  315. package/src/client-supervised-permit.js +20 -0
  316. package/src/client-supervised-protocol.js +37 -0
  317. package/src/client-supervised-store.js +167 -0
  318. package/src/client-supervised-supervisor.js +167 -0
  319. package/src/client-supervised.js +160 -0
  320. package/src/codex-cli-runner.js +358 -0
  321. package/src/codex-delivery.js +101 -0
  322. package/src/connect.js +703 -0
  323. package/src/doctor.js +795 -0
  324. package/src/gemini-cli.js +76 -0
  325. package/src/gemini-files.js +45 -0
  326. package/src/gemini-tools.js +249 -0
  327. package/src/init.js +473 -0
  328. package/src/install-lock.js +127 -0
  329. package/src/install-registry.js +61 -0
  330. package/src/legacy-repair.js +71 -0
  331. package/src/level-agents.js +111 -0
  332. package/src/link-states.js +172 -0
  333. package/src/memory-connection-artifacts.js +192 -0
  334. package/src/memory-connection-descriptor.js +158 -0
  335. package/src/memory-connection-diagnostic.js +177 -0
  336. package/src/memory-connection-files.js +191 -0
  337. package/src/memory-connection-manifest.js +118 -0
  338. package/src/memory-connection-package.js +176 -0
  339. package/src/memory-connection-plan.js +211 -0
  340. package/src/memory-connection-skill.js +211 -0
  341. package/src/memory-connection-toml.js +153 -0
  342. package/src/memory-locator.js +118 -0
  343. package/src/memory-mcp-policy.js +181 -0
  344. package/src/memory-mcp-server.js +166 -0
  345. package/src/memory-mcp-transport.js +59 -0
  346. package/src/missing-dependencies.js +21 -0
  347. package/src/model-command.js +147 -0
  348. package/src/model-preference.js +235 -0
  349. package/src/model-selection.js +368 -0
  350. package/src/native/managed-preferences.c +100 -0
  351. package/src/native/managed-preferences.h +17 -0
  352. package/src/package-lock-path.js +13 -0
  353. package/src/panel-cli.js +182 -0
  354. package/src/peer-handoff.js +27 -0
  355. package/src/peer-inbox-cli.js +211 -0
  356. package/src/peer-review-mcp.js +210 -0
  357. package/src/peer-review-store.js +532 -0
  358. package/src/platform.js +24 -0
  359. package/src/project-root.js +41 -0
  360. package/src/project-signals.js +339 -0
  361. package/src/recommend-report.js +77 -0
  362. package/src/review-instructions.js +211 -0
  363. package/src/review-policy.js +35 -0
  364. package/src/revision-adapters.js +157 -0
  365. package/src/revision-context.js +86 -0
  366. package/src/revision-isolation.js +222 -0
  367. package/src/revision-process.js +103 -0
  368. package/src/revision-provenance.js +89 -0
  369. package/src/revision-snapshot.js +120 -0
  370. package/src/revision.js +242 -0
  371. package/src/runtime-fixtures/runtime-supervisor/child.cjs +3 -0
  372. package/src/runtime-fixtures/runtime-supervisor/fixture.cjs +49 -0
  373. package/src/runtime-fixtures/supervised/child.cjs +3 -0
  374. package/src/runtime-fixtures/supervised/fixture.cjs +47 -0
  375. package/src/sensitive-data.js +21 -0
  376. package/src/setup-apply.js +231 -0
  377. package/src/setup-plan.js +231 -0
  378. package/src/setup-state.js +277 -0
  379. package/src/setup-tui.js +555 -0
  380. package/src/skill-catalog-add.js +91 -0
  381. package/src/skill-catalog-audit.js +68 -0
  382. package/src/skill-catalog.js +170 -0
  383. package/src/skill-files.js +39 -0
  384. package/src/skill-recommendations.js +1673 -0
  385. package/src/skill-scan-report.js +14 -0
  386. package/src/skill-scan.js +178 -0
  387. package/src/stable-command.js +53 -0
  388. package/src/stable-install.js +222 -0
  389. package/src/status.js +200 -0
  390. package/src/superpowers.js +133 -0
  391. package/src/sync-apply.js +227 -0
  392. package/src/sync-files.js +109 -0
  393. package/src/sync-inspect.js +394 -0
  394. package/src/sync-ledger.js +94 -0
  395. package/src/sync-markdown.js +151 -0
  396. package/src/sync-proposal.js +84 -0
  397. package/src/sync-record.js +459 -0
  398. package/src/sync.js +360 -0
  399. package/src/task-approvals.js +367 -0
  400. package/src/task-cli.js +79 -0
  401. package/src/task-external-verifier.js +584 -0
  402. package/src/task-prepare-files.js +115 -0
  403. package/src/task-prepare.js +180 -0
  404. package/src/task-verify-cli.js +67 -0
  405. package/src/task-verify-files.js +188 -0
  406. package/src/task-verify.js +118 -0
  407. package/src/task-workflow-mcp.js +544 -0
  408. package/src/task-workflow-store.js +254 -0
  409. package/src/terminal-text.js +68 -0
  410. package/src/toolkit-cli.js +543 -0
  411. package/src/toolkit-commands-guide.js +107 -0
  412. package/src/toolkit-setup.js +614 -0
  413. package/src/usage-metrics.js +43 -0
  414. package/templates/agent-team/01-encargo.md +158 -0
  415. package/templates/agent-team/02-propuesta.md +132 -0
  416. package/templates/agent-team/03-revision.md +150 -0
  417. package/templates/agent-team/README.md +213 -0
  418. package/templates/model-inventory/01-inventario.md +154 -0
  419. package/templates/model-inventory/README.md +115 -0
  420. package/templates/project-memory/README.md +67 -0
  421. package/templates/project-memory/project-memory.example.json +53 -0
  422. package/templates/project-memory/skill/project-id/SKILL.md +37 -0
  423. package/templates/project-memory/skill/project-id/references/project-profile.md +44 -0
  424. package/templates/project-memory/vault/00-INICIO/Estado actual.md +44 -0
  425. package/templates/project-memory/vault/00-INICIO/Fuentes de verdad.md +30 -0
  426. package/templates/project-memory/vault/00-INICIO/Inicio del proyecto.md +44 -0
  427. package/templates/project-memory/vault/00-INICIO/Mantenimiento de la memoria.md +26 -0
  428. package/templates/project-memory/vault/00-INICIO/Mapa de la memoria.md +33 -0
  429. package/templates/project-memory/vault/00-INICIO/Registro de sincronizaci/303/263n.md" +28 -0
  430. package/templates/project-memory/vault/01-PRODUCTO/Producto.md +16 -0
  431. package/templates/project-memory/vault/02-ARQUITECTURA/Arquitectura.md +16 -0
  432. package/templates/project-memory/vault/03-IMPLEMENTACION/Implementaci/303/263n.md +15 -0
  433. package/templates/project-memory/vault/04-DECISIONES/Decisiones.md +19 -0
  434. package/templates/project-memory/vault/05-ENTREGAS/Entregas.md +12 -0
  435. package/templates/project-memory/vault/06-OPERACION/Operaci/303/263n.md +15 -0
  436. package/templates/project-memory/vault/07-AGENTES/Protocolo de agentes.md +33 -0
  437. package/templates/project-memory/vault/08-RECURSOS/Recursos.md +12 -0
  438. package/templates/project-memory/vault/09-ARCHIVO/README.md +5 -0
@@ -0,0 +1,167 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import os from "node:os";
4
+ import { createStoreFiles, bytesHash } from "./client-runtime-store-files.js";
5
+ import { createSupervisedPermit, revokeSupervisedPermit } from "./client-supervised-permit.js";
6
+ import { createSupervisedContract, hash, same, taskKey, zeroMetrics, terminalStates, errorCode, fail, copyInertJson } from "./client-supervised-contract.js";
7
+
8
+ const names = ["0000.json", "0001.json", "0002.json", "0003.json"];
9
+ const unfinished = new Set(["reserved", "start-claimed", "started"]);
10
+
11
+ /** Separate one-attempt store; construction never initializes or repairs paths. */
12
+ export function createSupervisedStore(schema, configuration, dependencies = {}) {
13
+ const contract = createSupervisedContract(schema), cfg = copyInertJson(configuration);
14
+ if (Object.keys(cfg).join() !== "root" || typeof cfg.root !== "string" || !path.isAbsolute(cfg.root) || path.normalize(cfg.root) !== cfg.root) throw Error("Invalid supervised store configuration");
15
+ const files = createStoreFiles(dependencies.io), checkpoint = dependencies.checkpoint ?? (async () => {});
16
+ const clock = dependencies.clock ?? Date.now;
17
+ let rootIdentity;
18
+ async function root() {
19
+ const tmp = await fs.realpath(os.tmpdir());
20
+ // S2 is experiments only: do not activate a permanent project/user store.
21
+ if (path.dirname(cfg.root) !== tmp || !/^agent-supervised-[a-zA-Z0-9-]+$/.test(path.basename(cfg.root))) fail("supervised-root-not-temporary");
22
+ const s = await files.directory(cfg.root, rootIdentity); rootIdentity ??= s; return s;
23
+ }
24
+ function stamp() {
25
+ const n = clock(); if (!Number.isFinite(n)) fail("supervised-clock-unavailable");
26
+ return new Date(n).toISOString().replace(/\.\d{3}Z$/, "Z");
27
+ }
28
+ async function readChain(dir, identity, expectedDirectory) {
29
+ await root(); await files.directory(dir, expectedDirectory); await files.contents(dir, [...names, "confirmed.json"]);
30
+ const events = [], bytesHashes = []; let missingSeen = false;
31
+ for (const name of names) {
32
+ const p = path.join(dir, name);
33
+ if (!await files.exists(p)) { missingSeen = true; continue; }
34
+ if (missingSeen) fail("supervised-event-gap");
35
+ const { bytes } = await files.read(p, 131072); const e = contract.event(bytes);
36
+ if (e.limits.graceMs + e.limits.confirmationMs >= e.limits.timeoutMs || e.limits.maxLineBytes > e.limits.maxOutputBytes) fail("supervised-incompatible-limits");
37
+ const prior = events.at(-1);
38
+ if (e.sequence !== events.length || taskKey(e.identity) !== taskKey(identity) ||
39
+ e.previousSha256 !== (bytesHashes.at(-1) ?? null)) fail("supervised-event-chain-mismatch");
40
+ if (!prior) {
41
+ if (e.state !== "reserved" || !same(e.metrics, zeroMetrics()) || e.reasons.length) fail("supervised-invalid-reservation");
42
+ } else {
43
+ if (!same(e.identity, prior.identity) || e.attemptId !== prior.attemptId || e.fixtureId !== prior.fixtureId ||
44
+ e.requestSha256 !== prior.requestSha256 || !same(e.limits, prior.limits) || Date.parse(e.observedAt) < Date.parse(prior.observedAt)) fail("supervised-event-binding-mismatch");
45
+ const allowed = prior.state === "reserved" ? ["start-claimed", "canceled", "failed", "timed-out", "indeterminate"]
46
+ : prior.state === "start-claimed" ? ["started", "failed", "canceled", "timed-out", "indeterminate"]
47
+ : prior.state === "started" ? [...terminalStates] : [];
48
+ if (!allowed.includes(e.state) || e.metrics.spawnAttempts < prior.metrics.spawnAttempts ||
49
+ e.metrics.mainStartsObserved < prior.metrics.mainStartsObserved || e.metrics.mainStartsObserved > e.metrics.spawnAttempts ||
50
+ ["stdoutBytes", "stderrBytes", "events", "elapsedMs"].some(k => e.metrics[k] < prior.metrics[k])) fail("supervised-invalid-transition");
51
+ if (e.state === "start-claimed" && (e.metrics.spawnAttempts !== 1 || e.metrics.mainStartsObserved !== 0 || e.reasons.length)) fail("supervised-invalid-claim");
52
+ if (e.state === "started" && (e.metrics.spawnAttempts !== 1 || e.metrics.mainStartsObserved !== 1 || e.reasons.length)) fail("supervised-invalid-start");
53
+ if (terminalStates.has(e.state)) {
54
+ if (!e.reasons.length || e.state !== "indeterminate" && !e.metrics.terminationConfirmed) fail("supervised-unconfirmed-terminal");
55
+ if (e.state === "completed-for-review" && (prior.state !== "started" || e.metrics.mainStartsObserved !== 1 ||
56
+ e.metrics.stdoutBytes > e.limits.maxOutputBytes || e.metrics.stderrBytes > e.limits.maxStderrBytes ||
57
+ e.metrics.events > e.limits.maxEvents || e.metrics.elapsedMs > e.limits.timeoutMs)) fail("supervised-invalid-completion");
58
+ }
59
+ }
60
+ events.push(e); bytesHashes.push(bytesHash(bytes));
61
+ }
62
+ if (!events.length) fail("supervised-empty-reservation");
63
+ let receipt = false;
64
+ if (await files.exists(path.join(dir, "confirmed.json"))) {
65
+ const seal = contract.receipt((await files.read(path.join(dir, "confirmed.json"), 131072)).bytes);
66
+ if (!terminalStates.has(events.at(-1).state) || events.at(-1).state === "indeterminate" || seal.terminalSha256 !== bytesHashes.at(-1)) fail("supervised-receipt-mismatch");
67
+ receipt = true;
68
+ }
69
+ return { events, bytesHashes, last: events.at(-1), receipt };
70
+ }
71
+ async function observe(input) {
72
+ const r = { state: "clear", budgetConsumed: false, eventCount: 0, lastState: null, spawnAttempts: null,
73
+ mainStartsObserved: null, fixtureModelCalls: 0, actualModelCalls: null, internalCallCeiling: null,
74
+ remoteCancellationVerified: false, reasons: [] };
75
+ try {
76
+ const i = contract.identity(input); await root(); const dir = path.join(cfg.root, taskKey(i));
77
+ if (!await files.exists(dir)) return contract.observation(r);
78
+ r.budgetConsumed = true;
79
+ const c = await readChain(dir, i); const e = c.last;
80
+ r.eventCount = c.events.length; r.lastState = e.state;
81
+ r.spawnAttempts = e.metrics.spawnAttempts; r.mainStartsObserved = e.metrics.mainStartsObserved;
82
+ // Recorded zeros before observation do not prove that no process started.
83
+ if (unfinished.has(e.state) || e.state === "indeterminate" || !c.receipt) {
84
+ r.state = "reconciliation-required"; r.mainStartsObserved = e.metrics.mainStartsObserved === 1 ? 1 : null;
85
+ if (e.state === "reserved") r.spawnAttempts = null;
86
+ } else r.state = "consumed";
87
+ r.reasons = [r.state === "consumed" ? "supervised-budget-consumed" : "supervised-reconciliation-required"];
88
+ } catch (e) {
89
+ r.state = "reconciliation-required"; r.budgetConsumed = true; r.reasons = [errorCode(e)];
90
+ r.spawnAttempts = null; r.mainStartsObserved = null;
91
+ }
92
+ return contract.observation(r);
93
+ }
94
+ async function withReservation(input, consumer) {
95
+ const r = { state: "blocked", durability: "unconfirmed", reasons: [], value: null };
96
+ let handle, created = false;
97
+ try {
98
+ const d = contract.request(input); if (typeof consumer !== "function") fail("supervised-consumer-required");
99
+ const rootStat = await root(), dir = path.join(cfg.root, taskKey(d.identity));
100
+ await checkpoint("before-reserve");
101
+ try { await files.io.mkdir(dir, { mode: 0o700 }); created = true; }
102
+ catch (e) { if (e.code === "EEXIST") fail("supervised-budget-reserved"); throw e; }
103
+ const dirStat = await files.directory(dir); await files.syncDirectory(cfg.root, rootStat);
104
+ await checkpoint("after-directory");
105
+ let chain = [];
106
+ async function append(state, metrics, reasons = []) {
107
+ await root(); await files.directory(dir, dirStat);
108
+ if (chain.length) {
109
+ const current = await readChain(dir, d.identity, dirStat);
110
+ if (!same(current.events, chain)) fail("supervised-reservation-changed");
111
+ } else await files.contents(dir, []);
112
+ const prev = chain.at(-1);
113
+ const e = contract.event({ schemaVersion: "1.0.0", scope: "fixture-only", sequence: chain.length,
114
+ previousSha256: prev ? bytesHash((await files.read(path.join(dir, names[chain.length - 1]), 131072)).bytes) : null,
115
+ identity: d.identity, attemptId: d.attemptId, fixtureId: d.fixtureId, requestSha256: hash(d), limits: d.limits,
116
+ state, observedAt: stamp(), metrics, reasons: [...new Set(reasons)].sort(), fixtureModelCalls: 0,
117
+ actualModelCalls: null, internalCallCeiling: null, remoteCancellationVerified: false });
118
+ if (chain.length >= names.length) fail("supervised-event-limit");
119
+ const resource = await files.exclusive(path.join(dir, names[chain.length]));
120
+ try {
121
+ await files.write(resource, Buffer.from(JSON.stringify(e) + "\n"));
122
+ await checkpoint("after-write-" + state);
123
+ await files.syncDirectory(dir, dirStat); await files.owned(resource);
124
+ } finally { await resource.handle.close(); }
125
+ const read = await readChain(dir, d.identity, dirStat);
126
+ if (!same(read.last, e)) fail("supervised-write-not-confirmed");
127
+ chain = read.events;
128
+ await checkpoint("durable-" + state);
129
+ }
130
+ await append("reserved", zeroMetrics()); r.durability = "confirmed";
131
+ handle = createSupervisedPermit(hash(d), async () => {
132
+ await append("start-claimed", { ...zeroMetrics(), spawnAttempts: 1 });
133
+ }, async () => {
134
+ await append("started", { ...zeroMetrics(), spawnAttempts: 1, mainStartsObserved: 1 });
135
+ });
136
+ await checkpoint("before-consumer");
137
+ const value = contract.processReport(await consumer(handle)); r.value = value;
138
+ revokeSupervisedPermit(handle);
139
+ // An unfinished started write may still be completing. Do not race it by
140
+ // appending a terminal event; keep the reservation for reconciliation.
141
+ if (value.state === "indeterminate") {
142
+ r.state = "reconciliation-required"; r.reasons = ["supervised-reconciliation-required"]; return r;
143
+ }
144
+ const c = await readChain(dir, d.identity, dirStat);
145
+ if (!same(c.events, chain)) fail("supervised-reservation-changed");
146
+ const finalState = value.state === "not-started" ? "failed" : value.state;
147
+ await append(finalState, value.metrics, value.reasons.length ? value.reasons : ["supervised-local-result"]);
148
+ // Only write the receipt after terminal data, directory sync and readback
149
+ // have completed. A partial terminal append alone never proves settlement.
150
+ const terminal = await readChain(dir, d.identity, dirStat);
151
+ const receipt = contract.receipt({ schemaVersion: "1.0.0", scope: "fixture-only", terminalSha256: terminal.bytesHashes.at(-1) });
152
+ const seal = await files.exclusive(path.join(dir, "confirmed.json"));
153
+ try {
154
+ await files.write(seal, Buffer.from(JSON.stringify(receipt) + "\n"));
155
+ await files.syncDirectory(dir, dirStat); await files.owned(seal);
156
+ } finally { await seal.handle.close(); }
157
+ if (!(await readChain(dir, d.identity, dirStat)).receipt) fail("supervised-write-not-confirmed");
158
+ r.state = finalState === "indeterminate" ? "reconciliation-required" : "recorded";
159
+ r.reasons = r.state === "recorded" ? ["supervised-result-recorded"] : ["supervised-reconciliation-required"];
160
+ } catch (e) {
161
+ r.state = created ? "reconciliation-required" : "blocked";
162
+ r.durability = "unconfirmed"; r.reasons = [errorCode(e)];
163
+ } finally { if (handle) revokeSupervisedPermit(handle); }
164
+ return r;
165
+ }
166
+ return Object.freeze({ observe, withReservation });
167
+ }
@@ -0,0 +1,167 @@
1
+ import { supportsLocalPosix } from "./client-local-platform.js";
2
+ import fs from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { spawn as nativeSpawn } from "node:child_process";
7
+ import { claimSupervisedPermit } from "./client-supervised-permit.js";
8
+ import { createSupervisedProtocol } from "./client-supervised-protocol.js";
9
+ import { createSupervisedContract, hash, monotonicMs, zeroMetrics, errorCode, fail } from "./client-supervised-contract.js";
10
+
11
+ const script = fileURLToPath(new URL("./runtime-fixtures/supervised/fixture.cjs", import.meta.url));
12
+ const childScript = fileURLToPath(new URL("./runtime-fixtures/supervised/child.cjs", import.meta.url));
13
+
14
+ /** Trusted fixture runner, not a native subscription runner. */
15
+ export function createSupervisedSupervisor(schema, dependencies = {}) {
16
+ const contract = createSupervisedContract(schema);
17
+ const spawn = dependencies.spawn ?? nativeSpawn, kill = dependencies.kill ?? process.kill.bind(process);
18
+ const mono = dependencies.monotonic ?? monotonicMs, checkpoint = dependencies.checkpoint ?? (async () => {});
19
+ return async function supervise(handle, input, { signal, beganAt = mono() } = {}) {
20
+ const r = { scope: "fixture-only", state: "not-started", fixtureExecuted: false, nativeExecuted: false,
21
+ runtimeReady: false, verifiedAdmission: false, actualModelCalls: null, fixtureModelCalls: 0,
22
+ internalCallCeiling: null, remoteCancellationVerified: false, metrics: zeroMetrics(),
23
+ exitObserved: false, pipesClosed: false, groupObservation: "not-started", reasons: [] };
24
+ const elapsed = () => Math.max(0, Math.ceil(mono() - beganAt));
25
+ let cwd, owned, spawnReturned = false, attempted = false;
26
+ try {
27
+ const d = contract.request(input), l = d.limits;
28
+ if (!supportsLocalPosix(process.platform)) fail("supervised-platform-not-admitted");
29
+ if (!Number.isFinite(beganAt) || beganAt > mono()) fail("supervised-invalid-deadline");
30
+ const budget = () => {
31
+ if (signal?.aborted) fail("supervised-canceled-before-start");
32
+ if (elapsed() >= l.timeoutMs - l.graceMs - l.confirmationMs) fail("supervised-deadline-before-start");
33
+ };
34
+ budget();
35
+ for (const file of [script, childScript]) {
36
+ const s = await fs.lstat(file);
37
+ if (!s.isFile() || s.isSymbolicLink() || (s.mode & 0o022)) fail("supervised-fixture-source-unsafe");
38
+ }
39
+ const parent = await fs.lstat(path.dirname(script));
40
+ if (!parent.isDirectory() || parent.isSymbolicLink() || (parent.mode & 0o022)) fail("supervised-fixture-directory-unsafe");
41
+ const workspaceParent = dependencies.workspaceParent ?? await fs.realpath(os.tmpdir());
42
+ if (dependencies.workspaceParent !== undefined) {
43
+ const s = await fs.lstat(workspaceParent);
44
+ if (await fs.realpath(workspaceParent) !== workspaceParent || !s.isDirectory() || s.isSymbolicLink() ||
45
+ (s.mode & 0o7777) !== 0o700 || s.uid !== process.getuid()) fail("supervised-workspace-parent-unsafe");
46
+ }
47
+ cwd = await fs.realpath(await fs.mkdtemp(path.join(workspaceParent, "agent-supervised-work-")));
48
+ await fs.chmod(cwd, 0o700); owned = await fs.lstat(cwd);
49
+ budget(); await checkpoint("before-claim");
50
+ const capability = await claimSupervisedPermit(handle, hash(d));
51
+ // Claim consumed the only local start right; no reuse if later checks fail.
52
+ budget(); await checkpoint("before-spawn"); budget();
53
+ r.metrics.spawnAttempts = 1; attempted = true;
54
+ const child = spawn(process.execPath, [script, d.fixtureId], {
55
+ shell: false, detached: true, cwd, env: { LANG: "C", LC_ALL: "C" }, stdio: ["pipe", "pipe", "pipe"]
56
+ });
57
+ spawnReturned = true;
58
+ // Register all lifecycle handlers synchronously, before awaiting storage.
59
+ await new Promise(resolve => {
60
+ const protocol = createSupervisedProtocol(l), stderr = new TextDecoder("utf-8", { fatal: true });
61
+ let done = false, spawned = false, spawnFailed = false, canceled = false, cancelAt = null, forced = false;
62
+ let groupGone = false, startedWritePending = false, startedWriteFailed = false;
63
+ let stdinClosed = false, stdoutClosed = false, stderrClosed = false, closed = false, exitCode = null;
64
+ let timer, hardTimer;
65
+ const add = c => { if (!r.reasons.includes(c)) r.reasons.push(c); };
66
+ const groupAlive = () => {
67
+ if (groupGone || spawnFailed) return false;
68
+ if (!spawned) return true;
69
+ try { kill(-child.pid, 0); return true; }
70
+ catch (e) { if (e?.code === "ESRCH") { groupGone = true; return false; } add("supervised-group-unconfirmed"); return true; }
71
+ };
72
+ const send = sig => {
73
+ if (!spawned || groupGone) return;
74
+ try { kill(-child.pid, sig); }
75
+ catch (e) { if (e?.code === "ESRCH") groupGone = true; else add("supervised-signal-unconfirmed"); }
76
+ };
77
+ const cancel = (code, state = "failed") => {
78
+ if (done) return; add(code);
79
+ if (canceled) return;
80
+ canceled = true; cancelAt = mono(); r.state = state;
81
+ child.stdin.destroy(); send("SIGTERM");
82
+ };
83
+ const finish = uncertain => {
84
+ if (done) return; done = true;
85
+ clearInterval(timer); clearTimeout(hardTimer); signal?.removeEventListener("abort", abort);
86
+ const counts = protocol.counts();
87
+ Object.assign(r.metrics, { stdoutBytes: counts.stdoutBytes, events: counts.events, elapsedMs: elapsed() });
88
+ r.pipesClosed = stdinClosed && stdoutClosed && stderrClosed && closed;
89
+ r.groupObservation = spawnFailed ? "not-started" : groupGone ? "absent" : "unconfirmed";
90
+ r.metrics.terminationConfirmed = spawnFailed || r.exitObserved && r.pipesClosed && groupGone;
91
+ if (uncertain || startedWriteFailed || r.metrics.elapsedMs > l.timeoutMs) {
92
+ r.state = "indeterminate"; add("supervised-reconciliation-required");
93
+ } else if (spawnFailed) { r.state = "not-started"; }
94
+ else if (!canceled && r.state !== "failed") r.state = "completed-for-review";
95
+ if (!r.reasons.length) add("supervised-fixture-completed");
96
+ child.stdin.destroy(); child.stdout.destroy(); child.stderr.destroy(); resolve();
97
+ };
98
+ const poll = () => {
99
+ if (done) return;
100
+ if (elapsed() >= l.timeoutMs - l.graceMs - l.confirmationMs && !canceled) cancel("supervised-deadline", "timed-out");
101
+ if (canceled && !forced && mono() - cancelAt >= l.graceMs) { forced = true; send("SIGKILL"); }
102
+ const alive = groupAlive();
103
+ if (r.exitObserved && closed && stdinClosed && stdoutClosed && stderrClosed && !startedWritePending && !alive) {
104
+ if (!canceled && !spawnFailed) {
105
+ try { if (exitCode !== 0) fail("supervised-exit-failed"); protocol.finish(); stderr.decode(); }
106
+ catch (e) { r.state = "failed"; add(errorCode(e)); }
107
+ }
108
+ finish(false);
109
+ } else if (r.exitObserved && alive && !canceled) cancel("supervised-descendants-live");
110
+ if (spawnFailed && closed) finish(false);
111
+ };
112
+ const abort = () => cancel("supervised-canceled", "canceled");
113
+ child.on("spawn", () => {
114
+ spawned = true;
115
+ if (done) { send("SIGKILL"); return; }
116
+ r.fixtureExecuted = true; r.metrics.mainStartsObserved = 1; startedWritePending = true;
117
+ if (canceled) send("SIGTERM");
118
+ Promise.resolve().then(() => checkpoint("spawn-observed")).then(() => capability.started())
119
+ .catch(() => { startedWriteFailed = true; cancel("supervised-start-record-unconfirmed"); })
120
+ .finally(() => { startedWritePending = false; poll(); });
121
+ });
122
+ child.on("error", () => { if (done) return; if (!spawned) { spawnFailed = true; add("supervised-spawn-failed"); } else cancel("supervised-process-error"); });
123
+ child.on("exit", code => { if (done) return; r.exitObserved = true; exitCode = code; poll(); });
124
+ child.on("close", () => { closed = true; poll(); });
125
+ child.stdin.on("close", () => { stdinClosed = true; poll(); });
126
+ child.stdout.on("close", () => { stdoutClosed = true; poll(); });
127
+ child.stderr.on("close", () => { stderrClosed = true; poll(); });
128
+ for (const [stream, name] of [[child.stdin, "stdin"], [child.stdout, "stdout"], [child.stderr, "stderr"]]) {
129
+ stream.on("error", () => cancel("supervised-" + name + "-error"));
130
+ }
131
+ child.stdout.on("data", chunk => {
132
+ if (done || canceled) return;
133
+ try { protocol.push(chunk); } catch (e) { cancel(errorCode(e)); }
134
+ });
135
+ child.stderr.on("data", chunk => {
136
+ if (done || canceled) return;
137
+ r.metrics.stderrBytes += chunk.length;
138
+ if (r.metrics.stderrBytes > l.maxStderrBytes) cancel("supervised-stderr-limit");
139
+ else try { stderr.decode(chunk, { stream: true }); } catch { cancel("supervised-stderr-invalid-utf8"); }
140
+ });
141
+ signal?.addEventListener("abort", abort, { once: true }); if (signal?.aborted) abort();
142
+ timer = setInterval(poll, 10);
143
+ hardTimer = setTimeout(() => { send("SIGKILL"); poll(); if (!done) finish(true); }, Math.max(1, l.timeoutMs - elapsed()));
144
+ try { child.stdin.end(d.inputText, e => { if (e) cancel("supervised-stdin-error"); }); }
145
+ catch { cancel("supervised-stdin-error"); }
146
+ });
147
+ } catch (e) {
148
+ r.reasons = [errorCode(e)]; r.metrics.elapsedMs = elapsed();
149
+ r.metrics.terminationConfirmed = !spawnReturned;
150
+ if (spawnReturned) r.state = "indeterminate";
151
+ else if (e?.code === "supervised-canceled-before-start") r.state = "canceled";
152
+ else if (e?.code === "supervised-deadline-before-start") r.state = "timed-out";
153
+ // attempted is distinct from a returned ChildProcess and a spawn event.
154
+ if (attempted) r.metrics.spawnAttempts = 1;
155
+ } finally {
156
+ if (cwd && (!spawnReturned || r.metrics.terminationConfirmed)) {
157
+ try {
158
+ const s = await fs.lstat(cwd);
159
+ if (s.dev !== owned.dev || s.ino !== owned.ino || !s.isDirectory() || s.isSymbolicLink()) throw Error("changed");
160
+ await fs.rmdir(cwd);
161
+ } catch { r.state = "indeterminate"; r.reasons.push("supervised-workspace-cleanup-required"); }
162
+ }
163
+ }
164
+ r.reasons = [...new Set(r.reasons)].sort();
165
+ return contract.processReport(r);
166
+ };
167
+ }
@@ -0,0 +1,160 @@
1
+ import Ajv2020 from "ajv/dist/2020.js";
2
+ import { copyInertJson, copyBytes, decode, parseEventJson, ParseFailure, fail } from "./client-output-json.js";
3
+ import { CONTROLS, EFFECTS, hash, same, unique, fresh } from "./client-runtime-core.js";
4
+
5
+ const SCHEMA_ID = "https://agent-toolkit.local/schemas/agent-client-supervised.schema.json";
6
+ const MAX_INPUT_BYTES = 131072;
7
+ const REQUIRED_CONTROLS = CONTROLS.filter(id => id !== "internal-call-limit");
8
+ const SECTIONS = ["selection", "binding", "expectedBinding", "limits", "context", "authorization", "limitations", "history", "installation", "controls", "effects", "access", "observations"];
9
+ const GATES = ["trusted-authorization-and-limitations", "native-installation-and-controls", "subscription-and-billing", "selection-and-private-context", "supervised-history-and-durable-reservation", "local-supervision-and-termination", "human-result-review"];
10
+
11
+ function declarationScope(data, policySha256) {
12
+ const summary = value => {
13
+ if (!value) return null;
14
+ const { assessment, billingAssessment, ...declaration } = value;
15
+ return declaration;
16
+ };
17
+ const ordered = (items, key) => (items ?? []).map(summary).sort((a, b) => a[key] < b[key] ? -1 : a[key] > b[key] ? 1 : 0);
18
+ const authorization = summary(data.authorization);
19
+ if (authorization) authorization.effectsApproved = [...authorization.effectsApproved].sort();
20
+ return hash({ profile: data.profile, intentId: data.intentId, identity: data.identity,
21
+ selection: summary(data.selection), binding: data.binding ?? null, expectedBinding: data.expectedBinding ?? null,
22
+ limits: data.limits ?? null, context: summary(data.context), authorization,
23
+ limitations: summary(data.limitations), history: summary(data.history), access: summary(data.access),
24
+ controls: ordered(data.controls, "controlId"), effects: ordered(data.effects, "effectId"),
25
+ observations: [...(data.observations ?? [])].sort(), policySha256 });
26
+ }
27
+
28
+ // A separate pure review of declarations. This is not a C1 admission or a launcher.
29
+ export function createClientSupervisedEvaluator(schema, trustedPolicy) {
30
+ let contract; let policy;
31
+ try { contract = copyInertJson(schema); policy = copyInertJson(trustedPolicy); }
32
+ catch { throw Error("Invalid supervised evaluation configuration"); }
33
+ if (contract?.$id !== SCHEMA_ID) throw Error("Unsupported supervised evaluation schema");
34
+ const ajv = new Ajv2020({ strict: true, allErrors: true });
35
+ ajv.addFormat("date-time", { type: "string", validate: value => {
36
+ if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/.test(value)) return false;
37
+ const time = Date.parse(value);
38
+ return Number.isFinite(time) && new Date(time).toISOString() === value.replace(/Z$/, ".000Z");
39
+ } });
40
+ ajv.addSchema(contract);
41
+ const validator = name => ajv.compile({ $ref: `${SCHEMA_ID}#/$defs/${name}` });
42
+ const validInput = validator("input"), validPolicy = validator("policy"), validReport = validator("report");
43
+ if (!validPolicy(policy) || policy.limits.terminationGraceSeconds >= policy.limits.timeoutSeconds ||
44
+ policy.limits.maxEventBytes > policy.limits.maxStdoutBytes) throw Error("Invalid supervised evaluation policy");
45
+ const revoked = new Set(policy.revokedEvidenceRefs), policySha256 = hash(policy);
46
+
47
+ return function evaluateSupervisedIntent(input) {
48
+ const report = { schemaVersion: "1.0.0", profile: "supervised-subscription", intentId: null, state: "invalid",
49
+ executed: false, runtimeReady: false, verifiedAdmission: false, externalBillingVerified: false,
50
+ selectionVerified: false, internalCallCeiling: null, remoteCancellationVerified: false,
51
+ reasons: [], missing: [], externalGates: [...GATES], audit: { inputSha256: null, scopeSha256: null, policySha256 } };
52
+ const blockers = new Set(), missing = new Set();
53
+ const block = reason => blockers.add(reason);
54
+ function finish(state, reasons = []) {
55
+ report.state = state; report.reasons = [...new Set(reasons)].sort(); report.missing = [...missing].sort();
56
+ if (!validReport(report)) throw Error("Supervised evaluation report invariant failed");
57
+ return report;
58
+ }
59
+ try {
60
+ const parsed = typeof input === "string" || (input && typeof input === "object" && ArrayBuffer.isView(input))
61
+ ? parseEventJson(decode(copyBytes(input, MAX_INPUT_BYTES))) : input;
62
+ const data = copyInertJson(parsed);
63
+ const serialized = JSON.stringify(data);
64
+ parseEventJson(decode(copyBytes(serialized, MAX_INPUT_BYTES))); // Validate Unicode in copied object strings too.
65
+ if (!validInput(data)) fail("invalid-supervised-input");
66
+ if (data.controls && !unique(data.controls.map(c => c.controlId))) fail("duplicate-supervised-control");
67
+ if (data.effects && !unique(data.effects.map(e => e.effectId))) fail("duplicate-supervised-effect");
68
+ report.intentId = data.intentId; report.audit.inputSha256 = hash(data);
69
+ for (const section of SECTIONS) if (data[section] === undefined) missing.add(section);
70
+
71
+ // Evidence is bound to the whole intent, not just an installation or a task name.
72
+ const { assessment: selectionAssessment, ...selection } = data.selection ?? {};
73
+ const { assessment: contextAssessment, ...context } = data.context ?? {};
74
+ const scope = declarationScope(data, policySha256);
75
+ report.audit.scopeSha256 = scope;
76
+ function reference(id, label) {
77
+ if (id === null) missing.add(`${label}.reference`);
78
+ else if (revoked.has(id)) block(`supervised-reference-revoked:${label}`);
79
+ }
80
+ function assess(a, label, sources) {
81
+ if (!a) return;
82
+ reference(a.evidenceRef, label);
83
+ if (a.scopeSha256 !== scope) block(`supervised-scope-mismatch:${label}`);
84
+ if (!fresh(a, data.now, policy.maxEvidenceAgeSeconds)) block(`supervised-evidence-not-fresh:${label}`);
85
+ if (a.status === "rejected") block(`supervised-evidence-rejected:${label}`);
86
+ else if (a.status !== "confirmed") missing.add(`${label}.confirmation`);
87
+ else if (!sources.includes(a.source)) block(`supervised-source-conflict:${label}`);
88
+ }
89
+ const human = ["operator-attestation"], test = ["installation-test"], attested = [...human, ...test];
90
+ if (data.binding && data.expectedBinding && !same(data.binding, data.expectedBinding)) block("supervised-binding-mismatch");
91
+ if (data.selection) {
92
+ assess(selectionAssessment, "selection", attested);
93
+ if (["latest", "default", "opus", "sonnet", "haiku", "fable"].includes(selection.model) || selection.model.split("-").includes("latest")) block("supervised-model-not-pinned");
94
+ if (data.binding && (selection.client !== data.binding.client || selection.provider !== data.binding.provider)) block("supervised-selection-binding-mismatch");
95
+ if (selection.source === "operator-choice" && selectionAssessment.source !== "operator-attestation") block("supervised-selection-source-conflict");
96
+ }
97
+ if (data.limits) {
98
+ for (const key of Object.keys(policy.limits)) if (data.limits[key] > policy.limits[key]) block("supervised-limits-exceed-policy");
99
+ if (data.limits.terminationGraceSeconds >= data.limits.timeoutSeconds) block("supervised-grace-outside-deadline");
100
+ if (data.limits.maxEventBytes > data.limits.maxStdoutBytes) block("supervised-event-limit-inconsistent");
101
+ }
102
+ if (data.context) {
103
+ assess(contextAssessment, "context", attested);
104
+ if (data.limits && context.inputBytes > data.limits.maxInputBytes) block("supervised-context-exceeds-budget");
105
+ }
106
+ if (data.authorization) {
107
+ const a = data.authorization;
108
+ assess(a.assessment, "authorization", human);
109
+ if (a.status !== "approved") block("supervised-authorization-not-approved");
110
+ if (data.limits && !same(a.limits, data.limits)) block("supervised-authorization-limits-mismatch");
111
+ if (data.identity.mode === "tutor" && a.writer !== "user") block("supervised-tutor-authority-conflict");
112
+ }
113
+ if (data.identity.role === "tutor" && data.identity.mode !== "tutor") block("supervised-tutor-mode-conflict");
114
+ if (data.limitations) {
115
+ assess(data.limitations.assessment, "limitations", human);
116
+ if (!data.limitations.internalCallsUnknownAccepted || !data.limitations.remoteCancellationUnknownAccepted) block("supervised-limitations-not-accepted");
117
+ }
118
+ if (data.history) {
119
+ const h = data.history;
120
+ assess(h.assessment, "history", attested);
121
+ if (h.projectId !== data.identity.projectId || h.taskId !== data.identity.taskId) block("supervised-history-identity-mismatch");
122
+ if (h.state !== "clear") block("supervised-history-reconciliation-required");
123
+ if (h.mainStartsUsed === 0 && (h.durationUsedSeconds > 0 || (h.actualModelCalls !== null && h.actualModelCalls > 0))) block("supervised-history-counters-inconsistent");
124
+ if (data.limits && (h.mainStartsUsed >= data.limits.maxMainStarts || h.durationUsedSeconds >= data.limits.timeoutSeconds)) block("supervised-budget-exhausted");
125
+ if (h.mainStartsUsed > 0 && h.actualModelCalls === null) block("supervised-prior-consumption-unresolved");
126
+ }
127
+ if (data.installation) assess(data.installation.assessment, "installation", test);
128
+ for (const id of REQUIRED_CONTROLS) {
129
+ const c = data.controls?.find(c => c.controlId === id), label = `controls.${id}`;
130
+ if (!c) { missing.add(label); continue; }
131
+ assess(c.assessment, label, test);
132
+ for (const key of ["mechanismId", "positiveEvidenceRef", "negativeEvidenceRef"]) {
133
+ if (c[key] === null) missing.add(`${label}.${key.toLowerCase()}`);
134
+ else if (key !== "mechanismId") reference(c[key], `${label}.${key.toLowerCase()}`);
135
+ }
136
+ }
137
+ for (const id of EFFECTS) {
138
+ const e = data.effects?.find(e => e.effectId === id), label = `effects.${id}`;
139
+ if (!e) { missing.add(label); continue; }
140
+ assess(e.assessment, label, test);
141
+ if (e.presence === "unknown" || e.disposition !== "allowed") block(`supervised-effect-unconfirmed:${id}`);
142
+ if (["native-auth", "provider-inference"].includes(id) && e.presence === "absent") block(`supervised-required-effect-absent:${id}`);
143
+ if (e.presence === "present" && !data.authorization?.effectsApproved.includes(id)) block(`supervised-effect-not-authorized:${id}`);
144
+ }
145
+ if (data.access) {
146
+ assess(data.access.assessment, "access", attested);
147
+ assess(data.access.billingAssessment, "billing", attested);
148
+ if (data.access.method !== "subscription-session") block("supervised-subscription-required");
149
+ if (data.access.externalBilling !== "disabled") block("supervised-external-billing-not-disabled");
150
+ }
151
+ for (const code of data.observations ?? []) block(`supervised-unresolved:${code}`);
152
+ if (blockers.size) return finish("blocked", [...blockers]);
153
+ if (missing.size) return finish("incomplete", ["supervised-declarations-incomplete"]);
154
+ return finish("ready-for-supervised-review", ["supervised-declarations-only"]);
155
+ } catch (error) {
156
+ if (!(error instanceof ParseFailure)) throw error;
157
+ return finish("invalid", [error.code]);
158
+ }
159
+ };
160
+ }