@ornexus/neocortex 4.60.62 → 4.60.64

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 (137) hide show
  1. package/dist/release-source.json +1 -1
  2. package/dist/sbom.cdx.json +77 -50
  3. package/install.ps1 +1 -1
  4. package/install.sh +1 -1
  5. package/package.json +12 -5
  6. package/packages/client/dist/cli.js +8 -3
  7. package/packages/client/dist/commands/activate.js +8 -8
  8. package/packages/client/dist/commands/architecture-memory-terminal.js +4 -2
  9. package/packages/client/dist/commands/architecture-non-ui-continuation.d.ts +3 -0
  10. package/packages/client/dist/commands/architecture-non-ui-continuation.js +1 -0
  11. package/packages/client/dist/commands/invoke.d.ts +19 -16
  12. package/packages/client/dist/commands/invoke.js +86 -79
  13. package/packages/client/dist/commands/planning-generation.js +1 -1
  14. package/packages/client/dist/commands/planning-memory.d.ts +1 -0
  15. package/packages/client/dist/commands/planning-memory.js +1 -0
  16. package/packages/client/dist/commands/private-session.d.ts +1 -0
  17. package/packages/client/dist/commands/private-session.js +1 -0
  18. package/packages/client/dist/commands/qa-control.d.ts +4 -0
  19. package/packages/client/dist/commands/qa-control.js +1 -0
  20. package/packages/client/dist/commands/qa-scan-browser-launch.d.ts +8 -0
  21. package/packages/client/dist/commands/qa-scan-browser-launch.js +1 -0
  22. package/packages/client/dist/commands/qa-scan-browser-route.d.ts +3 -0
  23. package/packages/client/dist/commands/qa-scan-browser-route.js +1 -0
  24. package/packages/client/dist/commands/qa-scan-capture.d.ts +43 -0
  25. package/packages/client/dist/commands/qa-scan-capture.js +5 -5
  26. package/packages/client/dist/commands/qa-scan-discovery.d.ts +7 -0
  27. package/packages/client/dist/commands/qa-scan-discovery.js +3 -3
  28. package/packages/client/dist/commands/qa-scan-review.d.ts +8 -1
  29. package/packages/client/dist/commands/qa-scan-review.js +5 -5
  30. package/packages/client/dist/commands/qa-synthetic-backend-capture.d.ts +62 -0
  31. package/packages/client/dist/commands/qa-synthetic-backend-capture.js +1 -0
  32. package/packages/client/dist/commands/qa-synthetic-backend-review.d.ts +104 -0
  33. package/packages/client/dist/commands/qa-synthetic-backend-review.js +1 -0
  34. package/packages/client/dist/commands/qa-synthetic-backend.d.ts +52 -0
  35. package/packages/client/dist/commands/qa-synthetic-backend.js +7 -0
  36. package/packages/client/dist/commands/qa-synthetic-broker-port.d.ts +30 -0
  37. package/packages/client/dist/commands/qa-synthetic-broker-port.js +1 -0
  38. package/packages/client/dist/commands/qa-synthetic-browser.d.ts +1 -0
  39. package/packages/client/dist/commands/qa-synthetic-browser.js +1 -0
  40. package/packages/client/dist/commands/refactor-characterization.d.ts +12 -3
  41. package/packages/client/dist/commands/refactor-characterization.js +21 -12
  42. package/packages/client/dist/commands/refactor-control.d.ts +17 -0
  43. package/packages/client/dist/commands/refactor-control.js +3 -0
  44. package/packages/client/dist/commands/refactor-cpp-assertions.d.ts +4 -0
  45. package/packages/client/dist/commands/refactor-cpp-assertions.js +3 -0
  46. package/packages/client/dist/commands/refactor-review.d.ts +13 -0
  47. package/packages/client/dist/commands/refactor-review.js +6 -5
  48. package/packages/client/dist/commands/refactor-root.d.ts +165 -1
  49. package/packages/client/dist/commands/refactor-root.js +12 -7
  50. package/packages/client/dist/commands/refresh-memory.d.ts +1 -0
  51. package/packages/client/dist/commands/refresh-memory.js +3 -3
  52. package/packages/client/dist/commands/shared-architecture-non-ui-contract.d.ts +19 -0
  53. package/packages/client/dist/commands/shared-architecture-non-ui-contract.js +1 -0
  54. package/packages/client/dist/errors/error-messages.js +1 -1
  55. package/packages/client/dist/git/direct-yolo-checkpoint.js +4 -4
  56. package/packages/client/dist/git/git-lifecycle-store.js +7 -7
  57. package/packages/client/dist/license/license-client.d.ts +3 -1
  58. package/packages/client/dist/license/license-client.js +1 -1
  59. package/packages/client/dist/memory/project-memory-path-scope.d.ts +4 -0
  60. package/packages/client/dist/memory/project-memory-path-scope.js +1 -0
  61. package/packages/client/dist/memory/project-memory-writer.d.ts +4 -1
  62. package/packages/client/dist/memory/project-memory-writer.js +16 -16
  63. package/packages/client/dist/package.json +1 -0
  64. package/packages/client/dist/private-execution/clean-baseline.d.ts +7 -0
  65. package/packages/client/dist/private-execution/clean-baseline.js +2 -2
  66. package/packages/client/dist/private-execution/codex-executor.d.ts +48 -4
  67. package/packages/client/dist/private-execution/codex-executor.js +9 -2
  68. package/packages/client/dist/private-execution/codex-host-runtime.d.ts +10 -0
  69. package/packages/client/dist/private-execution/codex-host-runtime.js +1 -0
  70. package/packages/client/dist/private-execution/codex-lifecycle-guard.d.ts +4 -0
  71. package/packages/client/dist/private-execution/codex-lifecycle-guard.js +1 -0
  72. package/packages/client/dist/private-execution/codex-scoped-permissions.d.ts +8 -0
  73. package/packages/client/dist/private-execution/codex-scoped-permissions.js +1 -0
  74. package/packages/client/dist/private-execution/delivery.d.ts +18 -1
  75. package/packages/client/dist/private-execution/delivery.js +11 -3
  76. package/packages/client/dist/private-execution/diagnosis-root-review.d.ts +112 -0
  77. package/packages/client/dist/private-execution/diagnosis-root-review.js +2 -0
  78. package/packages/client/dist/private-execution/frozen-handoff.d.ts +2 -0
  79. package/packages/client/dist/private-execution/frozen-handoff.js +7 -0
  80. package/packages/client/dist/private-execution/implementation-validation.d.ts +24 -0
  81. package/packages/client/dist/private-execution/implementation-validation.js +2 -0
  82. package/packages/client/dist/private-execution/isolated-admission.d.ts +11 -7
  83. package/packages/client/dist/private-execution/isolated-admission.js +17 -10
  84. package/packages/client/dist/private-execution/isolated-session.d.ts +68 -0
  85. package/packages/client/dist/private-execution/isolated-session.js +5 -2
  86. package/packages/client/dist/private-execution/pact-test-source.d.ts +1 -1
  87. package/packages/client/dist/private-execution/pact-test-source.js +1 -1
  88. package/packages/client/dist/private-execution/planning-diagnosis-checkpoint.d.ts +2 -0
  89. package/packages/client/dist/private-execution/planning-diagnosis-checkpoint.js +5 -5
  90. package/packages/client/dist/private-execution/planning-generation-checkpoint.d.ts +13 -0
  91. package/packages/client/dist/private-execution/planning-generation-checkpoint.js +4 -3
  92. package/packages/client/dist/private-execution/planning-memory-checkpoint.d.ts +32 -0
  93. package/packages/client/dist/private-execution/planning-memory-checkpoint.js +3 -0
  94. package/packages/client/dist/private-execution/planning-research-checkpoint.js +4 -4
  95. package/packages/client/dist/private-execution/root-checkpoint.js +1 -1
  96. package/packages/client/dist/private-execution/root-memory-git-evidence.d.ts +30 -0
  97. package/packages/client/dist/private-execution/root-memory-git-evidence.js +3 -0
  98. package/packages/client/dist/private-execution/root-memory-recovery.d.ts +16 -0
  99. package/packages/client/dist/private-execution/root-memory-recovery.js +1 -0
  100. package/packages/client/dist/private-execution/root-memory-request.d.ts +28 -0
  101. package/packages/client/dist/private-execution/root-memory-request.js +1 -0
  102. package/packages/client/dist/private-execution/root-memory-scope.d.ts +28 -0
  103. package/packages/client/dist/private-execution/root-memory-scope.js +1 -0
  104. package/packages/client/dist/private-execution/root-memory-writer.d.ts +22 -0
  105. package/packages/client/dist/private-execution/root-memory-writer.js +1 -0
  106. package/packages/client/dist/private-execution/session-lease.d.ts +19 -0
  107. package/packages/client/dist/private-execution/session-lease.js +1 -0
  108. package/packages/client/dist/private-execution/ux-source-validation.js +1 -1
  109. package/packages/client/dist/runner-cli.js +0 -0
  110. package/packages/client/dist/yolo/change-evidence-collector.d.ts +2 -2
  111. package/packages/client/dist/yolo/change-evidence-collector.js +1 -1
  112. package/packages/client/dist/yolo/spec-envelope-collector.js +2 -2
  113. package/packages/shared/dist/invocation/index.js +4 -2
  114. package/packages/shared/dist/invocation/packed-invoke.d.ts +12 -0
  115. package/packages/shared/dist/invocation/packed-invoke.js +58 -0
  116. package/packages/shared/dist/invocation/packed-invoke.test.d.ts +1 -0
  117. package/packages/shared/dist/invocation/packed-invoke.test.js +21 -0
  118. package/packages/shared/dist/package.json +1 -0
  119. package/packages/shared/dist/planning/diagnosis-state.js +5 -2
  120. package/packages/shared/dist/private-qa-structural-admission.js +14 -0
  121. package/packages/shared/dist/private-yolo-predecessor-decision.js +32 -0
  122. package/packages/shared/dist/project-memory-targets.js +243 -0
  123. package/packages/shared/dist/project-validation-commands.js +96 -0
  124. package/packages/shared/dist/yolo/change-evidence.js +35 -0
  125. package/packages/shared/dist/yoloop/branch-unit.js +10 -1
  126. package/packages/shared/dist/yoloop/root-memory-effect.js +57 -0
  127. package/targets-stubs/antigravity/gemini.md +1 -1
  128. package/targets-stubs/antigravity/skill/SKILL.md +1 -1
  129. package/targets-stubs/claude-code/neocortex-root.agent.yaml +1 -1
  130. package/targets-stubs/claude-code/neocortex-root.md +2 -2
  131. package/targets-stubs/claude-code/neocortex.agent.yaml +1 -1
  132. package/targets-stubs/claude-code/neocortex.md +2 -2
  133. package/targets-stubs/codex/AGENTS.md +1 -1
  134. package/targets-stubs/cursor/agent.md +2 -2
  135. package/targets-stubs/gemini-cli/agent.md +2 -2
  136. package/targets-stubs/opencode/neocortex-root.md +1 -1
  137. package/targets-stubs/vscode/neocortex.agent.md +2 -2
@@ -1 +1 @@
1
- import{parse as H}from"@babel/parser";import{lstatSync as q,readFileSync as G}from"node:fs";import{join as K,posix as V}from"node:path";const Q=1024*1024,ee=1e5,z=/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;function p(){throw new Error("private-execution-ux-source-unverified")}function o(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function j(e,t){const r=q(K(e,t));(!r.isFile()||r.isSymbolicLink()||r.size<1||r.size>Q)&&p();const s=new TextDecoder("utf-8",{fatal:!0}).decode(G(K(e,t)));return(!s.trim()||s.includes("\0"))&&p(),s}function I(e,t){const r=H(j(e,t),{sourceType:"module",plugins:["typescript","jsx"],errorRecovery:!1});let s=0;const i=[r];for(;i.length>0;){const l=i.pop();if(o(l)){++s>ee&&p();for(const[n,f]of Object.entries(l))n==="loc"||n==="tokens"||n==="comments"||n==="errors"||(Array.isArray(f)?i.push(...f):o(f)&&i.push(f))}}return r}function E(e){const t=e.program;return(!o(t)||!Array.isArray(t.body))&&p(),t.body.filter(o)}function m(e,t){if(!o(e)||e.type!=="ObjectExpression"||!Array.isArray(e.properties))return;const r=e.properties.filter(s=>o(s)&&s.type==="ObjectProperty"&&s.computed!==!0&&o(s.key)&&(s.key.name===t||s.key.value===t));return r.length===1&&o(r[0])?r[0].value:void 0}function g(e){return o(e)&&e.type==="StringLiteral"&&typeof e.value=="string"?e.value:void 0}function y(e){return o(e)&&e.type==="Identifier"&&typeof e.name=="string"?e.name:void 0}function x(e){return e.type==="VariableDeclaration"&&Array.isArray(e.declarations)?e.declarations.filter(o):[]}function D(e){let t=e;for(let r=0;r<4&&o(t)&&["TSAsExpression","TSSatisfiesExpression","TSTypeAssertion","ParenthesizedExpression"].includes(String(t.type));r++)t=t.expression;return t}function te(e,t){const r=e.flatMap(x).filter(s=>y(s.id)===t);return r.length===1?D(r[0].init):void 0}function R(e,t){for(const r of e){if(r.type!=="ExportNamedDeclaration"||!o(r.declaration))continue;const s=r.declaration;if(s.type==="FunctionDeclaration"&&o(s.id)&&s.id.name===t)return s;const i=x(s).find(l=>o(l.id)&&l.id.name===t);if(i)return D(i.init)}}function A(e,t){const r=[],s=[e];for(;s.length>0;){const i=s.pop();if(o(i)){i.type===t&&r.push(i);for(const[l,n]of Object.entries(i))l==="loc"||l==="comments"||(Array.isArray(n)?s.push(...n):o(n)&&s.push(n))}}return r}function P(e){return e.screenId.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,64)}function U(e){return e.split(/[^A-Za-z0-9]+/).filter(Boolean).map(t=>`${t.charAt(0).toUpperCase()}${t.slice(1).toLowerCase()}`).join("")}function Z(e,t,r){const s=[];for(const i of e){if(i.type!=="ImportDeclaration"||i.importKind==="type"||!o(i.source)||typeof i.source.value!="string"||!i.source.value.startsWith("./")&&!i.source.value.startsWith("../"))continue;const l=V.normalize(V.join(V.dirname(t),i.source.value));if(!(l!==r.screenViewPath&&l!==r.screenViewPath.replace(/\.tsx$/,"")))for(const n of Array.isArray(i.specifiers)?i.specifiers:[])o(n)&&n.type==="ImportSpecifier"&&o(n.imported)&&n.imported.name===r.screenViewExport&&n.importKind!=="type"&&o(n.local)&&typeof n.local.name=="string"&&s.push(n.local.name)}return s.length!==1&&p(),s[0]}function re(e,t){return A(e,"JSXOpeningElement").some(r=>o(r.name)&&r.name.name===t)}function w(e,t,r){const s=e.filter(i=>i.type==="ImportDeclaration"&&o(i.source)&&i.source.value===t).flatMap(i=>Array.isArray(i.specifiers)?i.specifiers:[]).filter(i=>o(i)&&i.type==="ImportSpecifier"&&o(i.imported)&&i.imported.name===r&&o(i.local)&&typeof i.local.name=="string").map(i=>i.local);return s.length===1?s[0].name:void 0}function Y(e,t,r){return o(e)&&e.type==="CallExpression"&&o(e.callee)&&e.callee.type==="MemberExpression"&&e.callee.computed!==!0&&y(e.callee.object)===t&&y(e.callee.property)===r}function ne(e,t){const r=w(t,"storybook/test","within"),s=w(t,"storybook/test","userEvent"),i=w(t,"storybook/test","expect");if(!r||!s||!i||!Array.isArray(e.params)||!o(e.params[0])||e.params[0].type!=="ObjectPattern"||!Array.isArray(e.params[0].properties)||!e.params[0].properties.some(a=>o(a)&&o(a.key)&&a.key.name==="canvasElement"&&o(a.value)&&a.value.name==="canvasElement"))return!1;const l=A(e.body,"VariableDeclarator"),n=l.filter(a=>o(a.init)&&a.init.type==="CallExpression"&&y(a.init.callee)===r&&Array.isArray(a.init.arguments)&&a.init.arguments.length===1&&y(a.init.arguments[0])==="canvasElement").map(a=>y(a.id)).filter(a=>!!a),f=l.filter(a=>n.some(k=>Y(a.init,k,"getByRole")&&Array.isArray(a.init.arguments)&&g(a.init.arguments[0])==="button"&&typeof g(m(a.init.arguments[1],"name"))=="string"&&!!g(m(a.init.arguments[1],"name"))?.trim())).map(a=>y(a.id)).filter(a=>!!a);if(f.length===0)return!1;const u=A(e.body,"AwaitExpression").map(a=>a.argument),$=u.some(a=>Y(a,s,"tab")&&Array.isArray(a.arguments)&&a.arguments.length===0),h=u.some(a=>o(a)&&a.type==="CallExpression"&&o(a.callee)&&a.callee.type==="MemberExpression"&&y(a.callee.property)==="toHaveFocus"&&o(a.callee.object)&&a.callee.object.type==="CallExpression"&&y(a.callee.object.callee)===i&&Array.isArray(a.callee.object.arguments)&&f.includes(y(a.callee.object.arguments[0])??""));return $&&h}function se(e,t,r){const s=`src/screens/${P(t)}/${P(t)}`,i=I(e,t.screenViewPath),l=R(E(i),t.screenViewExport);(!l||A(l,"JSXElement").length+A(l,"JSXFragment").length===0)&&p();const n=I(e,t.appRoutePath),f=Z(E(n),t.appRoutePath,t);re(n,f)||p();const u=`${s}.stories.tsx`,$=I(e,u),h=E($),a=r==="storybook-react-vite"?"@storybook/react-vite":"@storybook/nextjs-vite";(!w(h,a,"Meta")||!w(h,a,"StoryObj"))&&p();const k=Z(h,u,t),C=h.filter(c=>c.type==="ExportDefaultDeclaration");C.length!==1&&p();const O=D(C[0].declaration),T=y(O)?te(h,y(O)):O;(y(m(T,"component"))!==k||g(m(T,"title"))!==`Screens/${t.screenId}`)&&p();const v=new Set;for(const c of t.states)for(const d of t.viewports){const L=`${U(c)}${U(d)}`;v.add(L);const b=R(h,L);if((!o(b)||b.type!=="ObjectExpression"||g(m(m(b,"args"),"state"))!==c||g(m(m(m(b,"parameters"),"viewport"),"defaultViewport"))!==d)&&p(),t.critical&&(c==="success"||c==="recovery")){const N=m(b,"play");(!o(N)||!["ArrowFunctionExpression","FunctionExpression"].includes(String(N.type))||!ne(N,h))&&p()}}const F=h.filter(c=>c.type==="ExportNamedDeclaration");F.some(c=>!o(c.declaration)||x(c.declaration).length!==1||Array.isArray(c.specifiers)&&c.specifiers.length>0)&&p();const X=F.flatMap(c=>x(c.declaration)).map(c=>y(c.id)).filter(c=>!!c);(X.length!==v.size||X.some(c=>!v.has(c)))&&p();const W=I(e,`${s}.fixtures.ts`);E(W).filter(c=>c.type==="ExportNamedDeclaration").flatMap(c=>o(c.declaration)?x(c.declaration):[]).some(c=>{const d=m(c.init,"synthetic");return o(d)&&d.type==="BooleanLiteral"&&d.value===!0&&m(c.init,"data")!==void 0})||p();const _=I(e,`${s}.handlers.ts`),B=E(_);(!B.some(c=>c.type==="ImportDeclaration"&&o(c.source)&&c.source.value==="msw"&&Array.isArray(c.specifiers)&&c.specifiers.some(d=>o(d)&&o(d.imported)&&d.imported.name==="http"))||!B.some(c=>c.type==="ExportNamedDeclaration"&&o(c.declaration)&&x(c.declaration).some(d=>o(d.init)&&d.init.type==="ArrayExpression"&&Array.isArray(d.init.elements)&&d.init.elements.length>0))||!A(_,"CallExpression").some(c=>o(c.callee)&&c.callee.type==="MemberExpression"&&o(c.callee.object)&&c.callee.object.name==="http"))&&p();const M=j(e,`${s}.mdx`),J=new RegExp(`import\\s+\\*\\s+as\\s+([A-Za-z_$][\\w$]*)\\s+from\\s+['"]\\./${P(t)}\\.stories(?:\\.tsx)?['"];?\\r?\\n(?:[ \\t]*\\r?\\n)+`).exec(M);(!/import\s+\{\s*Meta\s*\}\s+from\s+['"]@storybook\/addon-docs\/blocks['"]/.test(M)||!J||!M.includes(`<Meta of={${J[1]}} />`))&&p()}function S(e){return Array.isArray(e)?`[${e.map(S).join(",")}]`:e&&typeof e=="object"?`{${Object.entries(e).sort(([t],[r])=>t.localeCompare(r)).map(([t,r])=>`${JSON.stringify(t)}:${S(r)}`).join(",")}}`:JSON.stringify(e)??"null"}function oe(e){const t=S(e);let r=2166136261;for(let s=0;s<t.length;s++)r^=t.charCodeAt(s),r=Math.imul(r,16777619);return`uxm-${(r>>>0).toString(16).padStart(8,"0")}`}function ie(e,t){let r;try{r=JSON.parse(j(e,"docs/architecture/ux-coverage-manifest.json"))}catch{p()}(!o(r)||r.schemaVersion!==1||r.manifestId!=="P201-UX-MANIFEST-01"||!Array.isArray(r.entries)||typeof r.fingerprint!="string"||Object.keys(r).sort().join(",")!=="entries,fingerprint,manifestId,schemaVersion"||r.fingerprint!==oe(r.entries))&&p();const s=new Map;for(const n of t.screens)for(const f of n.states)for(const u of n.viewports)s.set(`Screens/${n.screenId}/${f}/${u}`,{screen:n,state:f,viewport:u});r.entries.length!==s.size&&p();const i=new Set;let l="";for(const n of r.entries){(!o(n)||typeof n.storyId!="string"||i.has(n.storyId))&&p(),l&&l.localeCompare(n.storyId)>=0&&p(),l=n.storyId,Object.keys(n).sort().join(",")!=="approvalEvidenceIds,fixtureId,handlerIds,journeyIds,screenId,screenViewPath,state,storyId,viewport"&&p(),i.add(n.storyId);const f=s.get(n.storyId);(!f||n.screenId!==f.screen.screenId||n.state!==f.state||n.viewport!==f.viewport||n.screenViewPath!==f.screen.screenViewPath||!Array.isArray(n.approvalEvidenceIds)||S([...n.approvalEvidenceIds].sort())!==S([...f.screen.approvalEvidenceIds].sort())||!Array.isArray(n.journeyIds)||n.journeyIds.length<1||n.journeyIds.some(u=>typeof u!="string"||!z.test(u))||new Set(n.journeyIds).size!==n.journeyIds.length||typeof n.fixtureId!="string"||!z.test(n.fixtureId)||!Array.isArray(n.handlerIds)||n.handlerIds.length<1||n.handlerIds.some(u=>typeof u!="string"||!z.test(u))||new Set(n.handlerIds).size!==n.handlerIds.length)&&p()}}function fe(e,t){try{for(const[r,s]of[["docs/architecture/ux-design.md","P201-UX-STORYBOOK-01"],["docs/architecture/storybook-ux-contract.md","P201-UX-STORYBOOK-01"]])j(e,r).includes(s)||p();for(const r of t.screens)se(e,r,t.adapterId);ie(e,t)}catch{p()}}export{fe as validateUxCandidateSource};
1
+ import{parse as H}from"@babel/parser";import{lstatSync as q,readFileSync as G}from"node:fs";import{join as U,posix as V}from"node:path";const Q=1024*1024,ee=1e5,P=/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;function p(){throw new Error("private-execution-ux-source-unverified")}function o(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function k(e,r){const t=q(U(e,r));(!t.isFile()||t.isSymbolicLink()||t.size<1||t.size>Q)&&p();const s=new TextDecoder("utf-8",{fatal:!0}).decode(G(U(e,r)));return(!s.trim()||s.includes("\0"))&&p(),s}function w(e,r){const t=H(k(e,r),{sourceType:"module",plugins:["typescript","jsx"],errorRecovery:!1});let s=0;const i=[t];for(;i.length>0;){const f=i.pop();if(o(f)){++s>ee&&p();for(const[n,l]of Object.entries(f))n==="loc"||n==="tokens"||n==="comments"||n==="errors"||(Array.isArray(l)?i.push(...l):o(l)&&i.push(l))}}return t}function S(e){const r=e.program;return(!o(r)||!Array.isArray(r.body))&&p(),r.body.filter(o)}function m(e,r){if(!o(e)||e.type!=="ObjectExpression"||!Array.isArray(e.properties))return;const t=e.properties.filter(s=>o(s)&&s.type==="ObjectProperty"&&s.computed!==!0&&o(s.key)&&(s.key.name===r||s.key.value===r));return t.length===1&&o(t[0])?t[0].value:void 0}function E(e){return o(e)&&e.type==="StringLiteral"&&typeof e.value=="string"?e.value:void 0}function u(e){return o(e)&&e.type==="Identifier"&&typeof e.name=="string"?e.name:void 0}function A(e){return e.type==="VariableDeclaration"&&Array.isArray(e.declarations)?e.declarations.filter(o):[]}function b(e){let r=e;for(let t=0;t<4&&o(r)&&["TSAsExpression","TSSatisfiesExpression","TSTypeAssertion","ParenthesizedExpression"].includes(String(r.type));t++)r=r.expression;return r}function te(e,r){const t=e.flatMap(A).filter(s=>u(s.id)===r);return t.length===1?b(t[0].init):void 0}function K(e,r){for(const t of e){if(t.type!=="ExportNamedDeclaration"||!o(t.declaration))continue;const s=t.declaration;if(s.type==="FunctionDeclaration"&&o(s.id)&&s.id.name===r)return s;const i=A(s).find(f=>o(f.id)&&f.id.name===r);if(i)return b(i.init)}}function g(e,r){const t=[],s=[e];for(;s.length>0;){const i=s.pop();if(o(i)){i.type===r&&t.push(i);for(const[f,n]of Object.entries(i))f==="loc"||f==="comments"||(Array.isArray(n)?s.push(...n):o(n)&&s.push(n))}}return t}function z(e){return e.screenId.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,64)}function R(e){return e.split(/[^A-Za-z0-9]+/).filter(Boolean).map(r=>`${r.charAt(0).toUpperCase()}${r.slice(1).toLowerCase()}`).join("")}function Z(e,r,t){const s=[];for(const i of e){if(i.type!=="ImportDeclaration"||i.importKind==="type"||!o(i.source)||typeof i.source.value!="string"||!i.source.value.startsWith("./")&&!i.source.value.startsWith("../"))continue;const f=V.normalize(V.join(V.dirname(r),i.source.value));if(!(f!==t.screenViewPath&&f!==t.screenViewPath.replace(/\.tsx$/,"")))for(const n of Array.isArray(i.specifiers)?i.specifiers:[])o(n)&&n.type==="ImportSpecifier"&&o(n.imported)&&n.imported.name===t.screenViewExport&&n.importKind!=="type"&&o(n.local)&&typeof n.local.name=="string"&&s.push(n.local.name)}return s.length!==1&&p(),s[0]}function re(e,r){return g(e,"JSXOpeningElement").some(t=>o(t.name)&&t.name.name===r)}function j(e,r,t){const s=e.filter(i=>i.type==="ImportDeclaration"&&o(i.source)&&i.source.value===r).flatMap(i=>Array.isArray(i.specifiers)?i.specifiers:[]).filter(i=>o(i)&&i.type==="ImportSpecifier"&&o(i.imported)&&i.imported.name===t&&o(i.local)&&typeof i.local.name=="string").map(i=>i.local);return s.length===1?s[0].name:void 0}function Y(e,r,t){return o(e)&&e.type==="CallExpression"&&o(e.callee)&&e.callee.type==="MemberExpression"&&e.callee.computed!==!0&&u(e.callee.object)===r&&u(e.callee.property)===t}function ne(e,r){const t=j(r,"storybook/test","within"),s=j(r,"storybook/test","userEvent"),i=j(r,"storybook/test","expect");if(!t||!s||!i||!Array.isArray(e.params)||!o(e.params[0])||e.params[0].type!=="ObjectPattern"||!Array.isArray(e.params[0].properties)||!e.params[0].properties.some(a=>o(a)&&o(a.key)&&a.key.name==="canvasElement"&&o(a.value)&&a.value.name==="canvasElement"))return!1;const f=g(e.body,"VariableDeclarator"),n=f.filter(a=>o(a.init)&&a.init.type==="CallExpression"&&u(a.init.callee)===t&&Array.isArray(a.init.arguments)&&a.init.arguments.length===1&&u(a.init.arguments[0])==="canvasElement").map(a=>u(a.id)).filter(a=>!!a),l=f.filter(a=>n.some(O=>Y(a.init,O,"getByRole")&&Array.isArray(a.init.arguments)&&E(a.init.arguments[0])==="button"&&typeof E(m(a.init.arguments[1],"name"))=="string"&&!!E(m(a.init.arguments[1],"name"))?.trim())).map(a=>u(a.id)).filter(a=>!!a);if(l.length===0)return!1;const d=g(e.body,"AwaitExpression").map(a=>a.argument),x=d.some(a=>Y(a,s,"tab")&&Array.isArray(a.arguments)&&a.arguments.length===0),h=d.some(a=>o(a)&&a.type==="CallExpression"&&o(a.callee)&&a.callee.type==="MemberExpression"&&u(a.callee.property)==="toHaveFocus"&&o(a.callee.object)&&a.callee.object.type==="CallExpression"&&u(a.callee.object.callee)===i&&Array.isArray(a.callee.object.arguments)&&l.includes(u(a.callee.object.arguments[0])??""));return x&&h}function se(e,r){const t=b(e);if(o(t)&&["ArrowFunctionExpression","FunctionExpression"].includes(String(t.type)))return t;const s=u(t);if(!s||!o(t))return;const i=r.flatMap(d=>A(d).filter(x=>u(x.id)===s).map(x=>({kind:d.kind,declaration:x})));if(i.length!==1||i[0].kind!=="const")return;const f=i[0].declaration;if(typeof f.start!="number"||typeof t.start!="number"||f.start>=t.start)return;const n={body:r};if(g(n,"AssignmentExpression").some(d=>u(b(d.left))===s)||g(n,"UpdateExpression").some(d=>u(b(d.argument))===s))return;const l=b(f.init);return o(l)&&["ArrowFunctionExpression","FunctionExpression"].includes(String(l.type))?l:void 0}function oe(e,r,t){const s=`src/screens/${z(r)}/${z(r)}`,i=w(e,r.screenViewPath),f=K(S(i),r.screenViewExport);(!f||g(f,"JSXElement").length+g(f,"JSXFragment").length===0)&&p();const n=w(e,r.appRoutePath),l=Z(S(n),r.appRoutePath,r);re(n,l)||p();const d=`${s}.stories.tsx`,x=w(e,d),h=S(x),a=t==="storybook-react-vite"?"@storybook/react-vite":"@storybook/nextjs-vite";(!j(h,a,"Meta")||!j(h,a,"StoryObj"))&&p();const O=Z(h,d,r),D=h.filter(c=>c.type==="ExportDefaultDeclaration");D.length!==1&&p();const v=b(D[0].declaration),C=u(v)?te(h,u(v)):v;(u(m(C,"component"))!==O||E(m(C,"title"))!==`Screens/${r.screenId}`)&&p();const M=new Set;for(const c of r.states)for(const y of r.viewports){const J=`${R(c)}${R(y)}`;M.add(J);const I=K(h,J);if((!o(I)||I.type!=="ObjectExpression"||E(m(m(I,"args"),"state"))!==c||E(m(m(m(I,"parameters"),"viewport"),"defaultViewport"))!==y)&&p(),r.critical&&(c==="success"||c==="recovery")){const L=se(m(I,"play"),h);(!L||!ne(L,h))&&p()}}const F=h.filter(c=>c.type==="ExportNamedDeclaration");F.some(c=>!o(c.declaration)||A(c.declaration).length!==1||Array.isArray(c.specifiers)&&c.specifiers.length>0)&&p();const T=F.flatMap(c=>A(c.declaration)).map(c=>u(c.id)).filter(c=>!!c);(T.length!==M.size||T.some(c=>!M.has(c)))&&p();const W=w(e,`${s}.fixtures.ts`);S(W).filter(c=>c.type==="ExportNamedDeclaration").flatMap(c=>o(c.declaration)?A(c.declaration):[]).some(c=>{const y=m(c.init,"synthetic");return o(y)&&y.type==="BooleanLiteral"&&y.value===!0&&m(c.init,"data")!==void 0})||p();const X=w(e,`${s}.handlers.ts`),_=S(X);(!_.some(c=>c.type==="ImportDeclaration"&&o(c.source)&&c.source.value==="msw"&&Array.isArray(c.specifiers)&&c.specifiers.some(y=>o(y)&&o(y.imported)&&y.imported.name==="http"))||!_.some(c=>c.type==="ExportNamedDeclaration"&&o(c.declaration)&&A(c.declaration).some(y=>o(y.init)&&y.init.type==="ArrayExpression"&&Array.isArray(y.init.elements)&&y.init.elements.length>0))||!g(X,"CallExpression").some(c=>o(c.callee)&&c.callee.type==="MemberExpression"&&o(c.callee.object)&&c.callee.object.name==="http"))&&p();const N=k(e,`${s}.mdx`),B=new RegExp(`import\\s+\\*\\s+as\\s+([A-Za-z_$][\\w$]*)\\s+from\\s+['"]\\./${z(r)}\\.stories(?:\\.tsx)?['"];?\\r?\\n(?:[ \\t]*\\r?\\n)+`).exec(N);(!/import\s+\{\s*Meta\s*\}\s+from\s+['"]@storybook\/addon-docs\/blocks['"]/.test(N)||!B||!N.includes(`<Meta of={${B[1]}} />`))&&p()}function $(e){return Array.isArray(e)?`[${e.map($).join(",")}]`:e&&typeof e=="object"?`{${Object.entries(e).sort(([r],[t])=>r.localeCompare(t)).map(([r,t])=>`${JSON.stringify(r)}:${$(t)}`).join(",")}}`:JSON.stringify(e)??"null"}function ie(e){const r=$(e);let t=2166136261;for(let s=0;s<r.length;s++)t^=r.charCodeAt(s),t=Math.imul(t,16777619);return`uxm-${(t>>>0).toString(16).padStart(8,"0")}`}function ae(e,r){let t;try{t=JSON.parse(k(e,"docs/architecture/ux-coverage-manifest.json"))}catch{p()}(!o(t)||t.schemaVersion!==1||t.manifestId!=="P201-UX-MANIFEST-01"||!Array.isArray(t.entries)||typeof t.fingerprint!="string"||Object.keys(t).sort().join(",")!=="entries,fingerprint,manifestId,schemaVersion")&&p(),t.fingerprint!==ie(t.entries)&&p();const s=new Map;for(const n of r.screens)for(const l of n.states)for(const d of n.viewports)s.set(`Screens/${n.screenId}/${l}/${d}`,{screen:n,state:l,viewport:d});t.entries.length!==s.size&&p();const i=new Set;let f="";for(const n of t.entries){(!o(n)||typeof n.storyId!="string"||i.has(n.storyId))&&p(),f&&f.localeCompare(n.storyId)>=0&&p(),f=n.storyId,Object.keys(n).sort().join(",")!=="approvalEvidenceIds,fixtureId,handlerIds,journeyIds,screenId,screenViewPath,state,storyId,viewport"&&p(),i.add(n.storyId);const l=s.get(n.storyId);(!l||n.screenId!==l.screen.screenId||n.state!==l.state||n.viewport!==l.viewport||n.screenViewPath!==l.screen.screenViewPath||!Array.isArray(n.approvalEvidenceIds)||$([...n.approvalEvidenceIds].sort())!==$([...l.screen.approvalEvidenceIds].sort())||!Array.isArray(n.journeyIds)||n.journeyIds.length<1||n.journeyIds.some(d=>typeof d!="string"||!P.test(d))||new Set(n.journeyIds).size!==n.journeyIds.length||typeof n.fixtureId!="string"||!P.test(n.fixtureId)||!Array.isArray(n.handlerIds)||n.handlerIds.length<1||n.handlerIds.some(d=>typeof d!="string"||!P.test(d))||new Set(n.handlerIds).size!==n.handlerIds.length)&&p()}}function de(e,r){try{for(const[t,s]of[["docs/architecture/ux-design.md","P201-UX-STORYBOOK-01"],["docs/architecture/storybook-ux-contract.md","P201-UX-STORYBOOK-01"]])k(e,t).includes(s)||p();for(const t of r.screens)oe(e,t,r.adapterId);ae(e,r)}catch{p()}}export{de as validateUxCandidateSource};
File without changes
@@ -1,4 +1,4 @@
1
- import { type YoloChangeEvidenceV1 } from '../../../shared/dist/yolo/change-evidence.js';
1
+ import { type YoloChangeEvidence } from '../../../shared/dist/yolo/change-evidence.js';
2
2
  /** Reacquire only an expired setup lease for this exact story through P207's CAS boundary. */
3
3
  export declare function reconcileYoloChangeEvidenceLease(options: {
4
4
  readonly projectRoot: string;
@@ -11,4 +11,4 @@ export declare function collectYoloChangeEvidence(options: {
11
11
  readonly expectedHeadSha: string;
12
12
  readonly storyId?: string;
13
13
  readonly epicId?: string;
14
- }): YoloChangeEvidenceV1;
14
+ }): YoloChangeEvidence;
@@ -1 +1 @@
1
- import{execFileSync as p}from"node:child_process";import{realpathSync as f}from"node:fs";import{createYoloChangeEvidenceV1 as w}from"../../../shared/dist/yolo/change-evidence.js";import{readGitLifecycleRuntimeSync as u}from"../git/git-lifecycle-store.js";async function j(e){let r;try{r=u(e.projectRoot,{required:!0}).epics[e.epicId]?.branch_lease}catch(c){if(c instanceof Error&&c.message==="git-lifecycle-runtime-missing")return;throw new Error("yolo-change-evidence-unavailable")}if(r==null)return;if(typeof r!="object"||Array.isArray(r)||r.ownerStoryId!==e.storyId||typeof r.expiresAt!="string")throw new Error("yolo-change-evidence-unavailable");const n=Date.parse(r.expiresAt);if(!Number.isFinite(n))throw new Error("yolo-change-evidence-unavailable");if(n>Date.now())return;if(typeof r.sessionId!="string"||!/^setup-[a-f0-9]{64}$/.test(r.sessionId)||r.idempotencyKey!==r.sessionId)throw new Error("yolo-change-evidence-unavailable");const{prepareDirectYoloSetup:o}=await import("../git/direct-yolo-checkpoint.js"),i=await o(e);if(!i.ok||i.value.storyId!==e.storyId||i.value.epicId!==e.epicId||Date.parse(i.value.leaseExpiresAt)<=Date.now())throw new Error("yolo-change-evidence-unavailable")}function t(e,r){try{return p("git",["-C",e,...r],{encoding:"utf8",timeout:3e3,maxBuffer:1024*1024,stdio:["ignore","pipe","ignore"]})}catch{throw new Error("yolo-change-evidence-unavailable")}}function x(e){if(!/^[A-Za-z0-9][A-Za-z0-9_./-]{0,119}$/.test(e.defaultBranch)||e.defaultBranch.includes(".."))throw new Error("yolo-change-evidence-unavailable");const r=t(e.projectRoot,["rev-parse","--show-toplevel"]).trim();if(f(r)!==f(e.projectRoot))throw new Error("yolo-change-evidence-unavailable");const n=t(e.projectRoot,["rev-parse","HEAD"]).trim();if(n!==e.expectedHeadSha)throw new Error("yolo-change-evidence-stale");let o,i=!1,c=null;if(e.storyId&&e.epicId)try{const a=u(e.projectRoot).epics[e.epicId],l=a?.branch_lease,h=t(e.projectRoot,["symbolic-ref","--quiet","--short","HEAD"]).trim();if(a?.branch_mode==="epic"&&a.execution_branch===h&&(c=h),l&&typeof l=="object"&&!Array.isArray(l)){const d=l;if(d.ownerStoryId!==e.storyId||typeof d.expiresAt!="string"||Date.parse(d.expiresAt)<=Date.now()||c===null)throw new Error("yolo-change-evidence-unavailable");i=!0}}catch{throw new Error("yolo-change-evidence-unavailable")}if(i)o=n;else{const s=c===null?"":t(e.projectRoot,["ls-remote","--heads","origin",`refs/heads/${c}`]).trim();if(s){const a=/^([a-f0-9]{40})\trefs\/heads\/([^\n]+)$/.exec(s);if(!a||a[2]!==c||t(e.projectRoot,["merge-base","HEAD",a[1]]).trim()!==a[1])throw new Error("yolo-change-evidence-unavailable");o=a[1]}else try{o=t(e.projectRoot,["merge-base","HEAD",e.defaultBranch]).trim()}catch{o=t(e.projectRoot,["merge-base","HEAD",`refs/remotes/origin/${e.defaultBranch}`]).trim()}}const y=t(e.projectRoot,["diff","--name-only","-z",o,"--"]).split("\0").filter(Boolean),m=t(e.projectRoot,["ls-files","--others","--exclude-standard","-z"]).split("\0").filter(Boolean),v=w({baseSha:o,headSha:n,changedPaths:[...y,...m]});if(t(e.projectRoot,["rev-parse","HEAD"]).trim()!==n)throw new Error("yolo-change-evidence-stale");return v}export{x as collectYoloChangeEvidence,j as reconcileYoloChangeEvidenceLease};
1
+ import{execFileSync as p}from"node:child_process";import{realpathSync as f}from"node:fs";import{createYoloChangeEvidence as w}from"../../../shared/dist/yolo/change-evidence.js";import{readGitLifecycleRuntimeSync as u}from"../git/git-lifecycle-store.js";async function j(e){let r;try{r=u(e.projectRoot,{required:!0}).epics[e.epicId]?.branch_lease}catch(c){if(c instanceof Error&&c.message==="git-lifecycle-runtime-missing")return;throw new Error("yolo-change-evidence-unavailable")}if(r==null)return;if(typeof r!="object"||Array.isArray(r)||r.ownerStoryId!==e.storyId||typeof r.expiresAt!="string")throw new Error("yolo-change-evidence-unavailable");const n=Date.parse(r.expiresAt);if(!Number.isFinite(n))throw new Error("yolo-change-evidence-unavailable");if(n>Date.now())return;if(typeof r.sessionId!="string"||!/^setup-[a-f0-9]{64}$/.test(r.sessionId)||r.idempotencyKey!==r.sessionId)throw new Error("yolo-change-evidence-unavailable");const{prepareDirectYoloSetup:o}=await import("../git/direct-yolo-checkpoint.js"),i=await o(e);if(!i.ok||i.value.storyId!==e.storyId||i.value.epicId!==e.epicId||Date.parse(i.value.leaseExpiresAt)<=Date.now())throw new Error("yolo-change-evidence-unavailable")}function t(e,r){try{return p("git",["-C",e,...r],{encoding:"utf8",timeout:3e3,maxBuffer:1024*1024,stdio:["ignore","pipe","ignore"]})}catch{throw new Error("yolo-change-evidence-unavailable")}}function x(e){if(!/^[A-Za-z0-9][A-Za-z0-9_./-]{0,119}$/.test(e.defaultBranch)||e.defaultBranch.includes(".."))throw new Error("yolo-change-evidence-unavailable");const r=t(e.projectRoot,["rev-parse","--show-toplevel"]).trim();if(f(r)!==f(e.projectRoot))throw new Error("yolo-change-evidence-unavailable");const n=t(e.projectRoot,["rev-parse","HEAD"]).trim();if(n!==e.expectedHeadSha)throw new Error("yolo-change-evidence-stale");let o,i=!1,c=null;if(e.storyId&&e.epicId)try{const a=u(e.projectRoot).epics[e.epicId],l=a?.branch_lease,h=t(e.projectRoot,["symbolic-ref","--quiet","--short","HEAD"]).trim();if(a?.branch_mode==="epic"&&a.execution_branch===h&&(c=h),l&&typeof l=="object"&&!Array.isArray(l)){const d=l;if(d.ownerStoryId!==e.storyId||typeof d.expiresAt!="string"||Date.parse(d.expiresAt)<=Date.now()||c===null)throw new Error("yolo-change-evidence-unavailable");i=!0}}catch{throw new Error("yolo-change-evidence-unavailable")}if(i)o=n;else{const s=c===null?"":t(e.projectRoot,["ls-remote","--heads","origin",`refs/heads/${c}`]).trim();if(s){const a=/^([a-f0-9]{40})\trefs\/heads\/([^\n]+)$/.exec(s);if(!a||a[2]!==c||t(e.projectRoot,["merge-base","HEAD",a[1]]).trim()!==a[1])throw new Error("yolo-change-evidence-unavailable");o=a[1]}else try{o=t(e.projectRoot,["merge-base","HEAD",e.defaultBranch]).trim()}catch{o=t(e.projectRoot,["merge-base","HEAD",`refs/remotes/origin/${e.defaultBranch}`]).trim()}}const y=t(e.projectRoot,["diff","--name-only","-z",o,"--"]).split("\0").filter(Boolean),m=t(e.projectRoot,["ls-files","--others","--exclude-standard","-z"]).split("\0").filter(Boolean),v=w({baseSha:o,headSha:n,changedPaths:[...y,...m]});if(t(e.projectRoot,["rev-parse","HEAD"]).trim()!==n)throw new Error("yolo-change-evidence-stale");return v}export{x as collectYoloChangeEvidence,j as reconcileYoloChangeEvidenceLease};
@@ -1,5 +1,5 @@
1
- import{execFileSync as L}from"node:child_process";import{existsSync as S,readFileSync as T,realpathSync as w,statSync as E}from"node:fs";import{join as y,sep as b}from"node:path";import{createYoloSpecEnvelopeV1 as x,YOLO_SPEC_ARTIFACT_LIMIT_BYTES as C,YOLO_SPEC_MAX_ARTIFACTS as R,YOLO_SPEC_TOTAL_LIMIT_BYTES as g}from"../../../shared/dist/yolo/spec-envelope.js";import{inspectFrontmatterContext as $}from"../../../shared/dist/frontmatter-context-contract.js";const O=["core/templates/specs/feature-spec-template.md","core/templates/specs/architecture-spec-template.md","core/templates/specs/contract-spec-template.md","core/templates/specs/story-spec-template.md","core/templates/specs/traceability-matrix-template.md"],W=/(?:^|[\s([`'";])((?:docs\/(?:stories|epics|specs|architecture|examples)\/|core\/templates\/specs\/)[A-Za-z0-9_./-]+\.(?:md|mdx|feature))(?:$|[\s)\]`'",;])/gm;function I(e){return e.startsWith("core/templates/")?"template":e.startsWith("docs/epics/")?"epic":e.startsWith("docs/stories/")&&e.endsWith(".story.md")?"story":e.toLowerCase().includes("adr")?"adr":e.toLowerCase().includes("contract")?"contract":e.toLowerCase().includes("nfr")?"nfr":e.endsWith(".feature")?"bdd":e.toLowerCase().includes("traceability")?"traceability":e.startsWith("docs/examples/")?"example":"spec"}function P(e){return[...new Set([...e.matchAll(W)].map(r=>r[1]).filter(r=>!!r))].sort()}function i(e,r){const c=w(e);let o;try{o=w(y(c,r))}catch{throw new Error("yolo-spec-envelope-required")}if(!o.startsWith(`${c}${b}`))throw new Error("yolo-spec-envelope-path-out-of-scope");if(!E(o).isFile())throw new Error("yolo-spec-envelope-unsafe");if(E(o).size>C)throw new Error("yolo-spec-envelope-too-large");return T(o,"utf8")}function f(e,r){const o=$(e,{context:r==="story"?"story-target":"epic-target",explicitlySelected:!0});if(o.status==="malformed"||o.status==="oversized")throw new Error("yolo-spec-envelope-unsafe");if(o.status==="absent")return e;const a=e.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/);if(!a)throw new Error("yolo-spec-envelope-unsafe");return`---
1
+ import{execFileSync as L}from"node:child_process";import{existsSync as S,readFileSync as T,realpathSync as w,statSync as E}from"node:fs";import{join as f,sep as b}from"node:path";import{createYoloSpecEnvelopeV1 as x,YOLO_SPEC_ARTIFACT_LIMIT_BYTES as C,YOLO_SPEC_MAX_ARTIFACTS as R,YOLO_SPEC_TOTAL_LIMIT_BYTES as g}from"../../../shared/dist/yolo/spec-envelope.js";import{inspectFrontmatterContext as $}from"../../../shared/dist/frontmatter-context-contract.js";const O=["core/templates/specs/feature-spec-template.md","core/templates/specs/architecture-spec-template.md","core/templates/specs/contract-spec-template.md","core/templates/specs/story-spec-template.md","core/templates/specs/traceability-matrix-template.md"],W=/(?:^|[\s([`'";])((?:docs\/(?:stories|epics|specs|architecture|examples)\/|core\/templates\/specs\/)[A-Za-z0-9_./-]+\.(?:md|mdx|feature))(?:$|[\s)\]`'",;])/gm;function I(e){return e.startsWith("core/templates/")?"template":e.startsWith("docs/epics/")?"epic":e.startsWith("docs/stories/")&&e.endsWith(".story.md")?"story":e.endsWith(".rtm.md")?"traceability":e.toLowerCase().includes("adr")?"adr":e.toLowerCase().includes("contract")?"contract":e.toLowerCase().includes("nfr")?"nfr":e.endsWith(".feature")?"bdd":e.toLowerCase().includes("traceability")?"traceability":e.startsWith("docs/examples/")?"example":"spec"}function P(e){return[...new Set([...e.matchAll(W)].map(r=>r[1]).filter(r=>!!r))].sort()}function i(e,r){const c=w(e);let o;try{o=w(f(c,r))}catch{throw new Error("yolo-spec-envelope-required")}if(!o.startsWith(`${c}${b}`))throw new Error("yolo-spec-envelope-path-out-of-scope");if(!E(o).isFile())throw new Error("yolo-spec-envelope-unsafe");if(E(o).size>C)throw new Error("yolo-spec-envelope-too-large");return T(o,"utf8")}function m(e,r){const o=$(e,{context:r==="story"?"story-target":"epic-target",explicitlySelected:!0});if(o.status==="malformed"||o.status==="oversized")throw new Error("yolo-spec-envelope-unsafe");if(o.status==="absent")return e;const a=e.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/);if(!a)throw new Error("yolo-spec-envelope-unsafe");return`---
2
2
  ${Object.entries(o.metadata).map(([s,l])=>`${s}: ${JSON.stringify(l)}`).join(`
3
3
  `)}
4
4
  ---
5
- ${e.slice(a[0].length)}`}function v(e){try{return L("git",["-C",e,"rev-parse","HEAD"],{encoding:"utf8",timeout:2e3,stdio:["ignore","pipe","ignore"]}).trim()}catch{throw new Error("yolo-spec-envelope-stale")}}function M(e){const r=`docs/stories/${e.storyId}.story.md`,c=`docs/epics/epic-${e.epicId}.md`,o=e.headSha??v(e.projectRoot),a=f(i(e.projectRoot,r),"story"),m=f(i(e.projectRoot,c),"epic"),s=[{kind:"story",path:r,content:a},{kind:"epic",path:c,content:m}],l=P(a),u=new Set([`docs/stories/${e.storyId}.spec.md`,`docs/stories/${e.storyId}.tasks.md`,`docs/stories/${e.storyId}.rtm.md`]),_=[...l.filter(t=>u.has(t)),...l.filter(t=>!u.has(t))];let p=s.reduce((t,n)=>t+Buffer.byteLength(n.content,"utf8"),0),h=0;for(const t of _){if(t===r||t===c||!S(y(e.projectRoot,t)))continue;if(t.startsWith("docs/stories/")&&t.endsWith(".story.md")||t.startsWith("docs/epics/"))throw new Error("yolo-spec-envelope-target-mismatch");const n=i(e.projectRoot,t),d=Buffer.byteLength(n,"utf8");if(s.length>=R||p+d>g){if(u.has(t))throw new Error("yolo-spec-envelope-too-large");h+=1;continue}s.push({kind:I(t),path:t,content:n}),p+=d}h&&e.onOmittedReferences?.(h);for(const t of O){if(t===r||t===c||l.includes(t)||!S(y(e.projectRoot,t)))continue;const n=i(e.projectRoot,t),d=Buffer.byteLength(n,"utf8");s.length>=R||p+d>g||(s.push({kind:I(t),path:t,content:n}),p+=d)}const j=x({storyId:e.storyId,epicId:e.epicId,targetPath:r,inputSha256:e.inputSha256,headSha:o,collectedAt:e.collectedAt??new Date().toISOString(),artifacts:s}),A=e.headSha??v(e.projectRoot);if(o!==A||f(i(e.projectRoot,r),"story")!==a||f(i(e.projectRoot,c),"epic")!==m||s.some(t=>t.kind!=="story"&&t.kind!=="epic"&&i(e.projectRoot,t.path)!==t.content))throw new Error("yolo-spec-envelope-stale");return j}export{M as collectYoloSpecEnvelope};
5
+ ${e.slice(a[0].length)}`}function j(e){try{return L("git",["-C",e,"rev-parse","HEAD"],{encoding:"utf8",timeout:2e3,stdio:["ignore","pipe","ignore"]}).trim()}catch{throw new Error("yolo-spec-envelope-stale")}}function M(e){const r=`docs/stories/${e.storyId}.story.md`,c=`docs/epics/epic-${e.epicId}.md`,o=e.headSha??j(e.projectRoot),a=m(i(e.projectRoot,r),"story"),u=m(i(e.projectRoot,c),"epic"),s=[{kind:"story",path:r,content:a},{kind:"epic",path:c,content:u}],l=new Set([`docs/stories/${e.storyId}.spec.md`,`docs/stories/${e.storyId}.tasks.md`,`docs/stories/${e.storyId}.rtm.md`]),h=[...new Set([...P(a),...[...l].filter(t=>S(f(e.projectRoot,t)))])].sort(),v=[...h.filter(t=>l.has(t)),...h.filter(t=>!l.has(t))];let p=s.reduce((t,n)=>t+Buffer.byteLength(n.content,"utf8"),0),y=0;for(const t of v){if(t===r||t===c||!S(f(e.projectRoot,t)))continue;if(t.startsWith("docs/stories/")&&t.endsWith(".story.md")||t.startsWith("docs/epics/"))throw new Error("yolo-spec-envelope-target-mismatch");const n=i(e.projectRoot,t),d=Buffer.byteLength(n,"utf8");if(s.length>=R||p+d>g){if(l.has(t))throw new Error("yolo-spec-envelope-too-large");y+=1;continue}s.push({kind:I(t),path:t,content:n}),p+=d}y&&e.onOmittedReferences?.(y);for(const t of O){if(t===r||t===c||h.includes(t)||!S(f(e.projectRoot,t)))continue;const n=i(e.projectRoot,t),d=Buffer.byteLength(n,"utf8");s.length>=R||p+d>g||(s.push({kind:I(t),path:t,content:n}),p+=d)}const _=x({storyId:e.storyId,epicId:e.epicId,targetPath:r,inputSha256:e.inputSha256,headSha:o,collectedAt:e.collectedAt??new Date().toISOString(),artifacts:s}),A=e.headSha??j(e.projectRoot);if(o!==A||m(i(e.projectRoot,r),"story")!==a||m(i(e.projectRoot,c),"epic")!==u||s.some(t=>t.kind!=="story"&&t.kind!=="epic"&&i(e.projectRoot,t.path)!==t.content))throw new Error("yolo-spec-envelope-stale");return _}export{M as collectYoloSpecEnvelope};
@@ -177,10 +177,12 @@ export function lexInvocationEnvelope(input) {
177
177
  if (escaped) {
178
178
  const allowed = char === '\\' || char === ' ' || char === '\t' || char === '\r' || char === '\n'
179
179
  || (quote === 'single' && char === "'") || (quote === 'double' && char === '"');
180
- if (!allowed)
180
+ // A quoted Windows path such as src\win\async.c is literal user text.
181
+ // Keep unquoted shell-shaped escapes fail-closed.
182
+ if (!allowed && !quote)
181
183
  return { ok: false, reason: 'unsupported_escape', tokenCount: tokens.length };
182
184
  startSegment(i - 1, quote);
183
- value += char;
185
+ value += allowed ? char : `\\${char}`;
184
186
  escaped = false;
185
187
  continue;
186
188
  }
@@ -0,0 +1,12 @@
1
+ export declare const PACKED_INVOKE_MAX_UNCOMPRESSED_BYTES: number;
2
+ interface PackedInvokeEnvelope {
3
+ readonly schemaVersion: 'PackedInvokeEnvelope/1';
4
+ readonly compression: 'gzip';
5
+ readonly uncompressedBytes: number;
6
+ readonly sha256: string;
7
+ readonly payload: string;
8
+ }
9
+ /** Keep the signed HTTP body below 256 KiB without changing the invoke JSON. */
10
+ export declare function packInvokeEnvelope(body: Record<string, unknown>): PackedInvokeEnvelope;
11
+ export declare function unpackInvokeEnvelope(value: unknown): Record<string, unknown>;
12
+ export {};
@@ -0,0 +1,58 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { gzipSync, gunzipSync } from 'node:zlib';
3
+ export const PACKED_INVOKE_MAX_UNCOMPRESSED_BYTES = 512 * 1024;
4
+ const PACKED_INVOKE_MAX_COMPRESSED_BYTES = 192 * 1024;
5
+ function isRecord(value) {
6
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
7
+ }
8
+ /** Keep the signed HTTP body below 256 KiB without changing the invoke JSON. */
9
+ export function packInvokeEnvelope(body) {
10
+ const raw = Buffer.from(JSON.stringify(body), 'utf8');
11
+ if (raw.length > PACKED_INVOKE_MAX_UNCOMPRESSED_BYTES)
12
+ throw new Error('packed-invoke-too-large');
13
+ const compressed = gzipSync(raw, { level: 6 });
14
+ if (compressed.length > PACKED_INVOKE_MAX_COMPRESSED_BYTES)
15
+ throw new Error('packed-invoke-too-large');
16
+ return {
17
+ schemaVersion: 'PackedInvokeEnvelope/1',
18
+ compression: 'gzip',
19
+ uncompressedBytes: raw.length,
20
+ sha256: createHash('sha256').update(raw).digest('hex'),
21
+ payload: compressed.toString('base64'),
22
+ };
23
+ }
24
+ export function unpackInvokeEnvelope(value) {
25
+ if (!isRecord(value) || Object.keys(value).sort().join(',') !==
26
+ 'compression,payload,schemaVersion,sha256,uncompressedBytes'
27
+ || value.schemaVersion !== 'PackedInvokeEnvelope/1' || value.compression !== 'gzip'
28
+ || !Number.isSafeInteger(value.uncompressedBytes) || value.uncompressedBytes < 1
29
+ || value.uncompressedBytes > PACKED_INVOKE_MAX_UNCOMPRESSED_BYTES
30
+ || typeof value.sha256 !== 'string' || !/^[a-f0-9]{64}$/.test(value.sha256)
31
+ || typeof value.payload !== 'string' || value.payload.length > Math.ceil(PACKED_INVOKE_MAX_COMPRESSED_BYTES * 4 / 3) + 4
32
+ || !/^[A-Za-z0-9+/]+={0,2}$/.test(value.payload))
33
+ throw new Error('packed-invoke-invalid');
34
+ const compressed = Buffer.from(value.payload, 'base64');
35
+ if (compressed.length > PACKED_INVOKE_MAX_COMPRESSED_BYTES
36
+ || compressed.toString('base64') !== value.payload)
37
+ throw new Error('packed-invoke-invalid');
38
+ let raw;
39
+ try {
40
+ raw = gunzipSync(compressed, { maxOutputLength: PACKED_INVOKE_MAX_UNCOMPRESSED_BYTES });
41
+ }
42
+ catch {
43
+ throw new Error('packed-invoke-invalid');
44
+ }
45
+ if (raw.length !== value.uncompressedBytes
46
+ || createHash('sha256').update(raw).digest('hex') !== value.sha256)
47
+ throw new Error('packed-invoke-invalid');
48
+ let parsed;
49
+ try {
50
+ parsed = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(raw));
51
+ }
52
+ catch {
53
+ throw new Error('packed-invoke-invalid');
54
+ }
55
+ if (!isRecord(parsed) || parsed.schemaVersion === 'PackedInvokeEnvelope/1')
56
+ throw new Error('packed-invoke-invalid');
57
+ return parsed;
58
+ }
@@ -0,0 +1,21 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { packInvokeEnvelope, unpackInvokeEnvelope } from './packed-invoke.js';
3
+ describe('signed invoke transport packing', () => {
4
+ it('round trips a large structural request within the HTTP body limit', () => {
5
+ const original = { args: '*yolo @docs/stories/P222.26.story.md', stateSnapshot: {
6
+ stories: Object.fromEntries(Array.from({ length: 27 }, (_, index) => [
7
+ `P222.${index + 1}`, { checkpoint: { qaReceipt: 'verified'.repeat(1300), headSha: String(index) } },
8
+ ])),
9
+ } };
10
+ expect(Buffer.byteLength(JSON.stringify(original))).toBeGreaterThan(262_144);
11
+ const packed = packInvokeEnvelope(original);
12
+ expect(Buffer.byteLength(JSON.stringify(packed))).toBeLessThan(262_144);
13
+ expect(unpackInvokeEnvelope(packed)).toEqual(original);
14
+ });
15
+ it('rejects modified bytes, extra fields, and excess expansion', () => {
16
+ const packed = packInvokeEnvelope({ args: '*status' });
17
+ expect(() => unpackInvokeEnvelope({ ...packed, sha256: '0'.repeat(64) })).toThrow('packed-invoke-invalid');
18
+ expect(() => unpackInvokeEnvelope({ ...packed, injected: true })).toThrow('packed-invoke-invalid');
19
+ expect(() => packInvokeEnvelope({ data: 'x'.repeat(512 * 1024) })).toThrow('packed-invoke-too-large');
20
+ });
21
+ });
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -9,6 +9,8 @@ function record(value) {
9
9
  return value !== null && typeof value === 'object' && !Array.isArray(value);
10
10
  }
11
11
  const SCALARS = ['goal', 'problem', 'desiredOutcome', 'rawIntent'];
12
+ /** Original selected input is preserved; ordinary summary fields stay at 512. */
13
+ export const PLANNING_RAW_INTENT_MAX_CHARS = 4096;
12
14
  const LISTS = ['context', 'users', 'surfaces', 'constraints', 'assumptions', 'risks', 'nonGoals',
13
15
  'validationExpectations', 'debtRefs', 'repositoryEvidencePaths', 'journeyIds', 'screenIds',
14
16
  'storybookStoryIds', 'backendContractIds', 'featureBlockerIds', 'remediationRefs'];
@@ -39,8 +41,9 @@ export function canonicalPlanningIntake(value) {
39
41
  allowedKeys(value, [...SCALARS, ...LISTS, ...BOOLEANS, 'examples', 'contracts']);
40
42
  const result = {};
41
43
  for (const key of SCALARS)
42
- if (value[key] !== undefined)
43
- result[key] = safeText(value[key]);
44
+ if (value[key] !== undefined) {
45
+ result[key] = safeText(value[key], key === 'rawIntent' ? PLANNING_RAW_INTENT_MAX_CHARS : 512);
46
+ }
44
47
  for (const key of LISTS)
45
48
  if (value[key] !== undefined) {
46
49
  const entries = value[key];
@@ -0,0 +1,14 @@
1
+ export function isPrivateQaStructuralAdmission(value) {
2
+ if (!value || typeof value !== 'object' || Array.isArray(value))
3
+ return false;
4
+ const r = value, checks = r.checks;
5
+ return Object.keys(r).sort().join('|') === ['schemaVersion', 'kind', 'stepId', 'generationId', 'graphRevision', 'topologyGenerationId', 'tier', 'checks', 'publicSafe'].sort().join('|')
6
+ && r.schemaVersion === 1 && r.kind === 'server-private-qa-structural-admission' && r.stepId === 'step-8721319d'
7
+ && typeof r.generationId === 'string' && /^sha256:[a-f0-9]{64}$/.test(r.generationId)
8
+ && typeof r.graphRevision === 'string' && /^[a-f0-9]{64}$/.test(r.graphRevision)
9
+ && typeof r.topologyGenerationId === 'string' && /^sha256:[a-f0-9]{64}$/.test(r.topologyGenerationId)
10
+ && ['free', 'pro', 'enterprise'].includes(String(r.tier)) && r.publicSafe === true
11
+ && !!checks && typeof checks === 'object' && !Array.isArray(checks)
12
+ && Object.keys(checks).sort().join('|') === ['classifiedAssetDelivery', 'licensedCommandAdmission', 'registeredStatusMapping', 'prerequisiteStateAdmitted'].sort().join('|')
13
+ && Object.values(checks).every(result => result === true);
14
+ }
@@ -0,0 +1,32 @@
1
+ export function isPrivateQaSkippedPredecessors(value) {
2
+ if (!Array.isArray(value) || value.length > 2)
3
+ return false;
4
+ const ids = [];
5
+ for (const item of value) {
6
+ if (isPrivateYoloSkippedPredecessors([item])) {
7
+ ids.push(item.stepId);
8
+ continue;
9
+ }
10
+ if (!item || typeof item !== 'object' || Array.isArray(item))
11
+ return false;
12
+ const r = item;
13
+ if (Object.keys(r).sort().join('|') !== ['stepId', 'featureGate', 'reason', 'tier', 'publicSafe'].sort().join('|')
14
+ || r.stepId !== 'step-b2fe7cb5' || r.featureGate !== 'validate-tests'
15
+ || r.reason !== 'subscription-tier' || r.tier !== 'free' || r.publicSafe !== true)
16
+ return false;
17
+ ids.push(r.stepId);
18
+ }
19
+ return new Set(ids).size === ids.length && (value.length < 2
20
+ || ids[0] === 'step-a8ce5c64' && ids[1] === 'step-b2fe7cb5' && value[0].tier === 'free');
21
+ }
22
+ export function isPrivateYoloSkippedPredecessors(value) {
23
+ return Array.isArray(value) && value.length <= 1 && value.every(item => {
24
+ if (!item || typeof item !== 'object' || Array.isArray(item))
25
+ return false;
26
+ const r = item;
27
+ return Object.keys(r).sort().join('|') === ['stepId', 'featureFlagId', 'enabled', 'tier', 'publicSafe'].sort().join('|')
28
+ && r.stepId === 'step-a8ce5c64' && r.featureFlagId === 'property-testing'
29
+ && typeof r.enabled === 'boolean' && ['free', 'pro', 'enterprise'].includes(String(r.tier))
30
+ && (r.enabled === false || r.tier === 'free') && r.publicSafe === true;
31
+ });
32
+ }
@@ -0,0 +1,243 @@
1
+ /**
2
+ * Canonical project-memory targets for agent platforms.
3
+ *
4
+ * Always-loaded memory files should stay compact: universal laws, active context,
5
+ * and references to deeper docs. They must not become full architecture dumps.
6
+ */
7
+ function projectFileRefs(...paths) {
8
+ return paths.map((path) => ({ scope: 'project', path }));
9
+ }
10
+ export const CANONICAL_PROJECT_MEMORY_SOURCE = 'NEOCORTEX.md';
11
+ const MANDATORY_SEMANTIC_SYMLINK = {
12
+ canonicalSource: CANONICAL_PROJECT_MEMORY_SOURCE,
13
+ semanticFileRequired: true,
14
+ symlinkBacked: true,
15
+ wrapperAllowed: false,
16
+ includeFallbackAllowed: false,
17
+ requiresWrapperPreservation: false,
18
+ fallbackIsCompatibilityRemediation: true,
19
+ policy: 'mandatory-semantic-symlink',
20
+ notes: 'Semantic platform memory file must resolve to NEOCORTEX.md through a symlink; do not replace it with an unrelated wrapper or copied frontmatter.',
21
+ };
22
+ const SYMLINK_BACKED_WRAPPER = {
23
+ canonicalSource: CANONICAL_PROJECT_MEMORY_SOURCE,
24
+ semanticFileRequired: true,
25
+ symlinkBacked: true,
26
+ wrapperAllowed: true,
27
+ includeFallbackAllowed: false,
28
+ requiresWrapperPreservation: true,
29
+ fallbackIsCompatibilityRemediation: true,
30
+ policy: 'symlink-backed-wrapper',
31
+ notes: 'Platform wrapper/frontmatter is allowed only when the semantic memory payload remains symlink-backed by NEOCORTEX.md.',
32
+ };
33
+ const SAFE_INCLUDE_FALLBACK = {
34
+ canonicalSource: CANONICAL_PROJECT_MEMORY_SOURCE,
35
+ semanticFileRequired: true,
36
+ symlinkBacked: true,
37
+ wrapperAllowed: true,
38
+ includeFallbackAllowed: true,
39
+ requiresWrapperPreservation: true,
40
+ fallbackIsCompatibilityRemediation: true,
41
+ policy: 'safe-include-fallback',
42
+ notes: 'Use a safe include/import only for platforms that cannot consume symlinks directly; the include must resolve back to NEOCORTEX.md.',
43
+ };
44
+ function bidirectionalReference(requirement) {
45
+ return {
46
+ canonicalSource: CANONICAL_PROJECT_MEMORY_SOURCE,
47
+ resolvesVia: requirement.policy,
48
+ feedbackTrigger: '*update-memory',
49
+ guidance: 'Treat NEOCORTEX.md as canonical project memory; consult it before platform-specific memory, and run *update-memory when durable project context changes should flow back to the canonical source.',
50
+ };
51
+ }
52
+ export const PROJECT_MEMORY_TARGET_IDS = [
53
+ 'claude-code',
54
+ 'codex',
55
+ 'grok',
56
+ 'gemini-cli',
57
+ 'antigravity',
58
+ 'vscode',
59
+ 'cursor',
60
+ 'opencode',
61
+ 'openclaw',
62
+ 'kimi',
63
+ 'github-copilot-cli',
64
+ ];
65
+ export const PROJECT_MEMORY_TARGETS = {
66
+ canonical: {
67
+ targetId: 'canonical',
68
+ platformName: 'Neocortex Canonical Memory',
69
+ canonicalSource: CANONICAL_PROJECT_MEMORY_SOURCE,
70
+ primaryFile: CANONICAL_PROJECT_MEMORY_SOURCE,
71
+ secondaryFiles: projectFileRefs('AGENTS.md', 'CLAUDE.md', 'GEMINI.md'),
72
+ ownedBlockName: 'NEOCORTEX-MEMORY',
73
+ templateKind: 'neocortex-md',
74
+ budget: { maxLines: 220, maxBytes: 18_000 },
75
+ linkRequirement: MANDATORY_SEMANTIC_SYMLINK,
76
+ bidirectionalReference: bidirectionalReference(MANDATORY_SEMANTIC_SYMLINK),
77
+ requiresWrapperPreservation: false,
78
+ notes: 'Canonical compact project memory source for platform symlinks and wrappers. Store only summaries, indexes, and links to architecture docs here.',
79
+ },
80
+ 'claude-code': {
81
+ targetId: 'claude-code',
82
+ platformName: 'Claude Code',
83
+ canonicalSource: CANONICAL_PROJECT_MEMORY_SOURCE,
84
+ primaryFile: 'CLAUDE.md',
85
+ secondaryFiles: projectFileRefs('.claude/agents/neocortex.md'),
86
+ ownedBlockName: 'NEOCORTEX-MEMORY',
87
+ templateKind: 'claude-md',
88
+ budget: { maxLines: 320, maxBytes: 28_000 },
89
+ linkRequirement: MANDATORY_SEMANTIC_SYMLINK,
90
+ bidirectionalReference: bidirectionalReference(MANDATORY_SEMANTIC_SYMLINK),
91
+ requiresWrapperPreservation: false,
92
+ notes: 'Claude Code project memory. Resolve to NEOCORTEX.md; keep root content concise and link deeper docs with @path references.',
93
+ },
94
+ codex: {
95
+ targetId: 'codex',
96
+ platformName: 'Codex CLI',
97
+ canonicalSource: CANONICAL_PROJECT_MEMORY_SOURCE,
98
+ primaryFile: 'AGENTS.md',
99
+ secondaryFiles: projectFileRefs('.codex/agents/neocortex.toml'),
100
+ ownedBlockName: 'NEOCORTEX-MEMORY',
101
+ templateKind: 'agents-md',
102
+ budget: { maxLines: 220, maxBytes: 18_000 },
103
+ linkRequirement: MANDATORY_SEMANTIC_SYMLINK,
104
+ bidirectionalReference: bidirectionalReference(MANDATORY_SEMANTIC_SYMLINK),
105
+ requiresWrapperPreservation: true,
106
+ notes: 'Codex root instructions. Uppercase AGENTS.md is required on case-sensitive filesystems.',
107
+ },
108
+ grok: {
109
+ targetId: 'grok',
110
+ platformName: 'Grok Build',
111
+ canonicalSource: CANONICAL_PROJECT_MEMORY_SOURCE,
112
+ primaryFile: 'AGENTS.md',
113
+ secondaryFiles: projectFileRefs('.grok/skills/neocortex/SKILL.md'),
114
+ ownedBlockName: 'NEOCORTEX-MEMORY',
115
+ templateKind: 'agents-md',
116
+ budget: { maxLines: 220, maxBytes: 18_000 },
117
+ linkRequirement: MANDATORY_SEMANTIC_SYMLINK,
118
+ bidirectionalReference: bidirectionalReference(MANDATORY_SEMANTIC_SYMLINK),
119
+ requiresWrapperPreservation: true,
120
+ notes: 'Grok Build reads AGENTS.md and the project-local Neocortex Skill; both resolve to canonical NEOCORTEX.md context.',
121
+ },
122
+ 'gemini-cli': {
123
+ targetId: 'gemini-cli',
124
+ platformName: 'Gemini CLI',
125
+ canonicalSource: CANONICAL_PROJECT_MEMORY_SOURCE,
126
+ primaryFile: 'GEMINI.md',
127
+ secondaryFiles: projectFileRefs('.gemini/agents/neocortex.md'),
128
+ ownedBlockName: 'NEOCORTEX-MEMORY',
129
+ templateKind: 'gemini-md',
130
+ budget: { maxLines: 260, maxBytes: 22_000 },
131
+ linkRequirement: MANDATORY_SEMANTIC_SYMLINK,
132
+ bidirectionalReference: bidirectionalReference(MANDATORY_SEMANTIC_SYMLINK),
133
+ requiresWrapperPreservation: false,
134
+ notes: 'Gemini CLI context file. Prefer shallow @file.md imports for detailed architecture docs.',
135
+ },
136
+ antigravity: {
137
+ targetId: 'antigravity',
138
+ platformName: 'Antigravity',
139
+ canonicalSource: CANONICAL_PROJECT_MEMORY_SOURCE,
140
+ primaryFile: 'GEMINI.md',
141
+ secondaryFiles: projectFileRefs('.gemini/agents/neocortex.md'),
142
+ ownedBlockName: 'NEOCORTEX-MEMORY',
143
+ templateKind: 'gemini-md',
144
+ budget: { maxLines: 260, maxBytes: 22_000 },
145
+ linkRequirement: MANDATORY_SEMANTIC_SYMLINK,
146
+ bidirectionalReference: bidirectionalReference(MANDATORY_SEMANTIC_SYMLINK),
147
+ requiresWrapperPreservation: false,
148
+ notes: 'Antigravity currently shares GEMINI.md behavior with the Gemini target stubs.',
149
+ },
150
+ vscode: {
151
+ targetId: 'vscode',
152
+ platformName: 'VS Code / GitHub Copilot',
153
+ canonicalSource: CANONICAL_PROJECT_MEMORY_SOURCE,
154
+ primaryFile: '.github/copilot-instructions.md',
155
+ secondaryFiles: projectFileRefs('.github/instructions/neocortex.instructions.md', '.github/agents/neocortex.agent.md'),
156
+ ownedBlockName: 'NEOCORTEX-MEMORY',
157
+ templateKind: 'copilot-instructions',
158
+ budget: { maxLines: 180, maxBytes: 14_000 },
159
+ linkRequirement: SYMLINK_BACKED_WRAPPER,
160
+ bidirectionalReference: bidirectionalReference(SYMLINK_BACKED_WRAPPER),
161
+ requiresWrapperPreservation: true,
162
+ notes: 'VS Code and GitHub Copilot always-on repository instructions.',
163
+ },
164
+ cursor: {
165
+ targetId: 'cursor',
166
+ platformName: 'Cursor',
167
+ canonicalSource: CANONICAL_PROJECT_MEMORY_SOURCE,
168
+ primaryFile: '.cursor/rules/neocortex.mdc',
169
+ secondaryFiles: projectFileRefs('AGENTS.md'),
170
+ ownedBlockName: 'NEOCORTEX-MEMORY',
171
+ templateKind: 'cursor-rule',
172
+ budget: { maxLines: 180, maxBytes: 14_000 },
173
+ linkRequirement: SYMLINK_BACKED_WRAPPER,
174
+ bidirectionalReference: bidirectionalReference(SYMLINK_BACKED_WRAPPER),
175
+ requiresWrapperPreservation: true,
176
+ notes: 'Cursor rule memory. Use AGENTS.md as compatibility fallback when Cursor rules are absent.',
177
+ },
178
+ opencode: {
179
+ targetId: 'opencode',
180
+ platformName: 'OpenCode',
181
+ canonicalSource: CANONICAL_PROJECT_MEMORY_SOURCE,
182
+ primaryFile: 'AGENTS.md',
183
+ secondaryFiles: projectFileRefs('.opencode/AGENTS.md', '.opencode/agents/neocortex-root.md', '.opencode/agents/neocortex.md', '.agent/skills/neocortex/SKILL.md'),
184
+ ownedBlockName: 'NEOCORTEX-MEMORY',
185
+ templateKind: 'agents-md',
186
+ budget: { maxLines: 220, maxBytes: 18_000 },
187
+ linkRequirement: MANDATORY_SEMANTIC_SYMLINK,
188
+ bidirectionalReference: bidirectionalReference(MANDATORY_SEMANTIC_SYMLINK),
189
+ requiresWrapperPreservation: true,
190
+ notes: 'OpenCode agent memory. It consumes AGENTS.md-compatible instructions and must resolve to canonical NEOCORTEX.md.',
191
+ },
192
+ openclaw: {
193
+ targetId: 'openclaw',
194
+ platformName: 'OpenClaw',
195
+ canonicalSource: CANONICAL_PROJECT_MEMORY_SOURCE,
196
+ primaryFile: '.openclaw/skills/neocortex/SKILL.md',
197
+ secondaryFiles: [{ scope: 'user', path: '.openclaw/skills/neocortex/SKILL.md' }],
198
+ ownedBlockName: 'NEOCORTEX-MEMORY',
199
+ templateKind: 'agents-md',
200
+ budget: { maxLines: 220, maxBytes: 18_000 },
201
+ linkRequirement: SAFE_INCLUDE_FALLBACK,
202
+ bidirectionalReference: bidirectionalReference(SAFE_INCLUDE_FALLBACK),
203
+ requiresWrapperPreservation: true,
204
+ notes: 'OpenClaw Skill thin-client memory entrypoint. Use the project Skill path when --create-project is requested; do not mutate ~/.openclaw/openclaw.json, and keep memory content public-safe.',
205
+ },
206
+ kimi: {
207
+ targetId: 'kimi',
208
+ platformName: 'Kimi',
209
+ canonicalSource: CANONICAL_PROJECT_MEMORY_SOURCE,
210
+ primaryFile: 'KIMI.md',
211
+ secondaryFiles: projectFileRefs('AGENTS.md', '.kimi/skills/neocortex/SKILL.md'),
212
+ ownedBlockName: 'NEOCORTEX-MEMORY',
213
+ templateKind: 'agents-md',
214
+ budget: { maxLines: 220, maxBytes: 18_000 },
215
+ linkRequirement: SAFE_INCLUDE_FALLBACK,
216
+ bidirectionalReference: bidirectionalReference(SAFE_INCLUDE_FALLBACK),
217
+ requiresWrapperPreservation: true,
218
+ notes: 'Kimi memory entrypoint. Prefer a symlink to NEOCORTEX.md; use a compact include only if the host cannot follow symlinks.',
219
+ },
220
+ 'github-copilot-cli': {
221
+ targetId: 'github-copilot-cli',
222
+ platformName: 'GitHub Copilot CLI / gh alias',
223
+ canonicalSource: CANONICAL_PROJECT_MEMORY_SOURCE,
224
+ primaryFile: '.github/copilot-instructions.md',
225
+ secondaryFiles: projectFileRefs('AGENTS.md'),
226
+ ownedBlockName: 'NEOCORTEX-MEMORY',
227
+ templateKind: 'copilot-instructions',
228
+ budget: { maxLines: 180, maxBytes: 14_000 },
229
+ linkRequirement: SAFE_INCLUDE_FALLBACK,
230
+ bidirectionalReference: bidirectionalReference(SAFE_INCLUDE_FALLBACK),
231
+ requiresWrapperPreservation: true,
232
+ notes: 'GitHub Copilot CLI or gh alias instructions. Resolve compact memory back to NEOCORTEX.md without copying private prompt bodies.',
233
+ },
234
+ };
235
+ export function getProjectMemoryTarget(targetId) {
236
+ return PROJECT_MEMORY_TARGETS[targetId];
237
+ }
238
+ export function isProjectMemoryTargetId(value) {
239
+ return value === 'canonical' || PROJECT_MEMORY_TARGET_IDS.includes(value);
240
+ }
241
+ export function listProjectMemoryTargets() {
242
+ return PROJECT_MEMORY_TARGET_IDS.map((targetId) => PROJECT_MEMORY_TARGETS[targetId]);
243
+ }