arkgate 4.6.2 → 4.6.3
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.
- package/CHANGELOG.md +21 -1
- package/README.md +17 -13
- package/bin/ark-mcp-runtime.mjs +5 -1
- package/bin/lib/ci-and-commands.mjs +4 -3
- package/bin/lib/first-run-help.mjs +7 -7
- package/bin/lib/host-support-matrix.mjs +13 -15
- package/bin/lib/status-command.mjs +1 -1
- package/bin/lib/write-path-capabilities.mjs +9 -5
- package/bin/lib/write-path-detect.mjs +3 -3
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/docs/README.md +4 -4
- package/docs/agent-guide.md +18 -13
- package/docs/ai-gates.md +29 -20
- package/docs/develop.md +4 -1
- package/docs/enthusiast/how-to-agent-gates.md +1 -1
- package/docs/package-surface.md +4 -3
- package/docs/product-voice.md +4 -4
- package/docs/threat-model.md +5 -1
- package/docs/use.md +6 -1
- package/package.json +1 -1
- package/server.json +3 -3
- package/templates/agent-skills/ark-coverage/SKILL.md +4 -3
- package/templates/skills/ark-coverage.md +4 -3
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var ts="4.6.2";var ns="1.5",kn="docs/diagnostics.md";function v(e){return typeof e=="string"&&e.length>0?e:void 0}function Cn(e,t){return Number.isInteger(e)&&Number(e)>0?Number(e):t}function Ot(e){let t=typeof e.ruleId=="string"?e.ruleId:typeof e.code=="string"?e.code:void 0,n=typeof e.file=="string"?e.file:void 0,r=typeof e.fromLayer=="string"?e.fromLayer:void 0,s=typeof e.toLayer=="string"?e.toLayer:void 0,i=typeof e.target=="string"?e.target:void 0;return[t,n,r??"",s??"",i??""].join("|")}function _t(e){let t=new Map;return e.map(n=>{let r=Ot(n),s=(t.get(r)??0)+1;return t.set(r,s),s===1?r:`${r}#${s}`})}function _n(e){let t=2166136261;for(let n=0;n<e.length;n+=1)t^=e.charCodeAt(n),t=Math.imul(t,16777619);return`fnv1a-${(t>>>0).toString(16).padStart(8,"0")}`}function xn(e){return`${kn}#${e}`}function rs(e,t,n){if(e==="LAYER_IMPORT_VIOLATION")return t.typeOnly||n.targetTypeOnlyExports===!0||n.namedBindingsTypeOnly===!0?"Move the referenced type to a mutually allowed layer, use `import type`, then preflight again.":n.peerIsolation===!0?"Extract the shared dependency to a shared layer, test at the public interface, then preflight again.":`Define a port in ${t.fromLayer??"the source layer"}, inject the ${t.toLayer??"outer-layer"} implementation, test at the public interface, then preflight again.`;if(e==="FORBIDDEN_GLOBAL")return`Inject ${t.target??"the capability"} through a port, test at the public interface, then preflight again.`;if(e==="CAPABILITY_VIOLATION")return`Define a ${v(n.capability)??"capability"} port in ${t.fromLayer??"the walled layer"}, bind the implementation outside it, test at the public interface, then preflight again.`;if(e==="CIRCULAR_DEPENDENCY")return"Extract the shared dependency into a third module, test at the public interface, then preflight again.";if(e==="RAW_EVENT_PUBLISH")return"Publish through a registered intent creator, then run Ark again.";if(e==="PUBLISH_MISSING_SOURCE")return"Add metadata.source to the publish call, then run Ark again.";if(e==="ARKRULE_STRUCTURE"||e==="ARKRULE_INVARIANT"||e==="INVARIANT_UNCOVERED"||e.startsWith("ARKRULE_")){let r=t.arkruleSource??"arkrules/<Layer>.json";return`Fix the structure or invariant for ${t.arkruleId??"the ArkRule"} (declared in ${r}), then preflight again. Do not demote the rule without a hash-bound policy acknowledgement.`}return`Resolve ${e} without weakening ark.config.json, then run Ark again.`}function xt(e,t="error",n){let r=v(e.ruleId)??v(e.code)??"ARK_UNKNOWN",s=e.severity==="warning"||e.failsStrict===!1||e.typeOnly===!0&&e.peerIsolation!==!0?"warning":t,i={...v(e.target)?{target:v(e.target)}:{},...v(e.fromLayer)?{fromLayer:v(e.fromLayer)}:{},...v(e.toLayer)?{toLayer:v(e.toLayer)}:{},...typeof e.typeOnly=="boolean"?{typeOnly:e.typeOnly}:{},...typeof e.targetTypeOnlyExports=="boolean"?{targetTypeOnlyExports:e.targetTypeOnlyExports}:{},...typeof e.sourcePureTypeModule=="boolean"?{sourcePureTypeModule:e.sourcePureTypeModule}:{},...typeof e.namedBindingsTypeOnly=="boolean"?{namedBindingsTypeOnly:e.namedBindingsTypeOnly}:{},...typeof e.portProofEligible=="boolean"?{portProofEligible:e.portProofEligible}:{},...typeof e.peerIsolation=="boolean"?{peerIsolation:e.peerIsolation}:{},...v(e.capability)?{capability:v(e.capability)}:{},...v(e.edgeKind)?{edgeKind:v(e.edgeKind)}:{},...v(e.arkruleId)?{arkruleId:v(e.arkruleId)}:{},...v(e.arkruleSource)?{arkruleSource:v(e.arkruleSource)}:{}},o=n??Ot(e),a=_n(o);return{ruleId:r,severity:s,message:v(e.message)??r,location:{file:v(e.file)??"<unknown>",line:Cn(e.line,1),column:Cn(e.column,1)},evidence:i,nextAction:v(e.nextAction)??rs(r,i,e),findingRef:a,targetKey:o,docsCodePath:xn(r)}}function ss(e){let t=e.completeness??"complete",n=e.mode??"lexical-compatibility";if(t==="complete"&&(e.completenessReasons?.length??0)>0)throw new Error("completenessReasons must be empty when completeness is complete.");let r=t==="complete"?[]:e.completenessReasons&&e.completenessReasons.length>0?e.completenessReasons.map(m=>({code:v(m.code)??"ANALYSIS_EVIDENCE_INCOMPLETE",message:v(m.message)??`Analysis ${t}: required evidence is incomplete.`,...v(m.file)?{file:v(m.file)}:{}})):[{code:t==="unavailable"?"ANALYSIS_UNAVAILABLE":"ANALYSIS_EVIDENCE_INCOMPLETE",message:`Analysis ${t}: required evidence is incomplete.`}],s={...v(e.policyHash)?{policyHash:v(e.policyHash)}:{},...v(e.resolverIdentity)?{resolverIdentity:v(e.resolverIdentity)}:{},...v(e.factsHash)?{factsHash:v(e.factsHash)}:{},...v(e.candidateTreeHash)?{candidateTreeHash:v(e.candidateTreeHash)}:{}};if(n==="resolved-candidate-facts"&&t!=="unavailable"){for(let m of["policyHash","resolverIdentity","factsHash","candidateTreeHash"])if(!s[m])throw new Error(`${m} is required for resolved ${t} adapter evidence.`)}let i=e.violations??[],o=e.warnings??[],a=_t(i),d=_t(o),u=[...i.map((m,c)=>xt(m,"error",a[c])),...o.map((m,c)=>xt(m,"warning",d[c]))],g={schemaVersion:"1.5",completenessReasons:r,diagnostics:u};if(n==="resolved-candidate-facts"){if(t==="unavailable")return{...g,mode:n,valid:!1,completeness:t,...s};let m={policyHash:s.policyHash,resolverIdentity:s.resolverIdentity,factsHash:s.factsHash,candidateTreeHash:s.candidateTreeHash};return t==="complete"?{...g,mode:n,valid:e.valid,completeness:t,...m}:{...g,mode:n,valid:!1,completeness:t,...m}}return t==="complete"?{...g,mode:n,valid:e.valid,completeness:t,...s}:{...g,mode:n,valid:!1,completeness:t,...s}}var is={$schema:"https://json-schema.org/draft/2020-12/schema",$id:"https://unpkg.com/arkgate@3/schemas/ark.analysis-result.schema.json",title:"ArkGate analysis result",type:"object",additionalProperties:!1,required:["schemaVersion","mode","valid","completeness","completenessReasons","diagnostics"],allOf:[{if:{properties:{completeness:{enum:["partial","unavailable"]}},required:["completeness"]},then:{properties:{valid:{const:!1}}}},{if:{properties:{mode:{const:"resolved-candidate-facts"},completeness:{enum:["complete","partial"]}},required:["mode","completeness"]},then:{required:["policyHash","resolverIdentity","factsHash","candidateTreeHash"]}},{if:{properties:{completeness:{const:"complete"}},required:["completeness"]},then:{properties:{completenessReasons:{maxItems:0}}},else:{properties:{completenessReasons:{minItems:1}}}}],properties:{schemaVersion:{const:"1.5"},mode:{enum:["lexical-compatibility","resolved-candidate-facts"]},valid:{type:"boolean"},completeness:{enum:["complete","partial","unavailable"]},completenessReasons:{type:"array",items:{type:"object",additionalProperties:!1,required:["code","message"],properties:{code:{type:"string",minLength:1},message:{type:"string",minLength:1},file:{type:"string",minLength:1}}}},policyHash:{type:"string",minLength:1},resolverIdentity:{type:"string",minLength:1},factsHash:{type:"string",minLength:1},candidateTreeHash:{type:"string",minLength:1},diagnostics:{type:"array",items:{type:"object",additionalProperties:!1,required:["ruleId","severity","message","location","evidence"],properties:{ruleId:{type:"string",minLength:1},severity:{enum:["error","warning"]},message:{type:"string",minLength:1},location:{type:"object",additionalProperties:!1,required:["file","line","column"],properties:{file:{type:"string",minLength:1},line:{type:"integer",minimum:1},column:{type:"integer",minimum:1}}},evidence:{type:"object",additionalProperties:!1,properties:{target:{type:"string"},fromLayer:{type:"string"},toLayer:{type:"string"},typeOnly:{type:"boolean"},targetTypeOnlyExports:{type:"boolean"},sourcePureTypeModule:{type:"boolean"},namedBindingsTypeOnly:{type:"boolean"},portProofEligible:{type:"boolean"},peerIsolation:{type:"boolean"},capability:{type:"string",minLength:1},edgeKind:{type:"string",minLength:1},arkruleId:{type:"string",minLength:1},arkruleSource:{type:"string",minLength:1}}},nextAction:{type:"string",minLength:1},findingRef:{type:"string",minLength:1,pattern:"^fnv1a-[0-9a-f]{8}$"},targetKey:{type:"string",minLength:1},docsCodePath:{type:"string",minLength:1}}}}}};var os="1.0",On="https://unpkg.com/arkgate@4/schemas/ark.project-identity.schema.json",We="^sha256:[a-f0-9]{64}$",Tn={type:"object",additionalProperties:!1,properties:{expectedRoot:{type:"string",minLength:1,description:"Absolute expected workspace/project directory. The initial authoritative handshake requires the exact project root; descendant calls also require expectedProjectId."},expectedProjectId:{type:"string",pattern:We,description:"Project id previously returned by ark_identity or ark_manifest."}}},Pn={type:"object",additionalProperties:!1,required:["status","authoritative"],properties:{status:{enum:["matched","unverified","mismatch"]},authoritative:{type:"boolean"},expectedRoot:{type:"string",minLength:1},expectedProjectId:{type:"string",pattern:We},code:{enum:["PROJECT_ROOT_MISMATCH","PROJECT_ID_MISMATCH","INVALID_PROJECT_EXPECTATION"]},message:{type:"string",minLength:1}}},as={$schema:"https://json-schema.org/draft/2020-12/schema",$id:On,title:"ArkGate MCP project identity",description:"Stable project binding plus separate runtime and architecture-contract evidence.",type:"object",additionalProperties:!1,required:["schemaVersion","projectId","resolvedRoot","resolvedConfigPath","arkgateVersion","contractHash","contractSource","runtimeId","processStartedAt"],properties:{schemaVersion:{const:"1.0"},projectId:{type:"string",pattern:We},resolvedRoot:{type:"string",minLength:1},resolvedConfigPath:{type:"string",minLength:1},arkgateVersion:{type:"string",minLength:1},contractHash:{type:"string",pattern:We},contractSource:{enum:["project","default-profile","manifest"]},runtimeId:{type:"string",minLength:1},processStartedAt:{type:"string",format:"date-time"}},$defs:{expectation:Tn,binding:Pn}};function ls(e,t,n){if(!e||!t)throw new Error("Project identity requires resolvedRoot and resolvedConfigPath.");let r=n(JSON.stringify({resolvedRoot:e,resolvedConfigPath:t})).toLowerCase();if(!/^[a-f0-9]{64}$/.test(r))throw new Error("Project identity hash adapter must return 64 hexadecimal SHA-256 characters.");return`sha256:${r}`}function cs(e){return{schemaVersion:"1.0",...e}}var Pt=Object.freeze(["network","filesystem","clock","randomness","environment","process","persistence"]),Nt=Object.freeze({fetch:"network",XMLHttpRequest:"network",Date:"clock","Date.now":"clock","Math.random":"randomness","process.env":"environment",process:"process"}),wt=Object.freeze(Object.keys(Nt).sort()),Tt=Object.freeze({fs:"filesystem","node:fs":"filesystem","fs/promises":"filesystem","node:fs/promises":"filesystem","fs-extra":"filesystem","graceful-fs":"filesystem",memfs:"filesystem",chokidar:"filesystem",http:"network",https:"network",http2:"network",net:"network",tls:"network",dgram:"network",dns:"network","node:http":"network","node:https":"network","node:http2":"network","node:net":"network","node:tls":"network","node:dgram":"network","node:dns":"network",axios:"network",undici:"network","node-fetch":"network",got:"network",ky:"network",superagent:"network",ws:"network",process:"process","node:process":"process",child_process:"process","node:child_process":"process","@prisma/client":"persistence",prisma:"persistence",pg:"persistence",mysql:"persistence",mysql2:"persistence",mongodb:"persistence",mongoose:"persistence",sqlite3:"persistence","better-sqlite3":"persistence",redis:"persistence",ioredis:"persistence",typeorm:"persistence",knex:"persistence","drizzle-orm":"persistence",sequelize:"persistence",kysely:"persistence","@supabase/supabase-js":"persistence"}),Lt=Object.freeze({process:Object.freeze(["process","node:process"])});function Le(e){if(!e||e.startsWith(".")||e.startsWith("/"))return null;let t=Tt[e];if(t)return t;let n=e.indexOf("/");if(n<0)return null;let r=e.slice(0,n),s=Tt[r];if(s)return s;let i=e.indexOf("/",n+1);return i<0?null:Tt[e.slice(0,i)]??null}function se(e,t){for(let n of t)if(Lt[n]?.includes(e))return n;return null}function Je(e){let t=e.split(".");for(let n=t.length;n>=1;n-=1){let r=t.slice(0,n).join("."),s=Nt[r];if(s)return s}return null}function ye(e){if(e?.pure===!0)return[...Pt].sort();let n=(e?.capabilities?.deny??[]).filter(r=>Pt.includes(r));return[...new Set(n)].sort()}function Ne(e,t){if(t.length===0)return!1;let n=new Set(t),r=e.split(".");for(let s=r.length;s>=1;s-=1)if(n.has(r.slice(0,s).join(".")))return!0;return!1}function Ze(e){let t=new Set,n=new Set,r=Object.keys(Nt);for(let s of e?.forbiddenGlobals??[]){let i=r.filter(o=>o===s||o.startsWith(`${s}.`));if(i.length===0)n.add(s);else for(let o of i)t.add(`ambient:${o}`);for(let o of Lt[s]??[])t.add(`import-exact:${o}`)}for(let s of ye(e)){if(t.add(`import:${s}`),s==="process")for(let i of Lt.process)t.add(`import-exact:${i}`);for(let i of r)Je(i)===s&&t.add(`ambient:${i}`)}return{atoms:[...t].sort(),rawGlobals:[...n].sort()}}var Ln=new Map;function Nn(e){return/[.*+?^${}()|[\]\\]/.test(e)?`\\${e}`:e}function Xe(e){let t="";for(let n=0;n<e.length;n+=1){let r=e[n];if(r==="\\"&&n+1<e.length){let s=e[n+1];if("*?{}[],".includes(s)||s==="\\"){t+="\\"+s,n+=1;continue}t+="/";continue}t+=r}return t}function ds(e){let t=0;for(let n=0;n<e.length;n+=1){let r=e[n];if(r==="\\"){n+=1;continue}if(r==="{")t+=1;else if(r==="}"&&(t-=1,t<0))return!1}return t===0}function le(e){let t=Ln.get(e);if(t)return t;let n=Xe(e),r=ds(n),s="",i=0;for(let a=0;a<n.length;a+=1){let d=n[a];d==="\\"&&a+1<n.length?(s+=Nn(n[a+1]),a+=1):d==="*"?n[a+1]==="*"?n[a+2]==="/"?(s+="(?:.*/)?",a+=2):(s+=".*",a+=1):s+="[^/]*":d==="?"?s+="[^/]":d==="{"&&r?(s+="(?:",i+=1):d==="}"&&r&&i>0?(s+=")",i-=1):d===","&&r&&i>0?s+="|":s+=Nn(d)}let o=new RegExp(`^${s}$`);return Ln.set(e,o),o}function ps(e){return Xe(String(e)).split("/").filter(Boolean).filter(n=>n!=="**"&&n!=="*"&&!n.includes("*")&&!n.includes("?")&&!n.includes("{")&&!n.includes("["))}function Mt(e,t){let n=Xe(String(e)),r=ps(n),s=n.replace(/\*/g,"").length,i=r.length*1e4+s;if(t==null||t==="")return i;let o=String(t).split(/[/\\]/).filter(Boolean);if(r.length===0)return s;let a=0,d=-1;for(let u of r){let g=-1;for(let m=a;m<o.length;m+=1)if(o[m]===u){g=m;break}if(g<0)return i;d=g,a=g+1}return(d+1)*1e6+r.length*1e4+s}function Q(e,t){let n=String(e).split(/[/\\]/).join("/"),r,s=-1;for(let i of t??[])if(!(i.exclude??[]).some(o=>le(o).test(n))){for(let o of i.patterns??[])if(le(o).test(n)){let a=Mt(o,n);a>s&&(s=a,r=i.name)}}return r}function wn(e,t){if(!t?.length)return;let n=String(e).split(/[/\\]/).filter(Boolean),r=new Set(t.map(s=>String(s).toLowerCase()));for(let s=0;s<n.length-1;s+=1)if(r.has(n[s].toLowerCase()))return`${n[s].toLowerCase()}/${n[s+1].toLowerCase()}`}function us(e){let t=new Set;for(let n of e??[]){let s=Xe(String(n)).split("/").filter(Boolean);for(let i=0;i<s.length;i+=1){let o=s[i];if((o==="**"||o==="*")&&i>0){let a=s[i-1];a&&!a.includes("*")&&!a.includes("{")&&!a.includes("}")&&t.add(a)}}}return[...t]}function fs(e,t,n){if(Array.isArray(e.sliceFolders)&&e.sliceFolders.length>0)return e.sliceFolders.filter(s=>typeof s=="string"&&s.length>0);let r=(n??[]).find(s=>s.name===t);return us(r?.patterns)}function ms(e){return!e.fromPath||!e.toPath||e.folderCount<=0||!e.fromSlice||!e.toSlice?!0:e.fromSlice!==e.toSlice}function ee(e,t,n,r){for(let s of e??[])if(!(s.from!==t||s.to!==n)&&s.allowed===!1){if(s.peerIsolation){let i=r?.fromPath,o=r?.toPath,a=fs(s,t,r?.layers),d=i&&o?wn(i,a):void 0,u=i&&o?wn(o,a):void 0;if(ms({fromPath:i,toPath:o,folderCount:a.length,fromSlice:d,toSlice:u}))return s;continue}if(t!==n)return s}}function he(e,t){return t&&e.isStringLiteralLike(t)?t.text:void 0}function Fn(e,t){return e.getLineAndCharacterOfPosition(t.getStart(e)).line+1}function Mn(e,t){if(e.isImportDeclaration(t)){let r=t.importClause;if(!r)return!1;if(r.isTypeOnly)return!0;let s=r.namedBindings;return!!(s&&e.isNamedImports(s)&&s.elements.length>0&&s.elements.every(i=>i.isTypeOnly))}if(t.isTypeOnly)return!0;let n=t.exportClause;return!!(n&&e.isNamedExports(n)&&n.elements.length>0&&n.elements.every(r=>r.isTypeOnly))}function Dn(e,t){let n={noLib:!0,noResolve:!0,target:e.ScriptTarget.Latest},r=e.createCompilerHost(n,!0);return r.getSourceFile=s=>s===t.fileName?t:void 0,r.fileExists=s=>s===t.fileName,r.readFile=s=>s===t.fileName?t.text:void 0,e.createProgram([t.fileName],n,r).getTypeChecker()}function $t(e,t){try{return e.getSymbolAtLocation(t)}catch{return}}function Ft(e,t,n,r){let s=r.parent&&e.isShorthandPropertyAssignment(r.parent)&&r.parent.name===r,i;try{i=s?t.getShorthandAssignmentValueSymbol(r.parent):$t(t,r)}catch{i=void 0}return!!i?.declarations?.some(o=>o.getSourceFile().fileName===n.fileName)}function Ae(e,t){let n,r=[],s=(o,a,d,u=!1)=>r.push({specifier:d,kind:a,line:Fn(t,o),typeOnly:u,unresolved:d===void 0,node:o}),i=o=>{if(e.isImportDeclaration(o))s(o,"import",he(e,o.moduleSpecifier),Mn(e,o));else if(e.isExportDeclaration(o)&&o.moduleSpecifier)s(o,"export",he(e,o.moduleSpecifier),Mn(e,o));else if(e.isImportEqualsDeclaration(o)&&e.isExternalModuleReference(o.moduleReference))s(o,"require",he(e,o.moduleReference.expression),o.isTypeOnly===!0);else if(e.isCallExpression(o)){let a=o.expression.kind===e.SyntaxKind.ImportKeyword,u=e.isIdentifier(o.expression)&&o.expression.text==="require"&&!Ft(e,n??(n=Dn(e,t)),t,o.expression);(a||u)&&s(o,u?"require":"dynamic-import",he(e,o.arguments[0]))}e.forEachChild(o,i)};return i(t),r}function gs(e,t){let n=[],r=t;for(;e.isPropertyAccessExpression(r)||e.isElementAccessExpression(r);){if(e.isPropertyAccessExpression(r))n.unshift(r.name.text);else{let s=he(e,r.argumentExpression);if(s===void 0)return;n.unshift(s)}r=r.expression}if(e.isIdentifier(r))return n.unshift(r.text),{root:r,segments:n}}function ys(e,t){let n=t.parent;return e.isPropertyAccessExpression(n)||e.isElementAccessExpression(n)?!1:e.isExpressionNode(t)&&!e.isInTypeQuery(t)||e.isShorthandPropertyAssignment(n)&&n.name===t}function $n(e,t){let n=t[0]==="globalThis"?t.slice(1):t;for(let r=n.length;r>=1;r-=1){let s=n.slice(0,r).join(".");if(e.has(s))return s}}function Ie(e,t,n){if(n.length===0)return[];let r=new Set(n),s=Dn(e,t),i=new Map,o=new Set;for(let c of t.statements)if(e.isVariableStatement(c))for(let l of c.declarationList.declarations)e.isIdentifier(l.name)&&o.add(l.name.text);let a=c=>{let l=gs(e,c);if(!l)return;let p=$t(s,l.root),y=p?i.get(p):void 0;return y?[...y,...l.segments.slice(1)]:Ft(e,s,t,l.root)||o.has(l.root.text)?void 0:l.segments};for(let c of t.statements)if(e.isVariableStatement(c))for(let l of c.declarationList.declarations){if(!l.initializer||!e.isIdentifier(l.name))continue;let p=a(l.initializer),y=$t(s,l.name);!p||!y||i.set(y,p)}let d=[],u=new Set,g=(c,l)=>{let p=Fn(t,l),y=`${c}:${l.getStart(t)}`;u.has(y)||(u.add(y),d.push({name:c,line:p,node:l}))},m=c=>{let l=c.parent&&(e.isPropertyAccessExpression(c.parent)||e.isElementAccessExpression(c.parent))&&c.parent.expression===c;if((e.isPropertyAccessExpression(c)||e.isElementAccessExpression(c))&&!l){let p=a(c),y=p?$n(r,p):void 0;y&&g(y,c)}else e.isIdentifier(c)&&r.has(c.text)&&ys(e,c)&&!Ft(e,s,t,c)&&g(c.text,c);if(e.isVariableDeclaration(c)&&e.isObjectBindingPattern(c.name)&&c.initializer){let p=a(c.initializer);if(p)for(let y of c.name.elements){if(!e.isIdentifier(y.name))continue;let I=y.propertyName?he(e,y.propertyName)??y.propertyName.text:y.name.text,R=$n(r,[...p,I]);R&&g(R,c.initializer)}}e.forEachChild(c,m)};return m(t),d}function Dt(e,t,n){let r=[];for(let s of n?.dependencies??Ae(e,t)){if(s.typeOnly||!s.specifier)continue;let i=Le(s.specifier);i&&r.push({capability:i,symbol:s.specifier,line:s.line,source:"import-based"})}for(let s of n?.ambientUses??Ie(e,t,wt)){let i=Je(s.name);i&&r.push({capability:i,symbol:s.name,line:s.line,source:"ambient-global"})}return r.sort((s,i)=>s.line-i.line||s.capability.localeCompare(i.capability)||s.symbol.localeCompare(i.symbol))}var Ht={RAW_EVENT_PUBLISH:"Publish through a registered intent creator; raw event objects or intent strings bypass Ark contracts and tooling.",PUBLISH_MISSING_SOURCE:"Strict Ark publish calls must include metadata.source."},Vt=Object.freeze([{layer:"DomainModel",prefixes:["Domain."]},{layer:"ApplicationOrchestration",prefixes:["Application."]},{layer:"PersistenceAdapters",prefixes:["Adapter.Persistence.","Adapter.Repository."]},{layer:"IntegrationAdapters",prefixes:["Adapter.Integration.","Adapter.External."]},{layer:"WorkflowSagaEngine",prefixes:["Workflow."]},{layer:"BackgroundJobsScheduling",prefixes:["Job."]},{layer:"PresentationAdapters",prefixes:["Presentation.","Adapter.Presentation.","Adapter.Api."]},{layer:"ReportingReadModels",prefixes:["Reporting."]},{layer:"ExtensibilityMetadata",prefixes:["Metadata."]},{layer:"SecurityAuditObservability",prefixes:["Security.","Audit.","Observability."]},{layer:"Kernel",prefixes:["Kernel."]}]);function jt(e,t){return t.flatMap((r,s)=>(r.prefixes??r.intentPrefixes??[]).map(i=>({layer:r.name,layerIndex:s,prefix:i.endsWith(".")?i:`${i}.`}))).filter(({prefix:r})=>e.startsWith(r)).sort((r,s)=>s.prefix.length-r.prefix.length||r.layerIndex-s.layerIndex)[0]?.layer}function ce(e){return/^(Domain|Application|Adapter|Workflow|Job|Presentation|Reporting|Metadata|Security|Audit|Observability|Kernel)\.[A-Za-z0-9_.]+$/.test(e)}function we(e){if(!e.publishCall)return[];let t=[];return(e.rawIntentName!==void 0&&ce(e.rawIntentName)||e.objectHasIntent)&&t.push({ruleId:"RAW_EVENT_PUBLISH",message:Ht.RAW_EVENT_PUBLISH}),e.arkPublishCandidate&&!e.hasSource&&t.push({ruleId:"PUBLISH_MISSING_SOURCE",message:Ht.PUBLISH_MISSING_SOURCE}),t}function w(e,t,n){return{ruleId:e,code:e,message:t,...n}}function be(e,t){return e.slice(0,t).split(`
|
|
1
|
+
var ts="4.6.3";var ns="1.5",kn="docs/diagnostics.md";function v(e){return typeof e=="string"&&e.length>0?e:void 0}function Cn(e,t){return Number.isInteger(e)&&Number(e)>0?Number(e):t}function Ot(e){let t=typeof e.ruleId=="string"?e.ruleId:typeof e.code=="string"?e.code:void 0,n=typeof e.file=="string"?e.file:void 0,r=typeof e.fromLayer=="string"?e.fromLayer:void 0,s=typeof e.toLayer=="string"?e.toLayer:void 0,i=typeof e.target=="string"?e.target:void 0;return[t,n,r??"",s??"",i??""].join("|")}function _t(e){let t=new Map;return e.map(n=>{let r=Ot(n),s=(t.get(r)??0)+1;return t.set(r,s),s===1?r:`${r}#${s}`})}function _n(e){let t=2166136261;for(let n=0;n<e.length;n+=1)t^=e.charCodeAt(n),t=Math.imul(t,16777619);return`fnv1a-${(t>>>0).toString(16).padStart(8,"0")}`}function xn(e){return`${kn}#${e}`}function rs(e,t,n){if(e==="LAYER_IMPORT_VIOLATION")return t.typeOnly||n.targetTypeOnlyExports===!0||n.namedBindingsTypeOnly===!0?"Move the referenced type to a mutually allowed layer, use `import type`, then preflight again.":n.peerIsolation===!0?"Extract the shared dependency to a shared layer, test at the public interface, then preflight again.":`Define a port in ${t.fromLayer??"the source layer"}, inject the ${t.toLayer??"outer-layer"} implementation, test at the public interface, then preflight again.`;if(e==="FORBIDDEN_GLOBAL")return`Inject ${t.target??"the capability"} through a port, test at the public interface, then preflight again.`;if(e==="CAPABILITY_VIOLATION")return`Define a ${v(n.capability)??"capability"} port in ${t.fromLayer??"the walled layer"}, bind the implementation outside it, test at the public interface, then preflight again.`;if(e==="CIRCULAR_DEPENDENCY")return"Extract the shared dependency into a third module, test at the public interface, then preflight again.";if(e==="RAW_EVENT_PUBLISH")return"Publish through a registered intent creator, then run Ark again.";if(e==="PUBLISH_MISSING_SOURCE")return"Add metadata.source to the publish call, then run Ark again.";if(e==="ARKRULE_STRUCTURE"||e==="ARKRULE_INVARIANT"||e==="INVARIANT_UNCOVERED"||e.startsWith("ARKRULE_")){let r=t.arkruleSource??"arkrules/<Layer>.json";return`Fix the structure or invariant for ${t.arkruleId??"the ArkRule"} (declared in ${r}), then preflight again. Do not demote the rule without a hash-bound policy acknowledgement.`}return`Resolve ${e} without weakening ark.config.json, then run Ark again.`}function xt(e,t="error",n){let r=v(e.ruleId)??v(e.code)??"ARK_UNKNOWN",s=e.severity==="warning"||e.failsStrict===!1||e.typeOnly===!0&&e.peerIsolation!==!0?"warning":t,i={...v(e.target)?{target:v(e.target)}:{},...v(e.fromLayer)?{fromLayer:v(e.fromLayer)}:{},...v(e.toLayer)?{toLayer:v(e.toLayer)}:{},...typeof e.typeOnly=="boolean"?{typeOnly:e.typeOnly}:{},...typeof e.targetTypeOnlyExports=="boolean"?{targetTypeOnlyExports:e.targetTypeOnlyExports}:{},...typeof e.sourcePureTypeModule=="boolean"?{sourcePureTypeModule:e.sourcePureTypeModule}:{},...typeof e.namedBindingsTypeOnly=="boolean"?{namedBindingsTypeOnly:e.namedBindingsTypeOnly}:{},...typeof e.portProofEligible=="boolean"?{portProofEligible:e.portProofEligible}:{},...typeof e.peerIsolation=="boolean"?{peerIsolation:e.peerIsolation}:{},...v(e.capability)?{capability:v(e.capability)}:{},...v(e.edgeKind)?{edgeKind:v(e.edgeKind)}:{},...v(e.arkruleId)?{arkruleId:v(e.arkruleId)}:{},...v(e.arkruleSource)?{arkruleSource:v(e.arkruleSource)}:{}},o=n??Ot(e),a=_n(o);return{ruleId:r,severity:s,message:v(e.message)??r,location:{file:v(e.file)??"<unknown>",line:Cn(e.line,1),column:Cn(e.column,1)},evidence:i,nextAction:v(e.nextAction)??rs(r,i,e),findingRef:a,targetKey:o,docsCodePath:xn(r)}}function ss(e){let t=e.completeness??"complete",n=e.mode??"lexical-compatibility";if(t==="complete"&&(e.completenessReasons?.length??0)>0)throw new Error("completenessReasons must be empty when completeness is complete.");let r=t==="complete"?[]:e.completenessReasons&&e.completenessReasons.length>0?e.completenessReasons.map(m=>({code:v(m.code)??"ANALYSIS_EVIDENCE_INCOMPLETE",message:v(m.message)??`Analysis ${t}: required evidence is incomplete.`,...v(m.file)?{file:v(m.file)}:{}})):[{code:t==="unavailable"?"ANALYSIS_UNAVAILABLE":"ANALYSIS_EVIDENCE_INCOMPLETE",message:`Analysis ${t}: required evidence is incomplete.`}],s={...v(e.policyHash)?{policyHash:v(e.policyHash)}:{},...v(e.resolverIdentity)?{resolverIdentity:v(e.resolverIdentity)}:{},...v(e.factsHash)?{factsHash:v(e.factsHash)}:{},...v(e.candidateTreeHash)?{candidateTreeHash:v(e.candidateTreeHash)}:{}};if(n==="resolved-candidate-facts"&&t!=="unavailable"){for(let m of["policyHash","resolverIdentity","factsHash","candidateTreeHash"])if(!s[m])throw new Error(`${m} is required for resolved ${t} adapter evidence.`)}let i=e.violations??[],o=e.warnings??[],a=_t(i),d=_t(o),u=[...i.map((m,c)=>xt(m,"error",a[c])),...o.map((m,c)=>xt(m,"warning",d[c]))],g={schemaVersion:"1.5",completenessReasons:r,diagnostics:u};if(n==="resolved-candidate-facts"){if(t==="unavailable")return{...g,mode:n,valid:!1,completeness:t,...s};let m={policyHash:s.policyHash,resolverIdentity:s.resolverIdentity,factsHash:s.factsHash,candidateTreeHash:s.candidateTreeHash};return t==="complete"?{...g,mode:n,valid:e.valid,completeness:t,...m}:{...g,mode:n,valid:!1,completeness:t,...m}}return t==="complete"?{...g,mode:n,valid:e.valid,completeness:t,...s}:{...g,mode:n,valid:!1,completeness:t,...s}}var is={$schema:"https://json-schema.org/draft/2020-12/schema",$id:"https://unpkg.com/arkgate@3/schemas/ark.analysis-result.schema.json",title:"ArkGate analysis result",type:"object",additionalProperties:!1,required:["schemaVersion","mode","valid","completeness","completenessReasons","diagnostics"],allOf:[{if:{properties:{completeness:{enum:["partial","unavailable"]}},required:["completeness"]},then:{properties:{valid:{const:!1}}}},{if:{properties:{mode:{const:"resolved-candidate-facts"},completeness:{enum:["complete","partial"]}},required:["mode","completeness"]},then:{required:["policyHash","resolverIdentity","factsHash","candidateTreeHash"]}},{if:{properties:{completeness:{const:"complete"}},required:["completeness"]},then:{properties:{completenessReasons:{maxItems:0}}},else:{properties:{completenessReasons:{minItems:1}}}}],properties:{schemaVersion:{const:"1.5"},mode:{enum:["lexical-compatibility","resolved-candidate-facts"]},valid:{type:"boolean"},completeness:{enum:["complete","partial","unavailable"]},completenessReasons:{type:"array",items:{type:"object",additionalProperties:!1,required:["code","message"],properties:{code:{type:"string",minLength:1},message:{type:"string",minLength:1},file:{type:"string",minLength:1}}}},policyHash:{type:"string",minLength:1},resolverIdentity:{type:"string",minLength:1},factsHash:{type:"string",minLength:1},candidateTreeHash:{type:"string",minLength:1},diagnostics:{type:"array",items:{type:"object",additionalProperties:!1,required:["ruleId","severity","message","location","evidence"],properties:{ruleId:{type:"string",minLength:1},severity:{enum:["error","warning"]},message:{type:"string",minLength:1},location:{type:"object",additionalProperties:!1,required:["file","line","column"],properties:{file:{type:"string",minLength:1},line:{type:"integer",minimum:1},column:{type:"integer",minimum:1}}},evidence:{type:"object",additionalProperties:!1,properties:{target:{type:"string"},fromLayer:{type:"string"},toLayer:{type:"string"},typeOnly:{type:"boolean"},targetTypeOnlyExports:{type:"boolean"},sourcePureTypeModule:{type:"boolean"},namedBindingsTypeOnly:{type:"boolean"},portProofEligible:{type:"boolean"},peerIsolation:{type:"boolean"},capability:{type:"string",minLength:1},edgeKind:{type:"string",minLength:1},arkruleId:{type:"string",minLength:1},arkruleSource:{type:"string",minLength:1}}},nextAction:{type:"string",minLength:1},findingRef:{type:"string",minLength:1,pattern:"^fnv1a-[0-9a-f]{8}$"},targetKey:{type:"string",minLength:1},docsCodePath:{type:"string",minLength:1}}}}}};var os="1.0",On="https://unpkg.com/arkgate@4/schemas/ark.project-identity.schema.json",We="^sha256:[a-f0-9]{64}$",Tn={type:"object",additionalProperties:!1,properties:{expectedRoot:{type:"string",minLength:1,description:"Absolute expected workspace/project directory. The initial authoritative handshake requires the exact project root; descendant calls also require expectedProjectId."},expectedProjectId:{type:"string",pattern:We,description:"Project id previously returned by ark_identity or ark_manifest."}}},Pn={type:"object",additionalProperties:!1,required:["status","authoritative"],properties:{status:{enum:["matched","unverified","mismatch"]},authoritative:{type:"boolean"},expectedRoot:{type:"string",minLength:1},expectedProjectId:{type:"string",pattern:We},code:{enum:["PROJECT_ROOT_MISMATCH","PROJECT_ID_MISMATCH","INVALID_PROJECT_EXPECTATION"]},message:{type:"string",minLength:1}}},as={$schema:"https://json-schema.org/draft/2020-12/schema",$id:On,title:"ArkGate MCP project identity",description:"Stable project binding plus separate runtime and architecture-contract evidence.",type:"object",additionalProperties:!1,required:["schemaVersion","projectId","resolvedRoot","resolvedConfigPath","arkgateVersion","contractHash","contractSource","runtimeId","processStartedAt"],properties:{schemaVersion:{const:"1.0"},projectId:{type:"string",pattern:We},resolvedRoot:{type:"string",minLength:1},resolvedConfigPath:{type:"string",minLength:1},arkgateVersion:{type:"string",minLength:1},contractHash:{type:"string",pattern:We},contractSource:{enum:["project","default-profile","manifest"]},runtimeId:{type:"string",minLength:1},processStartedAt:{type:"string",format:"date-time"}},$defs:{expectation:Tn,binding:Pn}};function ls(e,t,n){if(!e||!t)throw new Error("Project identity requires resolvedRoot and resolvedConfigPath.");let r=n(JSON.stringify({resolvedRoot:e,resolvedConfigPath:t})).toLowerCase();if(!/^[a-f0-9]{64}$/.test(r))throw new Error("Project identity hash adapter must return 64 hexadecimal SHA-256 characters.");return`sha256:${r}`}function cs(e){return{schemaVersion:"1.0",...e}}var Pt=Object.freeze(["network","filesystem","clock","randomness","environment","process","persistence"]),Nt=Object.freeze({fetch:"network",XMLHttpRequest:"network",Date:"clock","Date.now":"clock","Math.random":"randomness","process.env":"environment",process:"process"}),wt=Object.freeze(Object.keys(Nt).sort()),Tt=Object.freeze({fs:"filesystem","node:fs":"filesystem","fs/promises":"filesystem","node:fs/promises":"filesystem","fs-extra":"filesystem","graceful-fs":"filesystem",memfs:"filesystem",chokidar:"filesystem",http:"network",https:"network",http2:"network",net:"network",tls:"network",dgram:"network",dns:"network","node:http":"network","node:https":"network","node:http2":"network","node:net":"network","node:tls":"network","node:dgram":"network","node:dns":"network",axios:"network",undici:"network","node-fetch":"network",got:"network",ky:"network",superagent:"network",ws:"network",process:"process","node:process":"process",child_process:"process","node:child_process":"process","@prisma/client":"persistence",prisma:"persistence",pg:"persistence",mysql:"persistence",mysql2:"persistence",mongodb:"persistence",mongoose:"persistence",sqlite3:"persistence","better-sqlite3":"persistence",redis:"persistence",ioredis:"persistence",typeorm:"persistence",knex:"persistence","drizzle-orm":"persistence",sequelize:"persistence",kysely:"persistence","@supabase/supabase-js":"persistence"}),Lt=Object.freeze({process:Object.freeze(["process","node:process"])});function Le(e){if(!e||e.startsWith(".")||e.startsWith("/"))return null;let t=Tt[e];if(t)return t;let n=e.indexOf("/");if(n<0)return null;let r=e.slice(0,n),s=Tt[r];if(s)return s;let i=e.indexOf("/",n+1);return i<0?null:Tt[e.slice(0,i)]??null}function se(e,t){for(let n of t)if(Lt[n]?.includes(e))return n;return null}function Je(e){let t=e.split(".");for(let n=t.length;n>=1;n-=1){let r=t.slice(0,n).join("."),s=Nt[r];if(s)return s}return null}function ye(e){if(e?.pure===!0)return[...Pt].sort();let n=(e?.capabilities?.deny??[]).filter(r=>Pt.includes(r));return[...new Set(n)].sort()}function Ne(e,t){if(t.length===0)return!1;let n=new Set(t),r=e.split(".");for(let s=r.length;s>=1;s-=1)if(n.has(r.slice(0,s).join(".")))return!0;return!1}function Ze(e){let t=new Set,n=new Set,r=Object.keys(Nt);for(let s of e?.forbiddenGlobals??[]){let i=r.filter(o=>o===s||o.startsWith(`${s}.`));if(i.length===0)n.add(s);else for(let o of i)t.add(`ambient:${o}`);for(let o of Lt[s]??[])t.add(`import-exact:${o}`)}for(let s of ye(e)){if(t.add(`import:${s}`),s==="process")for(let i of Lt.process)t.add(`import-exact:${i}`);for(let i of r)Je(i)===s&&t.add(`ambient:${i}`)}return{atoms:[...t].sort(),rawGlobals:[...n].sort()}}var Ln=new Map;function Nn(e){return/[.*+?^${}()|[\]\\]/.test(e)?`\\${e}`:e}function Xe(e){let t="";for(let n=0;n<e.length;n+=1){let r=e[n];if(r==="\\"&&n+1<e.length){let s=e[n+1];if("*?{}[],".includes(s)||s==="\\"){t+="\\"+s,n+=1;continue}t+="/";continue}t+=r}return t}function ds(e){let t=0;for(let n=0;n<e.length;n+=1){let r=e[n];if(r==="\\"){n+=1;continue}if(r==="{")t+=1;else if(r==="}"&&(t-=1,t<0))return!1}return t===0}function le(e){let t=Ln.get(e);if(t)return t;let n=Xe(e),r=ds(n),s="",i=0;for(let a=0;a<n.length;a+=1){let d=n[a];d==="\\"&&a+1<n.length?(s+=Nn(n[a+1]),a+=1):d==="*"?n[a+1]==="*"?n[a+2]==="/"?(s+="(?:.*/)?",a+=2):(s+=".*",a+=1):s+="[^/]*":d==="?"?s+="[^/]":d==="{"&&r?(s+="(?:",i+=1):d==="}"&&r&&i>0?(s+=")",i-=1):d===","&&r&&i>0?s+="|":s+=Nn(d)}let o=new RegExp(`^${s}$`);return Ln.set(e,o),o}function ps(e){return Xe(String(e)).split("/").filter(Boolean).filter(n=>n!=="**"&&n!=="*"&&!n.includes("*")&&!n.includes("?")&&!n.includes("{")&&!n.includes("["))}function Mt(e,t){let n=Xe(String(e)),r=ps(n),s=n.replace(/\*/g,"").length,i=r.length*1e4+s;if(t==null||t==="")return i;let o=String(t).split(/[/\\]/).filter(Boolean);if(r.length===0)return s;let a=0,d=-1;for(let u of r){let g=-1;for(let m=a;m<o.length;m+=1)if(o[m]===u){g=m;break}if(g<0)return i;d=g,a=g+1}return(d+1)*1e6+r.length*1e4+s}function Q(e,t){let n=String(e).split(/[/\\]/).join("/"),r,s=-1;for(let i of t??[])if(!(i.exclude??[]).some(o=>le(o).test(n))){for(let o of i.patterns??[])if(le(o).test(n)){let a=Mt(o,n);a>s&&(s=a,r=i.name)}}return r}function wn(e,t){if(!t?.length)return;let n=String(e).split(/[/\\]/).filter(Boolean),r=new Set(t.map(s=>String(s).toLowerCase()));for(let s=0;s<n.length-1;s+=1)if(r.has(n[s].toLowerCase()))return`${n[s].toLowerCase()}/${n[s+1].toLowerCase()}`}function us(e){let t=new Set;for(let n of e??[]){let s=Xe(String(n)).split("/").filter(Boolean);for(let i=0;i<s.length;i+=1){let o=s[i];if((o==="**"||o==="*")&&i>0){let a=s[i-1];a&&!a.includes("*")&&!a.includes("{")&&!a.includes("}")&&t.add(a)}}}return[...t]}function fs(e,t,n){if(Array.isArray(e.sliceFolders)&&e.sliceFolders.length>0)return e.sliceFolders.filter(s=>typeof s=="string"&&s.length>0);let r=(n??[]).find(s=>s.name===t);return us(r?.patterns)}function ms(e){return!e.fromPath||!e.toPath||e.folderCount<=0||!e.fromSlice||!e.toSlice?!0:e.fromSlice!==e.toSlice}function ee(e,t,n,r){for(let s of e??[])if(!(s.from!==t||s.to!==n)&&s.allowed===!1){if(s.peerIsolation){let i=r?.fromPath,o=r?.toPath,a=fs(s,t,r?.layers),d=i&&o?wn(i,a):void 0,u=i&&o?wn(o,a):void 0;if(ms({fromPath:i,toPath:o,folderCount:a.length,fromSlice:d,toSlice:u}))return s;continue}if(t!==n)return s}}function he(e,t){return t&&e.isStringLiteralLike(t)?t.text:void 0}function Fn(e,t){return e.getLineAndCharacterOfPosition(t.getStart(e)).line+1}function Mn(e,t){if(e.isImportDeclaration(t)){let r=t.importClause;if(!r)return!1;if(r.isTypeOnly)return!0;let s=r.namedBindings;return!!(s&&e.isNamedImports(s)&&s.elements.length>0&&s.elements.every(i=>i.isTypeOnly))}if(t.isTypeOnly)return!0;let n=t.exportClause;return!!(n&&e.isNamedExports(n)&&n.elements.length>0&&n.elements.every(r=>r.isTypeOnly))}function Dn(e,t){let n={noLib:!0,noResolve:!0,target:e.ScriptTarget.Latest},r=e.createCompilerHost(n,!0);return r.getSourceFile=s=>s===t.fileName?t:void 0,r.fileExists=s=>s===t.fileName,r.readFile=s=>s===t.fileName?t.text:void 0,e.createProgram([t.fileName],n,r).getTypeChecker()}function $t(e,t){try{return e.getSymbolAtLocation(t)}catch{return}}function Ft(e,t,n,r){let s=r.parent&&e.isShorthandPropertyAssignment(r.parent)&&r.parent.name===r,i;try{i=s?t.getShorthandAssignmentValueSymbol(r.parent):$t(t,r)}catch{i=void 0}return!!i?.declarations?.some(o=>o.getSourceFile().fileName===n.fileName)}function Ae(e,t){let n,r=[],s=(o,a,d,u=!1)=>r.push({specifier:d,kind:a,line:Fn(t,o),typeOnly:u,unresolved:d===void 0,node:o}),i=o=>{if(e.isImportDeclaration(o))s(o,"import",he(e,o.moduleSpecifier),Mn(e,o));else if(e.isExportDeclaration(o)&&o.moduleSpecifier)s(o,"export",he(e,o.moduleSpecifier),Mn(e,o));else if(e.isImportEqualsDeclaration(o)&&e.isExternalModuleReference(o.moduleReference))s(o,"require",he(e,o.moduleReference.expression),o.isTypeOnly===!0);else if(e.isCallExpression(o)){let a=o.expression.kind===e.SyntaxKind.ImportKeyword,u=e.isIdentifier(o.expression)&&o.expression.text==="require"&&!Ft(e,n??(n=Dn(e,t)),t,o.expression);(a||u)&&s(o,u?"require":"dynamic-import",he(e,o.arguments[0]))}e.forEachChild(o,i)};return i(t),r}function gs(e,t){let n=[],r=t;for(;e.isPropertyAccessExpression(r)||e.isElementAccessExpression(r);){if(e.isPropertyAccessExpression(r))n.unshift(r.name.text);else{let s=he(e,r.argumentExpression);if(s===void 0)return;n.unshift(s)}r=r.expression}if(e.isIdentifier(r))return n.unshift(r.text),{root:r,segments:n}}function ys(e,t){let n=t.parent;return e.isPropertyAccessExpression(n)||e.isElementAccessExpression(n)?!1:e.isExpressionNode(t)&&!e.isInTypeQuery(t)||e.isShorthandPropertyAssignment(n)&&n.name===t}function $n(e,t){let n=t[0]==="globalThis"?t.slice(1):t;for(let r=n.length;r>=1;r-=1){let s=n.slice(0,r).join(".");if(e.has(s))return s}}function Ie(e,t,n){if(n.length===0)return[];let r=new Set(n),s=Dn(e,t),i=new Map,o=new Set;for(let c of t.statements)if(e.isVariableStatement(c))for(let l of c.declarationList.declarations)e.isIdentifier(l.name)&&o.add(l.name.text);let a=c=>{let l=gs(e,c);if(!l)return;let p=$t(s,l.root),y=p?i.get(p):void 0;return y?[...y,...l.segments.slice(1)]:Ft(e,s,t,l.root)||o.has(l.root.text)?void 0:l.segments};for(let c of t.statements)if(e.isVariableStatement(c))for(let l of c.declarationList.declarations){if(!l.initializer||!e.isIdentifier(l.name))continue;let p=a(l.initializer),y=$t(s,l.name);!p||!y||i.set(y,p)}let d=[],u=new Set,g=(c,l)=>{let p=Fn(t,l),y=`${c}:${l.getStart(t)}`;u.has(y)||(u.add(y),d.push({name:c,line:p,node:l}))},m=c=>{let l=c.parent&&(e.isPropertyAccessExpression(c.parent)||e.isElementAccessExpression(c.parent))&&c.parent.expression===c;if((e.isPropertyAccessExpression(c)||e.isElementAccessExpression(c))&&!l){let p=a(c),y=p?$n(r,p):void 0;y&&g(y,c)}else e.isIdentifier(c)&&r.has(c.text)&&ys(e,c)&&!Ft(e,s,t,c)&&g(c.text,c);if(e.isVariableDeclaration(c)&&e.isObjectBindingPattern(c.name)&&c.initializer){let p=a(c.initializer);if(p)for(let y of c.name.elements){if(!e.isIdentifier(y.name))continue;let I=y.propertyName?he(e,y.propertyName)??y.propertyName.text:y.name.text,R=$n(r,[...p,I]);R&&g(R,c.initializer)}}e.forEachChild(c,m)};return m(t),d}function Dt(e,t,n){let r=[];for(let s of n?.dependencies??Ae(e,t)){if(s.typeOnly||!s.specifier)continue;let i=Le(s.specifier);i&&r.push({capability:i,symbol:s.specifier,line:s.line,source:"import-based"})}for(let s of n?.ambientUses??Ie(e,t,wt)){let i=Je(s.name);i&&r.push({capability:i,symbol:s.name,line:s.line,source:"ambient-global"})}return r.sort((s,i)=>s.line-i.line||s.capability.localeCompare(i.capability)||s.symbol.localeCompare(i.symbol))}var Ht={RAW_EVENT_PUBLISH:"Publish through a registered intent creator; raw event objects or intent strings bypass Ark contracts and tooling.",PUBLISH_MISSING_SOURCE:"Strict Ark publish calls must include metadata.source."},Vt=Object.freeze([{layer:"DomainModel",prefixes:["Domain."]},{layer:"ApplicationOrchestration",prefixes:["Application."]},{layer:"PersistenceAdapters",prefixes:["Adapter.Persistence.","Adapter.Repository."]},{layer:"IntegrationAdapters",prefixes:["Adapter.Integration.","Adapter.External."]},{layer:"WorkflowSagaEngine",prefixes:["Workflow."]},{layer:"BackgroundJobsScheduling",prefixes:["Job."]},{layer:"PresentationAdapters",prefixes:["Presentation.","Adapter.Presentation.","Adapter.Api."]},{layer:"ReportingReadModels",prefixes:["Reporting."]},{layer:"ExtensibilityMetadata",prefixes:["Metadata."]},{layer:"SecurityAuditObservability",prefixes:["Security.","Audit.","Observability."]},{layer:"Kernel",prefixes:["Kernel."]}]);function jt(e,t){return t.flatMap((r,s)=>(r.prefixes??r.intentPrefixes??[]).map(i=>({layer:r.name,layerIndex:s,prefix:i.endsWith(".")?i:`${i}.`}))).filter(({prefix:r})=>e.startsWith(r)).sort((r,s)=>s.prefix.length-r.prefix.length||r.layerIndex-s.layerIndex)[0]?.layer}function ce(e){return/^(Domain|Application|Adapter|Workflow|Job|Presentation|Reporting|Metadata|Security|Audit|Observability|Kernel)\.[A-Za-z0-9_.]+$/.test(e)}function we(e){if(!e.publishCall)return[];let t=[];return(e.rawIntentName!==void 0&&ce(e.rawIntentName)||e.objectHasIntent)&&t.push({ruleId:"RAW_EVENT_PUBLISH",message:Ht.RAW_EVENT_PUBLISH}),e.arkPublishCandidate&&!e.hasSource&&t.push({ruleId:"PUBLISH_MISSING_SOURCE",message:Ht.PUBLISH_MISSING_SOURCE}),t}function w(e,t,n){return{ruleId:e,code:e,message:t,...n}}function be(e,t){return e.slice(0,t).split(`
|
|
2
2
|
`).length}function hs(e){let t=[],n=/['"`]([A-Za-z][A-Za-z0-9_.]*)['"`]/g,r;for(;(r=n.exec(e))!==null;)t.push({value:r[1],index:r.index});return t}function As(e){let t=[],n=[{kind:"import",re:/\bimport\s+(?:type\s+)?(?:[^'"]*?\s+from\s*)?['"]([^'"]+)['"]/g},{kind:"export",re:/\bexport\s+(?:type\s+)?[^'"]*?\s+from\s*['"]([^'"]+)['"]/g},{kind:"dynamic-import",re:/\bimport\s*\(\s*['"]([^'"]+)['"]\s*\)/g},{kind:"require",re:/\brequire\s*\(\s*['"]([^'"]+)['"]\s*\)/g}];for(let r of n){let s;for(;(s=r.re.exec(e))!==null;){let i=s.index+s[0].indexOf(s[1]),o=s[0],a=r.kind==="import"&&/\bimport\s+type\b/.test(o)||r.kind==="export"&&/\bexport\s+type\b/.test(o);t.push({value:s[1],index:i,kind:r.kind,typeOnly:a})}}return t.sort((r,s)=>r.index-s.index)}function Is(e,t){let n=e.createSourceFile("generated.ts",t,e.ScriptTarget.Latest,!0),r=[],s=i=>{e.isStringLiteralLike(i)&&r.push({value:i.text,index:i.getStart(n)}),e.forEachChild(i,s)};return s(n),r}function bs(e){let t=e.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean);return["adapter","adapters","infra","infrastructure","persistence","repository","repositories","integration","database","db"].some(n=>t.includes(n))}function Ss(e){let t=e.toLowerCase();return["sequelize","prisma","typeorm","mongoose","knex"].some(n=>t===n||t.startsWith(`${n}/`))}function Rs(e){let t=e.toLowerCase();return["adapter","infra","persistence","repository","repositories","integration","database"].some(n=>t.includes(n))}function $e(e,t){return t&&e.isStringLiteralLike(t)?t.text:void 0}function Es(e,t){if(t&&(e.isIdentifier(t)||e.isStringLiteralLike(t)))return t.text}function Hn(e,t,n){if(!(!t||!e.isObjectLiteralExpression(t)))return t.properties.find(r=>!e.isPropertyAssignment(r)&&!e.isShorthandPropertyAssignment(r)?!1:Es(e,r.name)===n)}function Fe(e,t,n){return Hn(e,t,n)!==void 0}function Me(e,t,n){let r=Hn(e,t,n);return r&&e.isPropertyAssignment(r)?r.initializer:void 0}function vs(e,t){let n=Me(e,t,"metadata");return Fe(e,n,"source")}function Vn(e,t){return t?e.isIdentifier(t)?/^[A-Z]/.test(t.text):e.isPropertyAccessExpression(t)?Vn(e,t.name):!1:!1}function Cs(e,t){if(!e.isCallExpression(t))return!1;let n=t.expression;return e.isPropertyAccessExpression(n)?n.name.text==="publish":e.isIdentifier(n)&&n.text==="publish"}function ks(e,t){if(!e.isCallExpression(t))return!1;let n=t.arguments[0],r=$e(e,n);return r!==void 0&&ce(r)||Fe(e,n,"intent")||Vn(e,n)}function _s(e,t){if(!e.isCallExpression(t))return!1;let[n,r,s]=t.arguments;return vs(e,n)||Fe(e,r,"source")||Fe(e,s,"source")}function xs(e,t){if(!e.isCallExpression(t))return;let[n,r,s]=t.arguments,i=Me(e,n,"metadata");return $e(e,Me(e,i,"source"))??$e(e,Me(e,r,"source"))??$e(e,Me(e,s,"source"))}function Os(e,t,n,r){let s=e.createSourceFile("generated.ts",t,e.ScriptTarget.Latest,!0),i=n,o=i?.filePath,a=i?.layer,d=[],u=m=>s.getLineAndCharacterOfPosition(m.getStart(s)).line+1,g=m=>{if(Cs(e,m)){let c=m.arguments[0],l=$e(e,c);for(let y of we({publishCall:!0,rawIntentName:l,objectHasIntent:Fe(e,c,"intent"),arkPublishCandidate:ks(e,m),hasSource:_s(e,m)}))d.push(w(y.ruleId,y.message,{line:u(m),filePath:o}));let p=xs(e,m);if(r&&a&&p&&ce(p)){let y=r.resolveLayer(p);y&&y!==a&&d.push(w("PUBLISH_SOURCE_LAYER_MISMATCH",`Publish source "${p}" resolves to ${y}, but the target file is classified as ${a}.`,{line:u(m),filePath:o,target:p,fromLayer:a,toLayer:y}))}}e.forEachChild(m,g)};return g(s),d}function jn(e={}){let t=new Set((e.intents||[]).map(i=>typeof i=="string"?i:i.name)),n=e.forbiddenPatterns||[],r=new Set(e.infrastructureLayers??[]),s=e.enforceIntentAllowlist??t.size>0;return{validate(i,o){let a=[],d=o,u=d?.filePath,g=d?.layer,m=e.typescript,c=m?m.createSourceFile(u??"generated.ts",i,m.ScriptTarget.Latest,!0):void 0,l=c?Ae(e.typescript,c):void 0,p=l?l.filter(f=>f.specifier!==void 0).map(f=>({value:f.specifier,index:f.node.getStart(c),kind:f.kind,typeOnly:f.typeOnly})):As(i),y=e.typescript?Is(e.typescript,i):hs(i);if(e.typescript&&!e.allowNonLiteralDynamicImport?.(u))for(let f of l?.filter(({unresolved:h})=>h)??[]){let h=f.kind==="require";a.push(w(h?"DYNAMIC_REQUIRE_NOT_ALLOWLISTED":"DYNAMIC_IMPORT_NOT_ALLOWLISTED",`Non-literal ${h?"require call":"dynamic import"} cannot be resolved statically; add the reviewed file to dynamicImportAllowlist.`,{line:f.line,filePath:u}))}let I=g!==void 0&&(r.has(g)||Rs(g)),R=g!==void 0?` If "${g}" is an infrastructure layer, mark it in ark.config.json with "mayImportInfrastructure": true (or name it with an infra token like Adapters/Persistence/Repository).`:"";for(let f of n)if(f instanceof RegExp){f.lastIndex=0;let h=f.exec(i);f.lastIndex=0,h&&a.push(w("FORBIDDEN_PATTERN",`Forbidden pattern matched: ${f}`,{line:h.index===void 0?void 0:be(i,h.index),filePath:u,suggestion:"Remove infrastructure imports from domain/application layers."+R}))}else i.includes(f)&&a.push(w("FORBIDDEN_SUBSTRING",`Forbidden substring: ${f}`,{line:be(i,i.indexOf(f)),filePath:u}));for(let f of p){let h=e.resolveImportTarget?.(f.value,u)??(e.resolveImportLayer?{layer:e.resolveImportLayer(f.value,u)}:void 0),S=typeof u=="string"?e.resolveImportTarget?.(u)??(e.resolveImportLayer?{layer:g,relPath:void 0}:void 0):void 0,k=h?.layer;if(k&&g){let N=ee(e.architectureProfile?.rules,g,k,{fromPath:S?.relPath,toPath:h?.relPath,layers:e.architectureLayers});if(N){if(f.typeOnly&&!N.peerIsolation)continue;let D=!!N.peerIsolation;a.push(w("LAYER_IMPORT_VIOLATION",N.message??(D?`Layer "${g}" must not import across slices into "${k}".`:`Layer "${g}" must not import "${k}".`),{line:be(i,f.index),source:f.value,target:f.value,filePath:u,fromLayer:g,toLayer:k,suggestion:D?"Extract shared code to a shared layer, or coordinate slices via events/ports \u2014 do not import across feature/context slices.":"Depend on a port/interface owned by an inner layer instead, or move this code to a layer allowed to make this import.",details:{importKind:f.kind,peerIsolation:D,...f.typeOnly?{typeOnly:!0}:{}}}));continue}continue}I||f.typeOnly||!bs(f.value)&&!Ss(f.value)||a.push(w("FORBIDDEN_IMPORT",`Forbidden ${f.kind} target: "${f.value}".`,{line:be(i,f.index),source:f.value,target:f.value,filePath:u,suggestion:"Route infrastructure access through an allowed adapter or port boundary."+R,details:{importKind:f.kind}}))}if(e.policies)for(let f of e.policies){let h=f.check({source:i,context:o});if(h!==!0)if(Array.isArray(h))for(let S of h)a.push(w("POLICY_VIOLATION",S.message,{filePath:u,suggestion:`Fix violation of policy "${f.name}".`}));else h===!1?a.push(w("POLICY_VIOLATION",`Policy ${f.name} failed on generated code`)):a.push(w("POLICY_VIOLATION",h.message))}if(s&&t.size>0)for(let f of y)ce(f.value)&&!t.has(f.value)&&a.push(w("UNKNOWN_INTENT",`Unknown intent reference: "${f.value}"`,{line:be(i,f.index),filePath:u,target:f.value,suggestion:`Register intent "${f.value}" via defineIntent() or remove the reference.`}));if(e.architectureProfile&&g)for(let f of y){if(!ce(f.value))continue;let h=e.architectureProfile.resolveLayer(f.value);if(!h)continue;let S=ee(e.architectureProfile.rules,g,h);S&&a.push(w("LAYER_REFERENCE_VIOLATION",S.message??`Layer "${g}" must not reference "${h}" through "${f.value}".`,{line:be(i,f.index),filePath:u,target:f.value,fromLayer:g,toLayer:h,suggestion:"Route the dependency through an allowed intent, port, or event.",details:{rule:S}}))}if(e.extensions)for(let f of e.extensions)try{let h=f.analyze(i,o);a.push(...h)}catch(h){a.push(w("EXTENSION_ERROR",`Extension "${f.name}" failed: ${h instanceof Error?h.message:String(h)}`))}if(e.typescript&&c&&g&&e.forbiddenGlobals?.[g]?.length)try{let f=e.forbiddenGlobals[g];a.push(...Ie(e.typescript,c,f).map(h=>w("FORBIDDEN_GLOBAL",`${g} must not use the ambient global "${h.name}".`,{line:h.line,filePath:u,target:h.name,fromLayer:g,suggestion:"Inject the capability through a port (e.g. a Clock, IdGenerator, or HttpPort) instead of reaching for the ambient global."})));for(let h of l??[]){if(h.typeOnly||!h.specifier)continue;let S=se(h.specifier,f);S&&a.push(w("FORBIDDEN_GLOBAL",`${g} must not use module "${h.specifier}" because it is the import form of forbidden global "${S}".`,{line:h.line,filePath:u,source:h.specifier,target:h.specifier,fromLayer:g,details:{importKind:h.kind,forbiddenGlobal:S},suggestion:"Inject the capability through a port instead of importing the ambient global module form."}))}}catch(f){a.push(w("AST_ANALYZER_ERROR",`TypeScript AST analyzer failed: ${f instanceof Error?f.message:String(f)}`))}if(e.typescript&&c&&g&&e.capabilityWalls?.[g]?.length)try{let f=new Set(e.capabilityWalls[g]),h=e.forbiddenGlobals?.[g]??[];for(let S of Dt(e.typescript,c))f.has(S.capability)&&(S.source==="ambient-global"&&Ne(S.symbol,h)||S.source==="import-based"&&se(S.symbol,h)||a.push(w("CAPABILITY_VIOLATION",S.source==="import-based"?`${g} denies the ${S.capability} capability; found import of "${S.symbol}".`:`${g} denies the ${S.capability} capability; found ambient "${S.symbol}".`,{line:S.line,filePath:u,target:S.symbol,capability:S.capability,fromLayer:g,suggestion:"Define a small port (ClockPort, HttpPort, StoragePort) and bind the implementation in an adapter layer."})))}catch(f){a.push(w("AST_ANALYZER_ERROR",`TypeScript AST analyzer failed: ${f instanceof Error?f.message:String(f)}`))}if(e.typescript)try{a.push(...Os(e.typescript,i,o,e.architectureProfile))}catch(f){a.push(w("AST_ANALYZER_ERROR",`TypeScript AST analyzer failed: ${f instanceof Error?f.message:String(f)}`))}return{mode:"lexical-compatibility",completeness:"partial",completenessReasons:["LEXICAL_EVIDENCE_INCOMPLETE"],valid:!1,lexicalValid:a.length===0,violations:a}}}}var Ts="1.1",et="https://unpkg.com/arkgate@2/schemas/ark.config.schema.json",Un=["DomainModel","ApplicationOrchestration","PersistenceAdapters","IntegrationAdapters","WorkflowSagaEngine","BackgroundJobsScheduling","PresentationAdapters","ReportingReadModels","ExtensibilityMetadata","SecurityAuditObservability","Kernel"],Ps=new Set(["PresentationAdapters->ApplicationOrchestration","ApplicationOrchestration->DomainModel","WorkflowSagaEngine->ApplicationOrchestration","WorkflowSagaEngine->DomainModel","BackgroundJobsScheduling->ApplicationOrchestration"]);function Ls(){let e=[];for(let t of Un)for(let n of Un)t===n||Ps.has(`${t}->${n}`)||e.push({from:t,to:n,allowed:!1});return e}var tt=Ls(),Ut=[{from:"unversioned",to:"1.0"},{from:"1.0",to:"1.1"}],te={type:"array",items:{type:"string",minLength:1},uniqueItems:!0},Gt={$schema:"https://json-schema.org/draft/2020-12/schema",$id:et,title:"ArkGate architecture contract",description:"Versioned contract consumed identically by ArkGate CLI, MCP, and ESLint surfaces.",type:"object",additionalProperties:!1,required:["$schema","schemaVersion","include","layers","rules"],properties:{$schema:{type:"string",minLength:1,default:et,description:"Editor-facing URL or local path for this JSON Schema."},schemaVersion:{type:"string",const:"1.1",default:"1.1"},name:{type:"string",minLength:1},include:{...te,minItems:1,default:["src"]},exclude:{...te,default:[]},excludeGenerated:{type:"boolean",default:!0},frameworkOverlay:{type:"string",minLength:1},layers:{type:"array",default:[],items:{$ref:"#/$defs/layer"}},rules:{type:"array",default:tt,items:{$ref:"#/$defs/rule"}},cyclePolicy:{type:"string",enum:["strict","soft","framework-soft","off"],default:"strict"},dynamicImportAllowlist:{...te,default:[]},safety:{$ref:"#/$defs/safety",default:{maxTsSuppressions:0,maxAnyCasts:0,allowInMemory:!1,allowDisabledPeerIsolation:!1}},arkRules:{type:"object",additionalProperties:{type:"string",minLength:1},default:{}},stewards:{...te,default:[]}},$defs:{layer:{type:"object",additionalProperties:!1,required:["name","patterns"],properties:{name:{type:"string",minLength:1},patterns:{...te,minItems:1},exclude:te,intentPrefixes:te,description:{type:"string",minLength:1},forbiddenGlobals:te,capabilities:{type:"object",additionalProperties:!1,properties:{deny:{type:"array",uniqueItems:!0,items:{type:"string",enum:["network","filesystem","clock","randomness","environment","process","persistence"]}}}},pure:{type:"boolean"},mayImportInfrastructure:{type:"boolean"},optional:{type:"boolean"}}},rule:{type:"object",additionalProperties:!1,required:["from","to","allowed"],properties:{from:{type:"string",minLength:1},to:{type:"string",minLength:1},allowed:{type:"boolean"},message:{type:"string",minLength:1},peerIsolation:{type:"boolean"},sliceFolders:{...te,minItems:1}}},safety:{type:"object",additionalProperties:!1,properties:{maxTsSuppressions:{type:"integer",minimum:0,default:0},maxAnyCasts:{type:"integer",minimum:0,default:0},allowInMemory:{type:"boolean",default:!1},allowDisabledPeerIsolation:{type:"boolean",default:!1}}}}},ne=class extends Error{issues;source;constructor(t,n){super(`Invalid ArkGate config (${t}):
|
|
3
3
|
${n.map(r=>`- ${r.path}: ${r.message}`).join(`
|
|
4
4
|
`)}`),this.name="ArkConfigValidationError",this.source=t,this.issues=n}};function Gn(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Qe(e,t){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)?`${e}.${t}`:`${e}[${JSON.stringify(t)}]`}function Se(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function Ns(e,t){let n="#/$defs/";if(e.startsWith(n))return t.$defs[e.slice(n.length)]}function De(e,t,n,r,s){if(t.$ref){let i=Ns(t.$ref,r);if(!i){s.push({path:n,message:`schema reference ${t.$ref} cannot be resolved`});return}De(e,i,n,r,s);return}if(t.const!==void 0&&!Object.is(e,t.const)){s.push({path:n,message:`must equal ${JSON.stringify(t.const)}`});return}if(t.enum&&!t.enum.some(i=>Object.is(i,e))){s.push({path:n,message:`must be one of ${t.enum.map(String).join(", ")}`});return}if(t.type==="object"){if(!Gn(e)){s.push({path:n,message:`must be an object; received ${Se(e)}`});return}let i=t.properties??{};for(let o of t.required??[])e[o]===void 0&&s.push({path:Qe(n,o),message:"is required"});if(t.additionalProperties===!1)for(let o of Object.keys(e))o in i||s.push({path:Qe(n,o),message:"unknown field"});else if(t.additionalProperties!==void 0&&t.additionalProperties!==!0&&typeof t.additionalProperties=="object"){let o=t.additionalProperties;for(let a of Object.keys(e))a in i||De(e[a],o,Qe(n,a),r,s)}for(let[o,a]of Object.entries(i))e[o]!==void 0&&De(e[o],a,Qe(n,o),r,s);return}if(t.type==="array"){if(!Array.isArray(e)){s.push({path:n,message:`must be an array; received ${Se(e)}`});return}if(t.minItems!==void 0&&e.length<t.minItems&&s.push({path:n,message:`must contain at least ${t.minItems} item(s)`}),t.uniqueItems){let i=e.map(o=>JSON.stringify(o));new Set(i).size!==i.length&&s.push({path:n,message:"must not contain duplicate items"})}t.items&&e.forEach((i,o)=>De(i,t.items,`${n}[${o}]`,r,s));return}if(t.type==="string"){if(typeof e!="string"){s.push({path:n,message:`must be a string; received ${Se(e)}`});return}t.minLength!==void 0&&e.length<t.minLength&&s.push({path:n,message:`must contain at least ${t.minLength} character(s)`});return}if(t.type==="boolean"){typeof e!="boolean"&&s.push({path:n,message:`must be a boolean; received ${Se(e)}`});return}if(t.type==="integer"){if(!Number.isInteger(e)){s.push({path:n,message:`must be an integer; received ${Se(e)}`});return}t.minimum!==void 0&&e<t.minimum&&s.push({path:n,message:`must be at least ${t.minimum}`})}}function ws(e){return{...e,$schema:e.$schema===void 0?et:e.$schema,schemaVersion:e.schemaVersion===void 0?"1.1":e.schemaVersion,include:e.include===void 0?["src"]:e.include,layers:e.layers===void 0?[]:e.layers,rules:e.rules===void 0?tt.map(t=>({...t})):e.rules}}function Ms(){let e=new Set(["1.1"]);for(let t of Ut)t.from!=="unversioned"&&e.add(t.from),e.add(t.to);return e}function $s(e,t="ark.config.json"){if(!Gn(e))throw new ne(t,[{path:"$",message:`must be an object; received ${Se(e)}`}]);let n=Ms(),r=e.schemaVersion===void 0?"unversioned":typeof e.schemaVersion=="string"?e.schemaVersion:null;if(r===null)throw new ne(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(e.schemaVersion)}; expected 1.1`}]);if(r!=="unversioned"&&!n.has(r))throw new ne(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(r)}; expected 1.1`}]);let s=r,i={...e},o=0;for(;s!=="1.1"&&o<Ut.length+1;){o+=1;let d=Ut.find(u=>u.from===s);if(!d)throw new ne(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(s)}; expected 1.1`}]);s=d.to,i.schemaVersion=s}if(s!=="1.1")throw new ne(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(r)}; expected 1.1`}]);let a=r==="unversioned"?"unversioned":r==="1.0"?"1.0":null;return{candidate:ws(i),migratedFrom:a}}function nt(e,t="ark.config.json"){let{candidate:n,migratedFrom:r}=$s(e,t),s=[];if(De(n,Gt,"$",Gt,s),s.length>0)throw new ne(t,s);return{config:n,migratedFrom:r}}function Bt(e,t="ark.config.json"){let n;try{n=JSON.parse(e)}catch(r){throw new ne(t,[{path:"$",message:`invalid JSON: ${r instanceof Error?r.message:String(r)}`}])}return nt(n,t)}function Bn(e){let t={$schema:typeof e.$schema=="string"&&e.$schema.length>0?e.$schema:et,schemaVersion:"1.1"};for(let[n,r]of Object.entries(e))n!=="$schema"&&n!=="schemaVersion"&&(t[n]=r);return t}function Fs(e){return e.endsWith(".")?e:`${e}.`}function Ds(e,t){let n=e.prefixes.length?Math.max(...e.prefixes.map(s=>s.length)):0;return(t.prefixes.length?Math.max(...t.prefixes.map(s=>s.length)):0)-n}function st(e){let t=e.layers.map(s=>({...s,prefixes:s.prefixes.map(Fs)})),n=[...t].sort(Ds),r=[...e.rules??[]];return{name:e.name,layers:t,rules:r,resolveLayer(s){return t.find(i=>i.match?.(s))?.name??n.find(i=>i.prefixes.some(o=>s.startsWith(o)))?.name}}}function Kn(e,t={}){return st({name:t.name??e.name??"ark.config.json",layers:e.layers.map((n,r)=>({name:n.name,prefixes:n.intentPrefixes??[],description:n.description,order:r+1})),rules:e.rules??[]})}var Hs=[{name:"DomainModel",prefixes:["Domain"],description:"Rich domain model, business rules, and domain events.",order:1},{name:"ApplicationOrchestration",prefixes:["Application"],description:"Use cases and command orchestration.",order:2},{name:"PersistenceAdapters",prefixes:["Adapter.Persistence","Adapter.Repository"],description:"Database, repository, and storage adapters.",order:3},{name:"IntegrationAdapters",prefixes:["Adapter.Integration","Adapter.External"],description:"External systems, APIs, and integration adapters.",order:4},{name:"WorkflowSagaEngine",prefixes:["Workflow"],description:"Sagas, workflows, and long-running processes.",order:5},{name:"BackgroundJobsScheduling",prefixes:["Job"],description:"Background jobs, scheduled work, and async processors.",order:6},{name:"PresentationAdapters",prefixes:["Presentation","Adapter.Presentation","Adapter.Api"],description:"API, UI, controller, and presentation adapters.",order:7},{name:"ReportingReadModels",prefixes:["Reporting"],description:"Read models, projections, and reporting surfaces.",order:8},{name:"ExtensibilityMetadata",prefixes:["Metadata"],description:"Metadata, extensions, and schema contracts.",order:9},{name:"SecurityAuditObservability",prefixes:["Security","Audit","Observability"],description:"Security, audit, and observability concerns.",order:10},{name:"Kernel",prefixes:["Kernel"],description:"Ark-owned governance and kernel signals.",order:11}],rt=st({name:"Ark 11-layer Hexagonal Event-Driven Profile",layers:Hs,rules:tt.map(e=>({...e}))}),Vs={DomainModel:["domain"],ApplicationOrchestration:["application","app"],PersistenceAdapters:["adapters/persistence","adapters/repository","repositories","infra/persistence"],IntegrationAdapters:["adapters/integration","adapters/external","integrations"],WorkflowSagaEngine:["workflows","sagas"],BackgroundJobsScheduling:["jobs","schedules"],PresentationAdapters:["presentation","adapters/presentation","adapters/api"],ReportingReadModels:["reporting","read-models","projections"],ExtensibilityMetadata:["metadata","extensions"],SecurityAuditObservability:["security","audit","observability"],Kernel:["kernel"]};function zn(e={}){let t=e.rootDir??"src",n=e.optionalLayers??!0,r=t==="."?"":`${t}/`;return Bn({include:e.include??[t],layers:rt.layers.map(s=>({name:s.name,patterns:(Vs[s.name]??[s.name]).map(i=>`${r}${i}/**`),intentPrefixes:s.prefixes,optional:n})),rules:[...rt.rules]})}function M(e){let t=2166136261;for(let n=0;n<e.length;n+=1)t^=e.charCodeAt(n),t=Math.imul(t,16777619);return`fnv1a-${(t>>>0).toString(16).padStart(8,"0")}`}function T(e){if(e===null||typeof e!="object")return JSON.stringify(e);if(Array.isArray(e))return`[${e.map(T).join(",")}]`;let t=e;return`{${Object.keys(t).sort().map(n=>`${JSON.stringify(n)}:${T(t[n])}`).join(",")}}`}var de="1.1";var qn=["network","filesystem","clock","randomness","environment","process","persistence"];function re(e,t){let n=T(e),r=T(t);return n<r?-1:n>r?1:0}function Z(e){return[...new Set(e)].sort((t,n)=>t<n?-1:t>n?1:0)}function He(e){let t={schemaVersion:"1.1",include:Z(e.include??[]),exclude:Z(e.exclude??[]),excludeGenerated:e.excludeGenerated!==!1,dynamicImportAllowlist:Z(e.dynamicImportAllowlist??[]),layers:e.layers.map(n=>({name:n.name,patterns:Z(n.patterns??[]),exclude:Z(n.exclude??[]),forbiddenGlobals:Z(n.forbiddenGlobals??[]),intentPrefixes:Z(n.intentPrefixes??[]),capabilityDeny:Z(n.capabilities?.deny??[]),pure:n.pure===!0})).sort(re),safety:{maxTsSuppressions:e.safety?.maxTsSuppressions??0,maxAnyCasts:e.safety?.maxAnyCasts??0,allowInMemory:e.safety?.allowInMemory===!0,allowDisabledPeerIsolation:e.safety?.allowDisabledPeerIsolation===!0}};return M(T(t))}function js(e){let t=e.completenessReasons.map(c=>({code:c.code,message:c.message,...c.file?{file:c.file}:{}})).sort(re),n=e.files.map(c=>({...c,typeOnlyExportNames:Z(c.typeOnlyExportNames)})).sort((c,l)=>c.path<l.path?-1:c.path>l.path?1:0),r=e.dependencies.map(c=>({...c,...c.namedBindings?{namedBindings:Z(c.namedBindings)}:{}})).sort(re),s=e.capabilityUses.map(c=>({...c})).sort(re),i=e.ambientUses.map(c=>({...c})).sort(re),o=e.publishCalls.map(c=>({...c})).sort(re),a=e.intentReferences.map(c=>({...c})).sort(re),d=e.safetyUses.map(c=>({...c})).sort(re),u=(e.classShapes??[]).map(c=>({...c,mutatingMethods:[...c.mutatingMethods??[]].map(l=>({...l}))})).sort(re),g=e.files.map(({path:c,contentHash:l})=>({path:c,contentHash:l})).sort((c,l)=>c.path<l.path?-1:c.path>l.path?1:0),m=M(T(g));return{schemaVersion:"1.1",completeness:e.completeness,completenessReasons:t,resolverIdentity:e.resolverIdentity,compilerIdentity:e.compilerIdentity,compilerOptionsHash:e.compilerOptionsHash,tsconfigHash:e.tsconfigHash,candidateTreeHash:m,evidenceRequirementsHash:e.evidenceRequirementsHash,...e.projectPackageName?{projectPackageName:e.projectPackageName}:{},files:n,dependencies:r,capabilityUses:s,ambientUses:i,publishCalls:o,intentReferences:a,safetyUses:d,classShapes:u}}function Wn(e){let t=js(e);return{...t,factsHash:M(T(t))}}function Kt(e){return Wn(Zn(K(e,"$"),!1))}function K(e,t){if(!e||typeof e!="object"||Array.isArray(e))throw new Error(`${t} must be an object.`);return e}function Y(e,t,n){let r=new Set(t),s=Object.keys(e).find(i=>!r.has(i));if(s)throw new Error(`${n}.${s} is not part of schema ${"1.1"}.`)}function F(e,t,n){let r=e[t];if(typeof r!="string"||r.length===0)throw new Error(`${n}.${t} must be a non-empty string.`);return r}function Re(e,t,n){if(e[t]!==void 0)return F(e,t,n)}function W(e,t,n){let r=F(e,t,n),s=r.replace(/\\/g,"/");if(!s||s.startsWith("/")||/^[A-Za-z]:\//.test(s)||/[\u0000-\u001f\u007f]/.test(s))throw new Error(`${n}.${t} must be a canonical project-relative path.`);let i=[];for(let a of s.split("/"))if(!(!a||a==="."))if(a===".."){if(i.length===0)throw new Error(`${n}.${t} must be a canonical project-relative path.`);i.pop()}else i.push(a);let o=i.join("/");if(!o||o!==r)throw new Error(`${n}.${t} must be a canonical project-relative path.`);return o}function $(e,t,n){if(typeof e[t]!="boolean")throw new Error(`${n}.${t} must be a boolean.`);return e[t]}function Jn(e,t,n){let r=e[t];if(!Number.isInteger(r)||Number(r)<0)throw new Error(`${n}.${t} must be a non-negative integer.`);return Number(r)}function Ee(e,t,n){let r=Jn(e,t,n);if(r===0)throw new Error(`${n}.${t} must be a positive integer.`);return r}function J(e,t,n){let r=e[t];if(!Array.isArray(r))throw new Error(`${n}.${t} must be an array.`);return r}function ie(e,t,n,r){let s=e[t];if(typeof s!="string"||!n.includes(s))throw new Error(`${r}.${t} must be one of ${n.join(", ")}.`);return s}function Yn(e,t){if(!Array.isArray(e)||e.some(n=>typeof n!="string"||!n))throw new Error(`${t} must be an array of non-empty strings.`);return[...e]}function Us(e,t,n){let r=new Set;for(let s of e){let i=t(s);if(r.has(i))throw new Error(`${n} must not contain duplicate facts (${i}).`);r.add(i)}}function Zn(e,t){Y(e,["schemaVersion","completeness","completenessReasons","resolverIdentity","compilerIdentity","compilerOptionsHash","tsconfigHash","evidenceRequirementsHash","projectPackageName","files","dependencies","capabilityUses","ambientUses","publishCalls","intentReferences","safetyUses","classShapes",...t?["candidateTreeHash","factsHash"]:[]],"$");let n=ie(e,"schemaVersion",["1.0","1.1"],"$"),r=ie(e,"completeness",["complete","partial","unavailable"],"$"),s=J(e,"completenessReasons","$").map((I,R)=>{let f=`$.completenessReasons[${R}]`,h=K(I,f);Y(h,["code","message","file"],f);let S=h.file===void 0?void 0:W(h,"file",f);return{code:F(h,"code",f),message:F(h,"message",f),...S?{file:S}:{}}});if(r==="complete"&&s.length>0)throw new Error("$.completenessReasons must be empty when completeness is complete.");if(r!=="complete"&&s.length===0)throw new Error("$.completenessReasons must explain partial or unavailable facts.");let i=J(e,"files","$").map((I,R)=>{let f=`$.files[${R}]`,h=K(I,f);return Y(h,["path","contentHash","parseStatus","parseDiagnosticCount","exportsOnlyTypes","typeOnlyExportNames","hasTopLevelSideEffects"],f),{path:W(h,"path",f),contentHash:F(h,"contentHash",f),parseStatus:ie(h,"parseStatus",["parsed","invalid"],f),parseDiagnosticCount:Jn(h,"parseDiagnosticCount",f),exportsOnlyTypes:$(h,"exportsOnlyTypes",f),typeOnlyExportNames:Yn(h.typeOnlyExportNames,`${f}.typeOnlyExportNames`),hasTopLevelSideEffects:$(h,"hasTopLevelSideEffects",f)}}),o=J(e,"dependencies","$").map((I,R)=>{let f=`$.dependencies[${R}]`,h=K(I,f);Y(h,["from","specifier","kind","typeOnly","line","resolution","target","namedBindings","targetTypeOnlyExports","sourcePureTypeModule","namedBindingsTypeOnly","portProofEligible"],f);let S=Re(h,"specifier",f),k=Re(h,"target",f),N=ie(h,"resolution",["resolved-project","resolved-external","unresolved","dynamic"],f);if(N==="resolved-project"&&!k)throw new Error(`${f}.target is required for resolved-project dependencies.`);if(N!=="resolved-project"&&k)throw new Error(`${f}.target is only allowed for resolved-project dependencies.`);if(N!=="dynamic"&&!S)throw new Error(`${f}.specifier is required unless resolution is dynamic.`);return{from:W(h,"from",f),...S?{specifier:S}:{},kind:ie(h,"kind",["import","export","dynamic-import","require"],f),typeOnly:$(h,"typeOnly",f),line:Ee(h,"line",f),resolution:N,...k?{target:W(h,"target",f)}:{},...h.namedBindings!==void 0?{namedBindings:Yn(h.namedBindings,`${f}.namedBindings`)}:{},...h.targetTypeOnlyExports!==void 0?{targetTypeOnlyExports:$(h,"targetTypeOnlyExports",f)}:{},...h.sourcePureTypeModule!==void 0?{sourcePureTypeModule:$(h,"sourcePureTypeModule",f)}:{},...h.namedBindingsTypeOnly!==void 0?{namedBindingsTypeOnly:$(h,"namedBindingsTypeOnly",f)}:{},...h.portProofEligible!==void 0?{portProofEligible:$(h,"portProofEligible",f)}:{}}}),a=J(e,"capabilityUses","$").map((I,R)=>{let f=`$.capabilityUses[${R}]`,h=K(I,f);return Y(h,["file","line","symbol","capability","source"],f),{file:W(h,"file",f),line:Ee(h,"line",f),symbol:F(h,"symbol",f),capability:ie(h,"capability",qn,f),source:ie(h,"source",["ambient-global","import-based"],f)}}),d=J(e,"ambientUses","$").map((I,R)=>{let f=`$.ambientUses[${R}]`,h=K(I,f);return Y(h,["file","line","symbol"],f),{file:W(h,"file",f),line:Ee(h,"line",f),symbol:F(h,"symbol",f)}}),u=J(e,"publishCalls","$").map((I,R)=>{let f=`$.publishCalls[${R}]`,h=K(I,f);Y(h,["file","line","rawIntentName","objectHasIntent","arkPublishCandidate","hasSource","sourceIntent"],f);let S=Re(h,"rawIntentName",f),k=Re(h,"sourceIntent",f);return{file:W(h,"file",f),line:Ee(h,"line",f),...S?{rawIntentName:S}:{},objectHasIntent:$(h,"objectHasIntent",f),arkPublishCandidate:$(h,"arkPublishCandidate",f),hasSource:$(h,"hasSource",f),...k?{sourceIntent:k}:{}}}),g=J(e,"intentReferences","$").map((I,R)=>{let f=`$.intentReferences[${R}]`,h=K(I,f);return Y(h,["file","line","intent"],f),{file:W(h,"file",f),line:Ee(h,"line",f),intent:F(h,"intent",f)}}),m=J(e,"safetyUses","$").map((I,R)=>{let f=`$.safetyUses[${R}]`,h=K(I,f);Y(h,["file","line","kind","symbol"],f);let S=Re(h,"symbol",f),k=ie(h,"kind",["ts-suppression","any-cast","dynamic-import","dynamic-require","in-memory-store"],f);if(k==="in-memory-store"&&!S)throw new Error(`${f}.symbol is required for in-memory-store facts.`);if(k!=="in-memory-store"&&S)throw new Error(`${f}.symbol is only allowed for in-memory-store facts.`);return{file:W(h,"file",f),line:Ee(h,"line",f),kind:k,...S?{symbol:S}:{}}});Us(i,I=>I.path,"$.files");let c=new Set(i.map(I=>I.path));for(let I of i){if(I.parseStatus==="parsed"&&I.parseDiagnosticCount!==0)throw new Error(`$.files[${I.path}].parseDiagnosticCount must be 0 when parseStatus is parsed.`);if(I.parseStatus==="invalid"&&I.parseDiagnosticCount===0)throw new Error(`$.files[${I.path}].parseDiagnosticCount must be positive when parseStatus is invalid.`)}if(r==="complete"&&i.some(I=>I.parseStatus==="invalid"))throw new Error("$.completeness cannot be complete when a candidate file failed to parse.");for(let I of o)if(!c.has(I.from))throw new Error(`$.dependencies references missing source file ${I.from}.`);for(let[I,R]of[["$.capabilityUses",a],["$.ambientUses",d],["$.publishCalls",u],["$.intentReferences",g],["$.safetyUses",m]])for(let f of R)if(!c.has(f.file))throw new Error(`${I} references missing file ${f.file}.`);let l=Re(e,"projectPackageName","$"),y=(e.classShapes===void 0?[]:J(e,"classShapes","$")).map((I,R)=>{let f=`$.classShapes[${R}]`,h=K(I,f);Y(h,["file","className","exported","hasPublicMutableFields","hasPublicSetters","hasPublicConstructor","hasStaticFactory","mutatingMethods","dataOnly"],f);let S=J(h,"mutatingMethods",f).map((k,N)=>{let D=`${f}.mutatingMethods[${N}]`,_=K(k,D);return Y(_,["name","referencesGuardOrPublish"],D),{name:F(_,"name",D),referencesGuardOrPublish:$(_,"referencesGuardOrPublish",D)}});return{file:W(h,"file",f),className:F(h,"className",f),exported:$(h,"exported",f),hasPublicMutableFields:$(h,"hasPublicMutableFields",f),hasPublicSetters:$(h,"hasPublicSetters",f),hasPublicConstructor:$(h,"hasPublicConstructor",f),hasStaticFactory:$(h,"hasStaticFactory",f),mutatingMethods:S,...h.dataOnly===void 0?{}:{dataOnly:$(h,"dataOnly",f)}}});return{schemaVersion:n,completeness:r,completenessReasons:s,resolverIdentity:F(e,"resolverIdentity","$"),compilerIdentity:F(e,"compilerIdentity","$"),compilerOptionsHash:F(e,"compilerOptionsHash","$"),tsconfigHash:F(e,"tsconfigHash","$"),evidenceRequirementsHash:F(e,"evidenceRequirementsHash","$"),...l?{projectPackageName:l}:{},files:i,dependencies:o,capabilityUses:a,ambientUses:d,publishCalls:u,intentReferences:g,safetyUses:m,classShapes:y}}function oe(e){let t=K(e,"$"),n=F(t,"factsHash","$"),r=F(t,"candidateTreeHash","$"),s=Wn(Zn(t,!0));if(s.factsHash!==n)throw new Error(`$.factsHash does not match the canonical payload (${s.factsHash}).`);if(r!==s.candidateTreeHash)throw new Error(`$.candidateTreeHash does not match the canonical file tree (${s.candidateTreeHash}).`);return s}var Gs=["network","filesystem","clock","randomness","environment","process","persistence"],x={type:"string",minLength:1},ve={type:"integer",minimum:1},X={type:"string",minLength:1,pattern:"^(?!/)(?![A-Za-z]:/)(?!.*\\\\)(?!.*//)(?!.*(?:^|/)\\.{1,2}(?:/|$))(?!.*[\\u0000-\\u001f\\u007f])(?!.*\\/$).+$"},zt={$schema:"https://json-schema.org/draft/2020-12/schema",$id:"https://unpkg.com/arkgate@3/schemas/ark.resolved-candidate-facts.schema.json",title:"ArkGate resolved candidate facts",type:"object",additionalProperties:!1,required:["schemaVersion","completeness","completenessReasons","resolverIdentity","compilerIdentity","compilerOptionsHash","tsconfigHash","candidateTreeHash","evidenceRequirementsHash","files","dependencies","capabilityUses","ambientUses","publishCalls","intentReferences","safetyUses","factsHash"],properties:{schemaVersion:{enum:["1.0","1.1"]},completeness:{enum:["complete","partial","unavailable"]},completenessReasons:{type:"array",items:{type:"object",additionalProperties:!1,required:["code","message"],properties:{code:x,message:x,file:X}}},resolverIdentity:x,compilerIdentity:x,compilerOptionsHash:x,tsconfigHash:x,candidateTreeHash:x,evidenceRequirementsHash:x,projectPackageName:x,files:{type:"array",uniqueItems:!0,items:{type:"object",additionalProperties:!1,required:["path","contentHash","parseStatus","parseDiagnosticCount","exportsOnlyTypes","typeOnlyExportNames","hasTopLevelSideEffects"],properties:{path:X,contentHash:x,parseStatus:{enum:["parsed","invalid"]},parseDiagnosticCount:{type:"integer",minimum:0},exportsOnlyTypes:{type:"boolean"},typeOnlyExportNames:{type:"array",items:x},hasTopLevelSideEffects:{type:"boolean"}},allOf:[{if:{properties:{parseStatus:{const:"parsed"}}},then:{properties:{parseDiagnosticCount:{const:0}}}},{if:{properties:{parseStatus:{const:"invalid"}}},then:{properties:{parseDiagnosticCount:{minimum:1}}}}]}},dependencies:{type:"array",items:{type:"object",additionalProperties:!1,required:["from","kind","typeOnly","line","resolution"],properties:{from:X,specifier:x,kind:{enum:["import","export","dynamic-import","require"]},typeOnly:{type:"boolean"},line:ve,resolution:{enum:["resolved-project","resolved-external","unresolved","dynamic"]},target:X,namedBindings:{type:"array",items:x},targetTypeOnlyExports:{type:"boolean"},sourcePureTypeModule:{type:"boolean"},namedBindingsTypeOnly:{type:"boolean"},portProofEligible:{type:"boolean"}},allOf:[{if:{properties:{resolution:{const:"resolved-project"}}},then:{required:["target"]},else:{not:{required:["target"]}}},{if:{properties:{resolution:{const:"dynamic"}}},else:{required:["specifier"]}}]}},capabilityUses:{type:"array",items:{type:"object",additionalProperties:!1,required:["file","line","symbol","capability","source"],properties:{file:X,line:ve,symbol:x,capability:{enum:Gs},source:{enum:["ambient-global","import-based"]}}}},ambientUses:{type:"array",items:{type:"object",additionalProperties:!1,required:["file","line","symbol"],properties:{file:X,line:ve,symbol:x}}},publishCalls:{type:"array",items:{type:"object",additionalProperties:!1,required:["file","line","objectHasIntent","arkPublishCandidate","hasSource"],properties:{file:X,line:ve,rawIntentName:x,objectHasIntent:{type:"boolean"},arkPublishCandidate:{type:"boolean"},hasSource:{type:"boolean"},sourceIntent:x}}},intentReferences:{type:"array",items:{type:"object",additionalProperties:!1,required:["file","line","intent"],properties:{file:X,line:ve,intent:x}}},safetyUses:{type:"array",items:{type:"object",additionalProperties:!1,required:["file","line","kind"],properties:{file:X,line:ve,kind:{enum:["ts-suppression","any-cast","dynamic-import","dynamic-require","in-memory-store"]},symbol:x},allOf:[{if:{properties:{kind:{const:"in-memory-store"}}},then:{required:["symbol"]},else:{not:{required:["symbol"]}}}]}},classShapes:{type:"array",items:{type:"object",additionalProperties:!1,required:["file","className","exported","hasPublicMutableFields","hasPublicSetters","hasPublicConstructor","hasStaticFactory","mutatingMethods"],properties:{file:X,className:x,exported:{type:"boolean"},hasPublicMutableFields:{type:"boolean"},hasPublicSetters:{type:"boolean"},hasPublicConstructor:{type:"boolean"},hasStaticFactory:{type:"boolean"},dataOnly:{type:"boolean"},mutatingMethods:{type:"array",items:{type:"object",additionalProperties:!1,required:["name","referencesGuardOrPublish"],properties:{name:x,referencesGuardOrPublish:{type:"boolean"}}}}}}},factsHash:x},allOf:[{if:{properties:{completeness:{const:"complete"}}},then:{properties:{completenessReasons:{maxItems:0},files:{items:{properties:{parseStatus:{const:"parsed"}}}}}}},{if:{properties:{completeness:{enum:["partial","unavailable"]}}},then:{properties:{completenessReasons:{minItems:1}}}}]};var qt="1.0";function U(e){return`${e.from}->${e.to}`}function Ve(e,t,n,r="dependency"){return{id:`${e}:${r}:${U(t)}`,classification:e,subject:"dependency",from:t.from,to:t.to,message:n,...e==="missing"?{nextAction:`Add the planned dependency ${U(t)} to the candidate, then preflight again.`}:e==="contradictory"?{nextAction:`Replace the reverse dependency with ${U(t)}, then preflight again.`}:e==="unplanned"?{nextAction:r==="dependency-removed"?`Restore the removed dependency ${U(t)} in the candidate, then preflight again.`:`Remove the unplanned dependency ${U(t)} from the candidate, then preflight again.`}:{}}}function Ce(e){let t=[],n=new Map(e.changeMap.map.files.map(c=>[c.path,c])),r=new Map(e.changes.map(c=>[c.path,c])),s=new Map(e.changeMap.map.dependencies.map(c=>[U(c),c])),i=new Map(e.baseDependencies.map(c=>[U(c),c])),o=new Map(e.candidateDependencies.map(c=>[U(c),c]));for(let c of[...n.values()].sort((l,p)=>l.path.localeCompare(p.path))){let l=r.get(c.path);l?l.operation!==c.operation?t.push({id:`contradictory:file:${c.path}`,classification:"contradictory",subject:"file",path:c.path,expectedOperation:c.operation,actualOperation:l.operation,message:`${c.path} was planned as ${c.operation} but the actual operation is ${l.operation}.`,nextAction:`Change ${c.path} to the planned ${c.operation} operation, then preflight again.`}):t.push({id:`satisfied:file:${c.path}`,classification:"satisfied",subject:"file",path:c.path,expectedOperation:c.operation,actualOperation:l.operation,message:`${c.path} matches the planned ${c.operation} operation.`}):t.push({id:`missing:file:${c.path}`,classification:"missing",subject:"file",path:c.path,expectedOperation:c.operation,message:`${c.path} was planned as ${c.operation} but is absent from the actual change.`,nextAction:`${c.operation[0].toUpperCase()}${c.operation.slice(1)} ${c.path} in the complete change set, then preflight again.`})}for(let c of[...r.values()].sort((l,p)=>l.path.localeCompare(p.path)))n.has(c.path)||t.push({id:`unplanned:file:${c.path}`,classification:"unplanned",subject:"file",path:c.path,actualOperation:c.operation,message:`${c.path} has an unplanned ${c.operation} operation.`,nextAction:`Remove ${c.path} from the change set, then preflight again.`});let a=new Set;for(let c of[...s.values()].sort((l,p)=>U(l).localeCompare(U(p)))){if(o.has(U(c))){t.push(Ve("satisfied",c,`${c.from} -> ${c.to} exists in the candidate architecture.`));continue}let l={from:c.to,to:c.from};o.has(U(l))?(a.add(U(l)),t.push(Ve("contradictory",c,`${c.from} -> ${c.to} was planned, but the candidate contains the reverse edge.`))):t.push(Ve("missing",c,`${c.from} -> ${c.to} is absent from the candidate architecture.`))}let d=new Set([...n.keys(),...r.keys()]);for(let[c,l]of[...o].sort(([p],[y])=>p.localeCompare(y)))i.has(c)||s.has(c)||a.has(c)||!d.has(l.from)&&!d.has(l.to)||t.push({...Ve("unplanned",l,`${l.from} -> ${l.to} was added without a matching planned dependency.`,"dependency-added"),actualOperation:"added"});let u=new Set(e.changeMap.map.files.filter(c=>c.operation==="delete").map(c=>c.path));for(let[c,l]of[...i].sort(([p],[y])=>p.localeCompare(y)))o.has(c)||u.has(l.from)||u.has(l.to)||!d.has(l.from)&&!d.has(l.to)||t.push({...Ve("unplanned",l,`${l.from} -> ${l.to} was removed without a planned file deletion.`,"dependency-removed"),actualOperation:"removed"});let g={satisfied:0,missing:1,contradictory:2,unplanned:3};t.sort((c,l)=>g[c.classification]-g[l.classification]||(c.subject===l.subject?0:c.subject==="file"?-1:1)||c.id.localeCompare(l.id));let m={satisfied:t.filter(c=>c.classification==="satisfied").length,missing:t.filter(c=>c.classification==="missing").length,contradictory:t.filter(c=>c.classification==="contradictory").length,unplanned:t.filter(c=>c.classification==="unplanned").length};return{schemaVersion:"1.0",readOnly:!0,changeMapHash:e.changeMap.hash,structurallyConverged:m.missing===0&&m.contradictory===0&&m.unplanned===0,behavioralCompletion:"not-evaluated",summary:m,findings:t}}var Bs="1.0",Yt="https://unpkg.com/arkgate/schemas/ark.arkrules.schema.json",er=["aggregate-private-state","always-valid-factory","domain-event-on-mutation","orchestration-only","thin-adapter","no-anemic-model","invariant-coverage"],Ks=["no-anemic-model"],Xn={type:"array",items:{type:"string",minLength:1},uniqueItems:!0},Wt={$schema:"https://json-schema.org/draft/2020-12/schema",$id:Yt,title:"ArkGate ArkRules (intra-layer contract)",description:"Per-layer structure sensors and invariant catalog consumed by the ArkGate Effective Contract.",type:"object",additionalProperties:!1,required:["schemaVersion","layer"],properties:{$schema:{type:"string",minLength:1,default:Yt},schemaVersion:{type:"string",const:"1.0",default:"1.0"},layer:{type:"string",minLength:1},structure:{type:"array",default:[],items:{$ref:"#/$defs/structureEntry"}},invariants:{type:"array",default:[],items:{$ref:"#/$defs/invariantEntry"}}},$defs:{structureEntry:{type:"object",additionalProperties:!1,required:["id","sensor"],properties:{id:{type:"string",minLength:1},sensor:{type:"string",enum:[...er]},mode:{type:"string",enum:["advisory","enforced"],default:"advisory"},appliesTo:Xn,description:{type:"string",minLength:1}}},invariantEntry:{type:"object",additionalProperties:!1,required:["id","description"],properties:{id:{type:"string",minLength:1},description:{type:"string",minLength:1},aggregate:{type:"string",minLength:1},coverage:{type:"object",additionalProperties:!1,properties:{test:{type:"boolean"},symbol:{type:"string",minLength:1}}},mode:{type:"string",enum:["advisory","enforced"],default:"advisory"},appliesTo:Xn}}}},pe=class extends Error{issues;source;constructor(t,n){super(`Invalid ArkRules (${t}):
|
package/docs/README.md
CHANGED
|
@@ -58,10 +58,10 @@ These are **not** the day-to-day product path. They stay in the repo for evidenc
|
|
|
58
58
|
| Field adoption kit (scaffolding, not closed) | [field/](field/) |
|
|
59
59
|
| Runtime hardening (experimental) | [production-hardening.md](production-hardening.md) |
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
Prior: [releases/4.6.
|
|
64
|
-
Previous: [releases/4.5.7.md](releases/4.5.7.md) · [releases/4.5.6.md](releases/4.5.6.md) · [releases/4.5.5.md](releases/4.5.5.md) · [releases/4.5.0.md](releases/4.5.0.md) · [releases/4.4.0.md](releases/4.4.0.md) · [releases/4.3.0.md](releases/4.3.0.md) · [releases/4.2.1.md](releases/4.2.1.md) · [releases/4.2.0.md](releases/4.2.0.md) · [releases/4.1.1.md](releases/4.1.1.md).
|
|
61
|
+
Current published: [releases/4.6.2.md](releases/4.6.2.md) (`arkgate@4.6.2` on npm `latest`).
|
|
62
|
+
Prepared: [releases/4.6.3.md](releases/4.6.3.md) (Codex operation-scoped hard write; not yet published).
|
|
63
|
+
Prior: [releases/4.6.1.md](releases/4.6.1.md) (`arkgate@4.6.1`).
|
|
64
|
+
Previous: [releases/4.6.0.md](releases/4.6.0.md) · [releases/4.5.7.md](releases/4.5.7.md) · [releases/4.5.6.md](releases/4.5.6.md) · [releases/4.5.5.md](releases/4.5.5.md) · [releases/4.5.0.md](releases/4.5.0.md) · [releases/4.4.0.md](releases/4.4.0.md) · [releases/4.3.0.md](releases/4.3.0.md) · [releases/4.2.1.md](releases/4.2.1.md) · [releases/4.2.0.md](releases/4.2.0.md) · [releases/4.1.1.md](releases/4.1.1.md).
|
|
65
65
|
Previous major: [releases/4.0.0.md](releases/4.0.0.md) (`arkgate@4.0.0`).
|
|
66
66
|
Config: [configuration.md](configuration.md) · Agent skills dual-plane: [agent-guide.md](agent-guide.md).
|
|
67
67
|
|
package/docs/agent-guide.md
CHANGED
|
@@ -8,9 +8,9 @@ reference for agents and codegen: write hooks, advisory MCP tools, CI, and `/ark
|
|
|
8
8
|
- Docs hub: [README.md](README.md)
|
|
9
9
|
|
|
10
10
|
Guarantees differ by host; start with the
|
|
11
|
-
[canonical host support matrix](../README.md#host-enforcement-support). The
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
[canonical host support matrix](../README.md#host-enforcement-support). The operation-scoped
|
|
12
|
+
local / all-path CI split is a deliberate trade-off, not a gap: covered local hooks block early,
|
|
13
|
+
MCP coaches, and a required merge status is the one boundary every write path can share.
|
|
14
14
|
|
|
15
15
|
CLI names: prefer **`arkgate` / `arkgate-check` / `arkgate-mcp`**; aliases `ark` / `ark-check` /
|
|
16
16
|
`ark-mcp` still work for one major. **arkgate@3.8.0+** tests packed project TypeScript
|
|
@@ -41,17 +41,20 @@ npx ark-check --install-agent-gates --skills-only --force
|
|
|
41
41
|
### Write-path honesty
|
|
42
42
|
|
|
43
43
|
Claude/Grok/Antigravity/Cursor can hard-block listed PreToolUse / preToolUse ops when installed
|
|
44
|
-
and trusted (Cursor: `Write` / `StrReplace` via `.cursor/hooks.json`). Codex
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
and trusted (Cursor: `Write` / `StrReplace` via `.cursor/hooks.json`). Codex CLI and local
|
|
45
|
+
ChatGPT Desktop/App Server can hard-block a complete `apply_patch` through a trusted
|
|
46
|
+
`.codex/hooks.json`; installed files stay unverified until a fresh covered invocation. Hosted
|
|
47
|
+
tools, specialized opt-out paths, shell/direct writes, incomplete patch reconstruction, and
|
|
48
|
+
OpenCode remain CI-backed or advisory. For every host, the repository-wide hard boundary is a
|
|
49
|
+
**required GitHub status context** that runs `arkgate-check --strict-merge` (alias
|
|
50
|
+
`ark-check --strict-merge`) — the CLI name is not the status context name. Soft-write or
|
|
51
|
+
unverified-hook evidence alone does not mean the project is unfinished. See
|
|
50
52
|
[ai-gates.md](ai-gates.md) and the README host matrix.
|
|
51
53
|
|
|
52
54
|
Surface the same plane from the CLI: pair **`ark status --json`** (activation facts) with
|
|
53
|
-
**`ark-check --doctor`** (`doctor.writePath`) —
|
|
54
|
-
merge status as the
|
|
55
|
+
**`ark-check --doctor`** (`doctor.writePath`) — operation-scoped local hard evidence where
|
|
56
|
+
observed, then **required** merge status as the all-path boundary. Product path:
|
|
57
|
+
[use.md — What you get](use.md#what-you-get) ·
|
|
55
58
|
[README host matrix](../README.md#host-enforcement-support).
|
|
56
59
|
|
|
57
60
|
**MCP project identity (4.2.0):** before trusting project-specific MCP evidence, call
|
|
@@ -1187,8 +1190,10 @@ Register the server itself in `.mcp.json` so the agent can handshake with `ark_i
|
|
|
1187
1190
|
}
|
|
1188
1191
|
```
|
|
1189
1192
|
|
|
1190
|
-
On Claude/Grok, the installed PreToolUse hook makes matched writes an enforced checkpoint.
|
|
1191
|
-
|
|
1193
|
+
On Claude/Grok, the installed PreToolUse hook makes matched writes an enforced checkpoint. Cursor
|
|
1194
|
+
does the same for Write/StrReplace, and Codex CLI/local Desktop does so for complete
|
|
1195
|
+
`apply_patch` calls after trust and runtime observation. MCP registration by itself remains
|
|
1196
|
+
advisory on every host because the agent must call the tool.
|
|
1192
1197
|
|
|
1193
1198
|
Decision rationale: [ADR 0017 — MCP verdicts require explicit project identity](adr/0017-mcp-project-identity-binding.md).
|
|
1194
1199
|
|
package/docs/ai-gates.md
CHANGED
|
@@ -12,15 +12,17 @@ overview: [develop.md](develop.md) · hub: [README.md](README.md).
|
|
|
12
12
|
| **Claude Code** | Hard PreToolUse for listed ops when installed + trusted + (for `hard:true`) runtime-observed | Required `arkgate-check --strict-merge` status |
|
|
13
13
|
| **Grok Build** | Hard PreToolUse for listed ops when installed + trusted + (for `hard:true`) runtime-observed | Required `arkgate-check --strict-merge` status |
|
|
14
14
|
| **Google Antigravity** | Hard PreToolUse for listed write tools when installed + trusted + (for `hard:true`) runtime-observed | Required `arkgate-check --strict-merge` status |
|
|
15
|
-
| **Cursor** |
|
|
16
|
-
| **OpenAI Codex** |
|
|
15
|
+
| **Cursor** | Hard preToolUse for Write/StrReplace when installed + trusted + runtime-observed | Required CI status (same check) |
|
|
16
|
+
| **OpenAI Codex** | Hard PreToolUse for complete local `apply_patch` in CLI/Desktop when installed + trusted + runtime-observed | Required CI status (same check) |
|
|
17
17
|
| **OpenCode** | **Advisory / best-effort** (MCP + optional experimental plugin) — **not** a hard boundary | Required CI status (same check) |
|
|
18
18
|
|
|
19
|
-
On Claude Code, Grok Build,
|
|
20
|
-
block
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
On Claude Code, Grok Build, Google Antigravity, Cursor, and Codex, an installed and trusted
|
|
20
|
+
PreToolUse hook can block the listed local operation before it lands on disk. Codex’s claim is
|
|
21
|
+
intentionally narrow: Ark must reconstruct the complete `apply_patch`, and a fresh hook invocation
|
|
22
|
+
must prove the operation. Current Codex CLI and local ChatGPT Desktop/App Server send the patch in
|
|
23
|
+
`tool_input.command`; hosted tools, specialized opt-out paths, shell/direct writes, and incomplete
|
|
24
|
+
patches remain outside that local claim. OpenCode `tool.execute.before` plugins have known subagent
|
|
25
|
+
bypass holes. See
|
|
24
26
|
the [canonical host support matrix](../README.md#host-enforcement-support) before installing. The
|
|
25
27
|
advisory-local / hard-CI split is a deliberate trade-off: local surfaces optimize feedback speed,
|
|
26
28
|
while a required merge status is the one boundary a repository can make every write path share.
|
|
@@ -327,29 +329,34 @@ Your repository backstop remains CI: `ark-check` fails its check on anything tha
|
|
|
327
329
|
through (Shell bypass, Tab, incomplete coverage). It blocks the merge only when that status
|
|
328
330
|
is required by repository policy.
|
|
329
331
|
|
|
330
|
-
## OpenAI Codex CLI
|
|
332
|
+
## OpenAI Codex CLI and local Desktop
|
|
331
333
|
|
|
332
334
|
Recommended for Ark projects.
|
|
333
335
|
|
|
336
|
+
Platform authority: [Codex Hooks](https://developers.openai.com/codex/hooks) ·
|
|
337
|
+
[Advanced configuration](https://developers.openai.com/codex/config-advanced) ·
|
|
338
|
+
[App Server](https://developers.openai.com/codex/app-server). Project-local hooks run only after
|
|
339
|
+
the project and exact hook definition are trusted.
|
|
340
|
+
|
|
334
341
|
Codex 0.123+ dispatches `PreToolUse` for the native `apply_patch` handler. Ark installs
|
|
335
342
|
`.codex/hooks.json` with `ApplyPatch|apply_patch|Write|Edit|MultiEdit` aliases and reconstructs
|
|
336
343
|
every added or updated file in a multi-file patch before allowing it. The hook passes
|
|
337
344
|
`--root . --root-env CODEX_PROJECT_DIR`: ArkGate reads the environment directly without
|
|
338
345
|
POSIX shell expansion and safely falls back to the hook working directory.
|
|
339
346
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
347
|
+
The trusted hook is a hard boundary for the covered local operation, not a universal Codex
|
|
348
|
+
guarantee. ArkGate claims `hard:true` only while processing a complete runtime-observed
|
|
349
|
+
`apply_patch`; `.codex/hooks.json` on disk is merely configured/unverified. Hosted tools,
|
|
350
|
+
specialized opt-out paths, shell/direct writes, and incomplete reconstruction remain CI-backed.
|
|
344
351
|
|
|
345
352
|
```bash
|
|
346
353
|
npx ark-check --install-agent-gates --tools codex
|
|
347
354
|
```
|
|
348
355
|
|
|
349
356
|
The generated hook includes `--hook-repair`, so a rejected patch **may emit** a structured
|
|
350
|
-
repair envelope (same JSON shape as Claude/Grok). **Reinjection is not guaranteed** on Codex
|
|
351
|
-
|
|
352
|
-
|
|
357
|
+
repair envelope (same JSON shape as Claude/Grok). **Reinjection is not guaranteed** on Codex:
|
|
358
|
+
the host must re-apply any fix. Exit `2` is the supported deny, and required CI remains the
|
|
359
|
+
all-path hard merge boundary. Codex still needs hook trust enabled for the project.
|
|
353
360
|
|
|
354
361
|
Modern Codex resolves MCP servers from the active project's `.codex/config.toml`. Ark writes
|
|
355
362
|
that file with relative paths, so every repository owns its primary `ark` binding without
|
|
@@ -409,8 +416,9 @@ observe a later MCP conversation from files alone. The matched `ark_identity` re
|
|
|
409
416
|
runtime observation for that caller and live process; it does not mutate the setup JSON.
|
|
410
417
|
`.codex/config.toml` by itself never upgrades `runtimeObserved` or `active`.
|
|
411
418
|
|
|
412
|
-
Codex uses
|
|
413
|
-
`ark-check` as the hard merge backstop. Register all three as soon as the repo is
|
|
419
|
+
Codex uses an operation-scoped hard local patch hook plus advisory MCP for discovery/validation
|
|
420
|
+
and `ark-check` as the all-path hard merge backstop. Register all three as soon as the repo is
|
|
421
|
+
adopted.
|
|
414
422
|
|
|
415
423
|
### Legacy Codex home fallback
|
|
416
424
|
|
|
@@ -501,9 +509,10 @@ released from Ark ownership.
|
|
|
501
509
|
home (`$CODEX_HOME/skills`). Home debt is **deferred** when the session host is not Codex.
|
|
502
510
|
- Legacy flat prompts alone are reported as non-loadable skill debt with a
|
|
503
511
|
`--skills-only --tools codex --force` (repo) or `--codex-home --force` (home) fix.
|
|
504
|
-
- Codex **
|
|
505
|
-
|
|
506
|
-
|
|
512
|
+
- Codex **complete local `apply_patch` is hard** when `.codex/hooks.json` is trusted and the
|
|
513
|
+
invocation is runtime-observed. MCP remains advisory; incomplete, hosted, specialized, shell,
|
|
514
|
+
and direct-write paths rely on CI `--strict-merge` (or `--strict`) as a **required GitHub status
|
|
515
|
+
context** (not “workflow file present”).
|
|
507
516
|
- CI workflows that run ark-check without the fail-closed profile (or with only
|
|
508
517
|
`--strict-config`) surface gap `enforcement-ci-not-fail-closed`.
|
|
509
518
|
|
package/docs/develop.md
CHANGED
|
@@ -36,8 +36,9 @@ Local write hardness **differs by host**. CI required status is the shared hard
|
|
|
36
36
|
| Host | Local write | MCP | Merge |
|
|
37
37
|
|------|-------------|-----|-------|
|
|
38
38
|
| Claude · Grok · Antigravity | Pre-write block when installed + trusted | Advisory | Required status context |
|
|
39
|
-
| Codex · OpenCode | Warning only (not blocked) | Advisory | Required status context |
|
|
40
39
|
| Cursor | Pre-write block for Write/StrReplace when `.cursor/hooks.json` is trusted | Advisory | Required status context |
|
|
40
|
+
| Codex CLI · local Desktop/App Server | Pre-write block for complete `apply_patch` when `.codex/hooks.json` is trusted | Advisory | Required status context |
|
|
41
|
+
| OpenCode | Warning only (not blocked) | Advisory | Required status context |
|
|
41
42
|
|
|
42
43
|
Full matrix and install commands: [ai-gates.md](ai-gates.md) · canonical table in [README](../README.md#host-enforcement-support).
|
|
43
44
|
|
|
@@ -52,6 +53,8 @@ npx arkgate-check --install-agent-gates --skills-only --force
|
|
|
52
53
|
|
|
53
54
|
Doctor reports what is actually installed and observed (`writePath` / enforcement state). Installed
|
|
54
55
|
files alone do not imply `hard:true` without runtime evidence where the product requires it.
|
|
56
|
+
Codex hosted tools, specialized opt-out paths, shell/direct filesystem writes, and incomplete
|
|
57
|
+
patch reconstruction remain outside the local hard claim and rely on required CI.
|
|
55
58
|
|
|
56
59
|
**Evidence split (Phase EH):** soft-write hosts keep `soft-write-host` in evidence without forcing
|
|
57
60
|
global **Not finished** when the contract is ready. With `ARK_DOCTOR_GITHUB=1`, successful CI runs
|
|
@@ -9,7 +9,7 @@ npx arkgate-check --install-agent-gates --tools claude,cursor,codex,grok
|
|
|
9
9
|
Installs:
|
|
10
10
|
|
|
11
11
|
- Write-path configuration (Claude/Grok/Antigravity/Cursor hard PreToolUse when covered;
|
|
12
|
-
Codex advisory
|
|
12
|
+
Codex hard complete local `apply_patch`; OpenCode advisory)
|
|
13
13
|
— PreToolUse / Cursor `preToolUse` uses **`--hook-repair`** (W4): on deny, stderr may include
|
|
14
14
|
`ARK_REPAIR_JSON` / `ARK_AUTOPATCH_JSON` for hosts that re-inject a patch.
|
|
15
15
|
Still exit 2 / hard block; never silent write. Drop `--hook-repair` for
|
package/docs/package-surface.md
CHANGED
|
@@ -17,6 +17,7 @@ hardening guide remains repository-hosted rather than duplicated in the gate tar
|
|
|
17
17
|
| Surface | How you use it | Stability notes |
|
|
18
18
|
|---------|----------------|-----------------|
|
|
19
19
|
| **CLI** | `arkgate` / `arkgate-check` (aliases `ark` / `ark-check`) | Flags and human text may improve; **JSON output shapes** for `--json` (check, doctor, plan, coverage, recommend, **status**, **agents-md**) are stable within a major. Additive fields OK; removals/renames are major. From 4.2, `--require-gates` implies strict config and verifies semantic Ark AGENTS, project-rooted MCP/compact Codex registration, and fail-closed CI rather than file presence alone. `ark status --json` is the unified status snapshot. `ark agents-md` is the version-matched agent projection (non-authoritative). |
|
|
20
|
+
| **Host write boundaries** | Generated trusted PreToolUse/preToolUse hooks + `ark-mcp --hook`; inspect with doctor/status | Hard is always operation-scoped and runtime-evidenced. From 4.6.3, Codex CLI and local ChatGPT Desktop/App Server can hard-block a complete `apply_patch` sent as `tool_input.command`; `.codex/hooks.json` on disk remains unverified until a fresh covered invocation. Hosted tools, specialized hook opt-outs, shell/direct writes, incomplete reconstruction, and humans rely on required CI. Repair envelopes may emit, but Codex reinjection is not guaranteed. |
|
|
20
21
|
| **Programmatic gate API** | `import { analyzeProject, loadContract, createAICodeGate, ... } from 'arkgate'` | The root export is the static gate/config/analysis contract listed below. It intentionally contains no runtime-kernel implementation. |
|
|
21
22
|
| **Improvement compass (4.4; status honesty 4.5)** | `ark-check --doctor --json` → `doctor.improvementCompass`; human doctor section **Improvement compass (not a score)**; HTML report `data-advisory="improvementCompass"`. **`ark status --json` / MCP `ark_status`** project a thin `improvementCompass` residual map with explicit honesty **`mode`**: `full` \| `subset` \| `unavailable` (always `notAScore: true`). When `mode` is `full`, status residual lens **ids** are a **subset of** doctor residual for the same facts (report snapshot stores the thin slice after `--report`). Incomplete or missing session facts → `subset` / `unavailable` + `reasonCode` / `reason` — **never invent green residual**. Residual never flips `valid` / strict-merge / `goal.met`. When status mode ≠ full, run doctor for full 15-lens detail. | Additive schema `1.0`. Closed **15** lens ids (`soc`, `cohesion`, `coupling`, `srp`, `dip`, `ocp`, `encapsulation`, `modularity`, `scalability`, `resilience`, `security`, `maintainability`, `testability`, `domain`, `stack`) with status `ok` \| `residual` \| `not-instrumented` \| `out-of-scope`, evidence refs, optional `nextAction`, capped `topResidual`, always **`notAScore: true`**. Projection from existing smells / walls / cohesion / ArkRules / design-weak only — **never** a gate input. Out-of-scope locked for scalability, resilience, and app security (no residual invent from missing SAST/APM). Root API: `buildImprovementCompass` / `IMPROVEMENT_LENS_IDS`; status: `projectStatusImprovementCompass` / `STATUS_COMPASS_MODES`. |
|
|
22
23
|
| **Deep-module coach (post-4.5 advisory)** | `ark-check --doctor --json` → `doctor.deepModuleCoach`; human doctor section **Deep-module coach (advisory — not a score)** always when doctor runs (empty candidates / hot-path `unavailable` are honesty, not omission); HTML `data-advisory="deepModuleCoach"`. | Additive schema `1.0`. Always **`notAScore: true`**. **`hotPaths`**: recent-churn heuristic from bounded git log; `available` + `status` `ok` \| `unavailable`; empty `paths` when history missing/incomplete — **never invent**. **`deepeningCandidates`**: cards projected only from existing design smells / physical cohesion / reshape pilot / pilotLoop / residual compass lenses — **empty when no evidence** (no fake candidates). Never flips `valid`, strict-merge, completeness green, or `goal.met`. Prefer deep modules / named seams / test-at-public-interface process language in skills. Domain pure + CLI gen mirror (`deepeningCoach.ts` / `bin/lib/deepening-coach.mjs`); **not** a root package export — consume via `doctor.deepModuleCoach` (or the gen mirror in Tooling). |
|
|
@@ -210,9 +211,9 @@ production deployment would need to satisfy; it is not a readiness certification
|
|
|
210
211
|
## Release notes (maintainers)
|
|
211
212
|
|
|
212
213
|
Ship notes for a version live under [releases/](https://github.com/pedroknigge/arkgate/tree/main/docs/releases)
|
|
213
|
-
(prepared: [4.6.
|
|
214
|
-
|
|
215
|
-
prior published: [4.6.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.6.0.md), [4.5.7.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.5.7.md), [4.5.6.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.5.6.md), [4.5.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.5.0.md), [4.4.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.4.0.md), [4.3.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.3.0.md),
|
|
214
|
+
(prepared: [4.6.3.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.6.3.md);
|
|
215
|
+
current published: [4.6.2.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.6.2.md);
|
|
216
|
+
prior published: [4.6.1.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.6.1.md), [4.6.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.6.0.md), [4.5.7.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.5.7.md), [4.5.6.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.5.6.md), [4.5.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.5.0.md), [4.4.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.4.0.md), [4.3.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.3.0.md),
|
|
216
217
|
[4.2.1.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.2.1.md);
|
|
217
218
|
previous: [4.2.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.2.0.md),
|
|
218
219
|
[4.1.1.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.1.1.md),
|
package/docs/product-voice.md
CHANGED
|
@@ -106,7 +106,7 @@ stay stable unless a change explicitly adds an alias.
|
|
|
106
106
|
| **runtime observed** | runtime observed | A live `ark_identity` matched this workspace |
|
|
107
107
|
| **required CI status** | required CI / status context | Merge hard boundary: required GitHub status running `arkgate-check --strict-merge` |
|
|
108
108
|
| **config ready** | contract ready | Project/import-rules/ArkRules honesty clear — not the same as a local pre-write block |
|
|
109
|
-
| **host limitation** | environment residual |
|
|
109
|
+
| **host limitation** | environment residual | Soft-write or uncovered host path (e.g. OpenCode, hosted/specialized tools) — do not paint the whole project unfinished |
|
|
110
110
|
| **allowed rule ids** | guardrail catalog | Closed vocabulary of sensors, capabilities, `ruleId`s, skill roles |
|
|
111
111
|
| **check (tool)** | scan | Deterministic engine / CLI / MCP. Same inputs → same verdict. No LLM. |
|
|
112
112
|
| **coaching / your judgment** | process | Skill- or agent-side. **Never** package pass/fail |
|
|
@@ -178,8 +178,8 @@ gate → same binary verdict on every parity-capable adapter
|
|
|
178
178
|
| Name the status light + plain fact + next action | “Enforce · leftover design work. Import rules check out; design smells remain. Next: one Shape door — explore → plan B → autopilot with OK.” |
|
|
179
179
|
| Rank one primary door under residual | Doctor **Primary next action** #1; **Also** only for secondary |
|
|
180
180
|
| Label expert skills as escapes | “Install skill pack only when doctor or a STOP handoff names a skill.” |
|
|
181
|
-
| State host write honesty | “Cursor
|
|
182
|
-
| Soft
|
|
181
|
+
| State host write honesty | “Cursor blocks trusted Write/StrReplace. Codex blocks complete trusted local `apply_patch` after runtime observation. Required GitHub status covers every path.” |
|
|
182
|
+
| Soft/unverified write ≠ unfinished project | “Architecture config ready; this host operation is advisory or unverified.” Keep environment residual in evidence; reserve **Not finished** for config/project debt. |
|
|
183
183
|
| Keep Suggest on start → doctor | New-here primary is finish `start`, not a competing recommend/architect curriculum |
|
|
184
184
|
| Qualify import-clean under leftover design | “None on checked imports … leftover design work remains. Not healthy finished.” |
|
|
185
185
|
| Prefer unverified-as-not-green | Incomplete analysis, unobserved hooks, and soft MCP never paint as a hard green pre-write block |
|
|
@@ -208,7 +208,7 @@ gate → same binary verdict on every parity-capable adapter
|
|
|
208
208
|
| Skill-shopping lists as the default curriculum | Progressive disclosure: one door first |
|
|
209
209
|
| “Healthy / done” while leftover design work remains | False done |
|
|
210
210
|
| “Honesty clear” as “architecture finished” | Honesty clear only means residual honesty sensors are quiet; graph/mode debt is separate |
|
|
211
|
-
| “Not finished” solely because host is
|
|
211
|
+
| “Not finished” solely because a host hook is unverified or one host path is advisory | Environment residual is not architecture debt; do not paint a green whole-tree project as unfinished architecture |
|
|
212
212
|
| “MCP installed / active” because a config file exists | Say **configured on disk · runtime unverified** until `ark_identity` matches the expected root |
|
|
213
213
|
| Treating an unverified legacy MCP call as authoritative | Compatibility is not proof; require `binding.status: "matched"` and `authoritative: true` |
|
|
214
214
|
| “Handler means controller” / “every constant is a business rule” | ArkRules inventory uses configured layer context and suppresses narrow technical/test evidence; candidates remain prompts for judgment |
|
package/docs/threat-model.md
CHANGED
|
@@ -44,13 +44,17 @@ infrastructure beyond how this package is published.
|
|
|
44
44
|
|
|
45
45
|
```
|
|
46
46
|
Claude/Grok host --PreToolUse--> arkgate-mcp (hard only for observed covered operation)
|
|
47
|
-
Codex
|
|
47
|
+
Codex apply_patch --PreToolUse--> arkgate-mcp (hard for complete trusted + observed local operation)
|
|
48
48
|
Any MCP host --tool call----> arkgate-mcp (advisory validation)
|
|
49
49
|
Human IDE --disk/git-----> working tree
|
|
50
50
|
working tree --PR-----------> CI ark-check --strict-merge
|
|
51
51
|
npm publish <-- signed tag --- GitHub Release + provenance
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
+
Codex hosted tools, specialized hook opt-outs, shell/direct writes, and incomplete patch
|
|
55
|
+
reconstruction do not inherit the local `apply_patch` claim; required CI remains the shared
|
|
56
|
+
all-path merge boundary.
|
|
57
|
+
|
|
54
58
|
## Residual risk (accepted)
|
|
55
59
|
|
|
56
60
|
- Branch protection is **external GitHub state** — doctor reports honestly when unavailable.
|
package/docs/use.md
CHANGED
|
@@ -49,7 +49,12 @@ In those cases a boundary linter or editor rules may be enough; see [README —
|
|
|
49
49
|
| Before merge | Make the Ark job a **required GitHub status context** running `arkgate-check --strict-merge` (alias `ark-check`) |
|
|
50
50
|
| Anytime | Doctor: Suggest / Adapt / Enforce (+ leftover design work if the design is still messy) |
|
|
51
51
|
|
|
52
|
-
**Cursor:** pre-write block for Write/StrReplace when `.cursor/hooks.json` is trusted.
|
|
52
|
+
**Cursor:** pre-write block for Write/StrReplace when `.cursor/hooks.json` is trusted.
|
|
53
|
+
**Codex CLI / local Desktop:** pre-write block for a complete `apply_patch` when
|
|
54
|
+
`.codex/hooks.json` is trusted and the operation is observed. Hosted/specialized paths,
|
|
55
|
+
shell/direct writes, and incomplete patches still rely on CI. **OpenCode:** local write stays
|
|
56
|
+
advisory (warning only, not blocked). An unverified host hook is environment evidence, not
|
|
57
|
+
unfinished architecture; **Not finished** is reserved for real project/config debt.
|
|
53
58
|
|
|
54
59
|
ArkGate is **not** a web framework, ORM, or app runtime. It is architecture enforcement + a coach for AI TypeScript.
|
|
55
60
|
|
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.pedroknigge/arkgate",
|
|
4
|
-
"description": "When your agent writes TypeScript, ArkGate stops it from breaking the layers
|
|
4
|
+
"description": "When your agent writes TypeScript, ArkGate stops it from breaking the layers.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/pedroknigge/arkgate",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "4.6.
|
|
9
|
+
"version": "4.6.3",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "arkgate",
|
|
14
|
-
"version": "4.6.
|
|
14
|
+
"version": "4.6.3",
|
|
15
15
|
"runtimeHint": "npx",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
@@ -128,9 +128,10 @@ because governed% is 100% and plan is empty.
|
|
|
128
128
|
**Honesty hard lines (doctor JSON):**
|
|
129
129
|
- `coverageHonesty.worseThanNoGate` / weak coverage (~<50%): green is **worse than no gate**.
|
|
130
130
|
- `baseline.honesty.dirtyBaselineRisk`: green-via-freeze may hide false-positive debt.
|
|
131
|
-
- `writePath.honesty.softWriteHost` (
|
|
132
|
-
best-effort**, not hard PreToolUse — required CI status is the hard merge boundary.
|
|
133
|
-
-
|
|
131
|
+
- `writePath.honesty.softWriteHost` (OpenCode or another uncovered path): write path is
|
|
132
|
+
**advisory / best-effort**, not hard PreToolUse — required CI status is the hard merge boundary.
|
|
133
|
+
- Cursor hard evidence is limited to trusted Write/StrReplace; Codex is limited to a complete,
|
|
134
|
+
trusted, runtime-observed local `apply_patch`. Do not borrow either claim for other paths.
|
|
134
135
|
|
|
135
136
|
## Related onboarding
|
|
136
137
|
|