arkgate 4.0.0 → 4.0.1

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/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- var wn="4.0.0";var $n="1.4";function I(e){return typeof e=="string"&&e.length>0?e:void 0}function Ht(e,t){return Number.isInteger(e)&&Number(e)>0?Number(e):t}function Pn(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, then preflight again.":`Define a port in ${t.fromLayer??"the source layer"}, inject the ${t.toLayer??"outer-layer"} implementation, then preflight again.`;if(e==="FORBIDDEN_GLOBAL")return`Inject ${t.target??"the capability"} through a port, then preflight again.`;if(e==="CAPABILITY_VIOLATION")return`Define a ${I(n.capability)??"capability"} port in ${t.fromLayer??"the walled layer"}, bind the implementation outside it, then preflight again.`;if(e==="CIRCULAR_DEPENDENCY")return"Extract the shared dependency into a third module, 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 s=t.arkruleSource??"arkrules/<Layer>.json";return`Fix the structure or invariant for ${t.arkruleId??"the ArkRule"} (declared in ${s}), 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 it(e,t="error"){let n=I(e.ruleId)??I(e.code)??"ARK_UNKNOWN",s=e.severity==="warning"?"warning":t,r={...I(e.target)?{target:I(e.target)}:{},...I(e.fromLayer)?{fromLayer:I(e.fromLayer)}:{},...I(e.toLayer)?{toLayer:I(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}:{},...I(e.capability)?{capability:I(e.capability)}:{},...I(e.edgeKind)?{edgeKind:I(e.edgeKind)}:{},...I(e.arkruleId)?{arkruleId:I(e.arkruleId)}:{},...I(e.arkruleSource)?{arkruleSource:I(e.arkruleSource)}:{}};return{ruleId:n,severity:s,message:I(e.message)??n,location:{file:I(e.file)??"<unknown>",line:Ht(e.line,1),column:Ht(e.column,1)},evidence:r,nextAction:I(e.nextAction)??Pn(n,r,e)}}function On(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 s=t==="complete"?[]:e.completenessReasons&&e.completenessReasons.length>0?e.completenessReasons.map(c=>({code:I(c.code)??"ANALYSIS_EVIDENCE_INCOMPLETE",message:I(c.message)??`Analysis ${t}: required evidence is incomplete.`,...I(c.file)?{file:I(c.file)}:{}})):[{code:t==="unavailable"?"ANALYSIS_UNAVAILABLE":"ANALYSIS_EVIDENCE_INCOMPLETE",message:`Analysis ${t}: required evidence is incomplete.`}],r={...I(e.policyHash)?{policyHash:I(e.policyHash)}:{},...I(e.resolverIdentity)?{resolverIdentity:I(e.resolverIdentity)}:{},...I(e.factsHash)?{factsHash:I(e.factsHash)}:{},...I(e.candidateTreeHash)?{candidateTreeHash:I(e.candidateTreeHash)}:{}};if(n==="resolved-candidate-facts"&&t!=="unavailable"){for(let c of["policyHash","resolverIdentity","factsHash","candidateTreeHash"])if(!r[c])throw new Error(`${c} is required for resolved ${t} adapter evidence.`)}let i=[...(e.violations??[]).map(c=>it(c,"error")),...(e.warnings??[]).map(c=>it(c,"warning"))],a={schemaVersion:"1.4",completenessReasons:s,diagnostics:i};if(n==="resolved-candidate-facts"){if(t==="unavailable")return{...a,mode:n,valid:!1,completeness:t,...r};let c={policyHash:r.policyHash,resolverIdentity:r.resolverIdentity,factsHash:r.factsHash,candidateTreeHash:r.candidateTreeHash};return t==="complete"?{...a,mode:n,valid:e.valid,completeness:t,...c}:{...a,mode:n,valid:!1,completeness:t,...c}}return t==="complete"?{...a,mode:n,valid:e.valid,completeness:t,...r}:{...a,mode:n,valid:!1,completeness:t,...r}}var Ln={$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.4"},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}}}}}};var ot=Object.freeze(["network","filesystem","clock","randomness","environment","process","persistence"]),ct=Object.freeze({fetch:"network",XMLHttpRequest:"network",Date:"clock","Date.now":"clock","Math.random":"randomness","process.env":"environment",process:"process"}),dt=Object.freeze(Object.keys(ct).sort()),at=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 Ie(e){if(!e||e.startsWith(".")||e.startsWith("/"))return null;let t=at[e];if(t)return t;let n=e.indexOf("/");if(n<0)return null;let s=e.slice(0,n),r=at[s];if(r)return r;let i=e.indexOf("/",n+1);return i<0?null:at[e.slice(0,i)]??null}function J(e,t){for(let n of t)if(lt[n]?.includes(e))return n;return null}function He(e){let t=e.split(".");for(let n=t.length;n>=1;n-=1){let s=t.slice(0,n).join("."),r=ct[s];if(r)return r}return null}function le(e){if(e?.pure===!0)return[...ot].sort();let n=(e?.capabilities?.deny??[]).filter(s=>ot.includes(s));return[...new Set(n)].sort()}function Ce(e,t){if(t.length===0)return!1;let n=new Set(t),s=e.split(".");for(let r=s.length;r>=1;r-=1)if(n.has(s.slice(0,r).join(".")))return!0;return!1}function Ve(e){let t=new Set,n=new Set,s=Object.keys(ct);for(let r of e?.forbiddenGlobals??[]){let i=s.filter(a=>a===r||a.startsWith(`${r}.`));if(i.length===0)n.add(r);else for(let a of i)t.add(`ambient:${a}`);for(let a of lt[r]??[])t.add(`import-exact:${a}`)}for(let r of le(e)){if(t.add(`import:${r}`),r==="process")for(let i of lt.process)t.add(`import-exact:${i}`);for(let i of s)He(i)===r&&t.add(`ambient:${i}`)}return{atoms:[...t].sort(),rawGlobals:[...n].sort()}}var Vt=new Map;function jt(e){return/[.*+?^${}()|[\]\\]/.test(e)?`\\${e}`:e}function pt(e){let t="";for(let n=0;n<e.length;n+=1){let s=e[n];if(s==="\\"&&n+1<e.length){let r=e[n+1];if("*?{}[],".includes(r)||r==="\\"){t+="\\"+r,n+=1;continue}t+="/";continue}t+=s}return t}function _n(e){let t=0;for(let n=0;n<e.length;n+=1){let s=e[n];if(s==="\\"){n+=1;continue}if(s==="{")t+=1;else if(s==="}"&&(t-=1,t<0))return!1}return t===0}function ee(e){let t=Vt.get(e);if(t)return t;let n=pt(e),s=_n(n),r="",i=0;for(let c=0;c<n.length;c+=1){let p=n[c];p==="\\"&&c+1<n.length?(r+=jt(n[c+1]),c+=1):p==="*"?n[c+1]==="*"?n[c+2]==="/"?(r+="(?:.*/)?",c+=2):(r+=".*",c+=1):r+="[^/]*":p==="?"?r+="[^/]":p==="{"&&s?(r+="(?:",i+=1):p==="}"&&s&&i>0?(r+=")",i-=1):p===","&&s&&i>0?r+="|":r+=jt(p)}let a=new RegExp(`^${r}$`);return Vt.set(e,a),a}function ut(e){let t=pt(String(e)),s=t.split("*")[0].split("/").filter(Boolean).length,r=t.replace(/\*/g,"").length;return s*1e4+r}function z(e,t){let n=String(e).split(/[/\\]/).join("/"),s,r=-1;for(let i of t??[])if(!(i.exclude??[]).some(a=>ee(a).test(n))){for(let a of i.patterns??[])if(ee(a).test(n)){let c=ut(a);c>r&&(r=c,s=i.name)}}return s}function Ut(e,t){if(!t?.length)return;let n=String(e).split(/[/\\]/).filter(Boolean),s=new Set(t.map(r=>String(r).toLowerCase()));for(let r=0;r<n.length-1;r+=1)if(s.has(n[r].toLowerCase()))return`${n[r].toLowerCase()}/${n[r+1].toLowerCase()}`}function Tn(e){let t=new Set;for(let n of e??[]){let r=pt(String(n)).split("/").filter(Boolean);for(let i=0;i<r.length;i+=1){let a=r[i];if((a==="**"||a==="*")&&i>0){let c=r[i-1];c&&!c.includes("*")&&!c.includes("{")&&!c.includes("}")&&t.add(c)}}}return[...t]}function Fn(e,t,n){if(Array.isArray(e.sliceFolders)&&e.sliceFolders.length>0)return e.sliceFolders.filter(r=>typeof r=="string"&&r.length>0);let s=(n??[]).find(r=>r.name===t);return Tn(s?.patterns)}function K(e,t,n,s){for(let r of e??[])if(!(r.from!==t||r.to!==n)&&r.allowed===!1){if(r.peerIsolation){let i=s?.fromPath,a=s?.toPath;if(!i||!a)return r;let c=Fn(r,t,s?.layers);if(c.length===0)return r;let p=Ut(i,c),y=Ut(a,c);if(!p||!y||p!==y)return r;continue}if(t!==n)return r}}function ce(e,t){return t&&e.isStringLiteralLike(t)?t.text:void 0}function qt(e,t){return e.getLineAndCharacterOfPosition(t.getStart(e)).line+1}function Gt(e,t){if(e.isImportDeclaration(t)){let s=t.importClause;if(!s)return!1;if(s.isTypeOnly)return!0;let r=s.namedBindings;return!!(r&&e.isNamedImports(r)&&r.elements.length>0&&r.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(s=>s.isTypeOnly))}function zt(e,t){let n={noLib:!0,noResolve:!0,target:e.ScriptTarget.Latest},s=e.createCompilerHost(n,!0);return s.getSourceFile=r=>r===t.fileName?t:void 0,s.fileExists=r=>r===t.fileName,s.readFile=r=>r===t.fileName?t.text:void 0,e.createProgram([t.fileName],n,s).getTypeChecker()}function ft(e,t){try{return e.getSymbolAtLocation(t)}catch{return}}function yt(e,t,n,s){let r=s.parent&&e.isShorthandPropertyAssignment(s.parent)&&s.parent.name===s,i;try{i=r?t.getShorthandAssignmentValueSymbol(s.parent):ft(t,s)}catch{i=void 0}return!!i?.declarations?.some(a=>a.getSourceFile().fileName===n.fileName)}function de(e,t){let n,s=[],r=(a,c,p,y=!1)=>s.push({specifier:p,kind:c,line:qt(t,a),typeOnly:y,unresolved:p===void 0,node:a}),i=a=>{if(e.isImportDeclaration(a))r(a,"import",ce(e,a.moduleSpecifier),Gt(e,a));else if(e.isExportDeclaration(a)&&a.moduleSpecifier)r(a,"export",ce(e,a.moduleSpecifier),Gt(e,a));else if(e.isImportEqualsDeclaration(a)&&e.isExternalModuleReference(a.moduleReference))r(a,"require",ce(e,a.moduleReference.expression),a.isTypeOnly===!0);else if(e.isCallExpression(a)){let c=a.expression.kind===e.SyntaxKind.ImportKeyword,y=e.isIdentifier(a.expression)&&a.expression.text==="require"&&!yt(e,n??(n=zt(e,t)),t,a.expression);(c||y)&&r(a,y?"require":"dynamic-import",ce(e,a.arguments[0]))}e.forEachChild(a,i)};return i(t),s}function Nn(e,t){let n=[],s=t;for(;e.isPropertyAccessExpression(s)||e.isElementAccessExpression(s);){if(e.isPropertyAccessExpression(s))n.unshift(s.name.text);else{let r=ce(e,s.argumentExpression);if(r===void 0)return;n.unshift(r)}s=s.expression}if(e.isIdentifier(s))return n.unshift(s.text),{root:s,segments:n}}function Dn(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 Bt(e,t){let n=t[0]==="globalThis"?t.slice(1):t;for(let s=n.length;s>=1;s-=1){let r=n.slice(0,s).join(".");if(e.has(r))return r}}function pe(e,t,n){if(n.length===0)return[];let s=new Set(n),r=zt(e,t),i=new Map,a=new Set;for(let o of t.statements)if(e.isVariableStatement(o))for(let l of o.declarationList.declarations)e.isIdentifier(l.name)&&a.add(l.name.text);let c=o=>{let l=Nn(e,o);if(!l)return;let g=ft(r,l.root),u=g?i.get(g):void 0;return u?[...u,...l.segments.slice(1)]:yt(e,r,t,l.root)||a.has(l.root.text)?void 0:l.segments};for(let o of t.statements)if(e.isVariableStatement(o))for(let l of o.declarationList.declarations){if(!l.initializer||!e.isIdentifier(l.name))continue;let g=c(l.initializer),u=ft(r,l.name);!g||!u||i.set(u,g)}let p=[],y=new Set,h=(o,l)=>{let g=qt(t,l),u=`${o}:${l.getStart(t)}`;y.has(u)||(y.add(u),p.push({name:o,line:g,node:l}))},m=o=>{let l=o.parent&&(e.isPropertyAccessExpression(o.parent)||e.isElementAccessExpression(o.parent))&&o.parent.expression===o;if((e.isPropertyAccessExpression(o)||e.isElementAccessExpression(o))&&!l){let g=c(o),u=g?Bt(s,g):void 0;u&&h(u,o)}else e.isIdentifier(o)&&s.has(o.text)&&Dn(e,o)&&!yt(e,r,t,o)&&h(o.text,o);if(e.isVariableDeclaration(o)&&e.isObjectBindingPattern(o.name)&&o.initializer){let g=c(o.initializer);if(g)for(let u of o.name.elements){if(!e.isIdentifier(u.name))continue;let b=u.propertyName?ce(e,u.propertyName)??u.propertyName.text:u.name.text,v=Bt(s,[...g,b]);v&&h(v,o.initializer)}}e.forEachChild(o,m)};return m(t),p}function mt(e,t,n){let s=[];for(let r of n?.dependencies??de(e,t)){if(r.typeOnly||!r.specifier)continue;let i=Ie(r.specifier);i&&s.push({capability:i,symbol:r.specifier,line:r.line,source:"import-based"})}for(let r of n?.ambientUses??pe(e,t,dt)){let i=He(r.name);i&&s.push({capability:i,symbol:r.name,line:r.line,source:"ambient-global"})}return s.sort((r,i)=>r.line-i.line||r.capability.localeCompare(i.capability)||r.symbol.localeCompare(i.symbol))}var gt={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."},ht=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 At(e,t){return t.flatMap((s,r)=>(s.prefixes??s.intentPrefixes??[]).map(i=>({layer:s.name,layerIndex:r,prefix:i.endsWith(".")?i:`${i}.`}))).filter(({prefix:s})=>e.startsWith(s)).sort((s,r)=>r.prefix.length-s.prefix.length||s.layerIndex-r.layerIndex)[0]?.layer}function te(e){return/^(Domain|Application|Adapter|Workflow|Job|Presentation|Reporting|Metadata|Security|Audit|Observability|Kernel)\.[A-Za-z0-9_.]+$/.test(e)}function Ee(e){if(!e.publishCall)return[];let t=[];return(e.rawIntentName!==void 0&&te(e.rawIntentName)||e.objectHasIntent)&&t.push({ruleId:"RAW_EVENT_PUBLISH",message:gt.RAW_EVENT_PUBLISH}),e.arkPublishCandidate&&!e.hasSource&&t.push({ruleId:"PUBLISH_MISSING_SOURCE",message:gt.PUBLISH_MISSING_SOURCE}),t}function x(e,t,n){return{ruleId:e,code:e,message:t,...n}}function ue(e,t){return e.slice(0,t).split(`
1
+ var wn="4.0.1";var $n="1.4";function I(e){return typeof e=="string"&&e.length>0?e:void 0}function Ht(e,t){return Number.isInteger(e)&&Number(e)>0?Number(e):t}function Pn(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, then preflight again.":`Define a port in ${t.fromLayer??"the source layer"}, inject the ${t.toLayer??"outer-layer"} implementation, then preflight again.`;if(e==="FORBIDDEN_GLOBAL")return`Inject ${t.target??"the capability"} through a port, then preflight again.`;if(e==="CAPABILITY_VIOLATION")return`Define a ${I(n.capability)??"capability"} port in ${t.fromLayer??"the walled layer"}, bind the implementation outside it, then preflight again.`;if(e==="CIRCULAR_DEPENDENCY")return"Extract the shared dependency into a third module, 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 s=t.arkruleSource??"arkrules/<Layer>.json";return`Fix the structure or invariant for ${t.arkruleId??"the ArkRule"} (declared in ${s}), 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 it(e,t="error"){let n=I(e.ruleId)??I(e.code)??"ARK_UNKNOWN",s=e.severity==="warning"?"warning":t,r={...I(e.target)?{target:I(e.target)}:{},...I(e.fromLayer)?{fromLayer:I(e.fromLayer)}:{},...I(e.toLayer)?{toLayer:I(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}:{},...I(e.capability)?{capability:I(e.capability)}:{},...I(e.edgeKind)?{edgeKind:I(e.edgeKind)}:{},...I(e.arkruleId)?{arkruleId:I(e.arkruleId)}:{},...I(e.arkruleSource)?{arkruleSource:I(e.arkruleSource)}:{}};return{ruleId:n,severity:s,message:I(e.message)??n,location:{file:I(e.file)??"<unknown>",line:Ht(e.line,1),column:Ht(e.column,1)},evidence:r,nextAction:I(e.nextAction)??Pn(n,r,e)}}function On(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 s=t==="complete"?[]:e.completenessReasons&&e.completenessReasons.length>0?e.completenessReasons.map(c=>({code:I(c.code)??"ANALYSIS_EVIDENCE_INCOMPLETE",message:I(c.message)??`Analysis ${t}: required evidence is incomplete.`,...I(c.file)?{file:I(c.file)}:{}})):[{code:t==="unavailable"?"ANALYSIS_UNAVAILABLE":"ANALYSIS_EVIDENCE_INCOMPLETE",message:`Analysis ${t}: required evidence is incomplete.`}],r={...I(e.policyHash)?{policyHash:I(e.policyHash)}:{},...I(e.resolverIdentity)?{resolverIdentity:I(e.resolverIdentity)}:{},...I(e.factsHash)?{factsHash:I(e.factsHash)}:{},...I(e.candidateTreeHash)?{candidateTreeHash:I(e.candidateTreeHash)}:{}};if(n==="resolved-candidate-facts"&&t!=="unavailable"){for(let c of["policyHash","resolverIdentity","factsHash","candidateTreeHash"])if(!r[c])throw new Error(`${c} is required for resolved ${t} adapter evidence.`)}let i=[...(e.violations??[]).map(c=>it(c,"error")),...(e.warnings??[]).map(c=>it(c,"warning"))],a={schemaVersion:"1.4",completenessReasons:s,diagnostics:i};if(n==="resolved-candidate-facts"){if(t==="unavailable")return{...a,mode:n,valid:!1,completeness:t,...r};let c={policyHash:r.policyHash,resolverIdentity:r.resolverIdentity,factsHash:r.factsHash,candidateTreeHash:r.candidateTreeHash};return t==="complete"?{...a,mode:n,valid:e.valid,completeness:t,...c}:{...a,mode:n,valid:!1,completeness:t,...c}}return t==="complete"?{...a,mode:n,valid:e.valid,completeness:t,...r}:{...a,mode:n,valid:!1,completeness:t,...r}}var Ln={$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.4"},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}}}}}};var ot=Object.freeze(["network","filesystem","clock","randomness","environment","process","persistence"]),ct=Object.freeze({fetch:"network",XMLHttpRequest:"network",Date:"clock","Date.now":"clock","Math.random":"randomness","process.env":"environment",process:"process"}),dt=Object.freeze(Object.keys(ct).sort()),at=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 Ie(e){if(!e||e.startsWith(".")||e.startsWith("/"))return null;let t=at[e];if(t)return t;let n=e.indexOf("/");if(n<0)return null;let s=e.slice(0,n),r=at[s];if(r)return r;let i=e.indexOf("/",n+1);return i<0?null:at[e.slice(0,i)]??null}function J(e,t){for(let n of t)if(lt[n]?.includes(e))return n;return null}function He(e){let t=e.split(".");for(let n=t.length;n>=1;n-=1){let s=t.slice(0,n).join("."),r=ct[s];if(r)return r}return null}function le(e){if(e?.pure===!0)return[...ot].sort();let n=(e?.capabilities?.deny??[]).filter(s=>ot.includes(s));return[...new Set(n)].sort()}function Ce(e,t){if(t.length===0)return!1;let n=new Set(t),s=e.split(".");for(let r=s.length;r>=1;r-=1)if(n.has(s.slice(0,r).join(".")))return!0;return!1}function Ve(e){let t=new Set,n=new Set,s=Object.keys(ct);for(let r of e?.forbiddenGlobals??[]){let i=s.filter(a=>a===r||a.startsWith(`${r}.`));if(i.length===0)n.add(r);else for(let a of i)t.add(`ambient:${a}`);for(let a of lt[r]??[])t.add(`import-exact:${a}`)}for(let r of le(e)){if(t.add(`import:${r}`),r==="process")for(let i of lt.process)t.add(`import-exact:${i}`);for(let i of s)He(i)===r&&t.add(`ambient:${i}`)}return{atoms:[...t].sort(),rawGlobals:[...n].sort()}}var Vt=new Map;function jt(e){return/[.*+?^${}()|[\]\\]/.test(e)?`\\${e}`:e}function pt(e){let t="";for(let n=0;n<e.length;n+=1){let s=e[n];if(s==="\\"&&n+1<e.length){let r=e[n+1];if("*?{}[],".includes(r)||r==="\\"){t+="\\"+r,n+=1;continue}t+="/";continue}t+=s}return t}function _n(e){let t=0;for(let n=0;n<e.length;n+=1){let s=e[n];if(s==="\\"){n+=1;continue}if(s==="{")t+=1;else if(s==="}"&&(t-=1,t<0))return!1}return t===0}function ee(e){let t=Vt.get(e);if(t)return t;let n=pt(e),s=_n(n),r="",i=0;for(let c=0;c<n.length;c+=1){let p=n[c];p==="\\"&&c+1<n.length?(r+=jt(n[c+1]),c+=1):p==="*"?n[c+1]==="*"?n[c+2]==="/"?(r+="(?:.*/)?",c+=2):(r+=".*",c+=1):r+="[^/]*":p==="?"?r+="[^/]":p==="{"&&s?(r+="(?:",i+=1):p==="}"&&s&&i>0?(r+=")",i-=1):p===","&&s&&i>0?r+="|":r+=jt(p)}let a=new RegExp(`^${r}$`);return Vt.set(e,a),a}function ut(e){let t=pt(String(e)),s=t.split("*")[0].split("/").filter(Boolean).length,r=t.replace(/\*/g,"").length;return s*1e4+r}function z(e,t){let n=String(e).split(/[/\\]/).join("/"),s,r=-1;for(let i of t??[])if(!(i.exclude??[]).some(a=>ee(a).test(n))){for(let a of i.patterns??[])if(ee(a).test(n)){let c=ut(a);c>r&&(r=c,s=i.name)}}return s}function Ut(e,t){if(!t?.length)return;let n=String(e).split(/[/\\]/).filter(Boolean),s=new Set(t.map(r=>String(r).toLowerCase()));for(let r=0;r<n.length-1;r+=1)if(s.has(n[r].toLowerCase()))return`${n[r].toLowerCase()}/${n[r+1].toLowerCase()}`}function Tn(e){let t=new Set;for(let n of e??[]){let r=pt(String(n)).split("/").filter(Boolean);for(let i=0;i<r.length;i+=1){let a=r[i];if((a==="**"||a==="*")&&i>0){let c=r[i-1];c&&!c.includes("*")&&!c.includes("{")&&!c.includes("}")&&t.add(c)}}}return[...t]}function Fn(e,t,n){if(Array.isArray(e.sliceFolders)&&e.sliceFolders.length>0)return e.sliceFolders.filter(r=>typeof r=="string"&&r.length>0);let s=(n??[]).find(r=>r.name===t);return Tn(s?.patterns)}function K(e,t,n,s){for(let r of e??[])if(!(r.from!==t||r.to!==n)&&r.allowed===!1){if(r.peerIsolation){let i=s?.fromPath,a=s?.toPath;if(!i||!a)return r;let c=Fn(r,t,s?.layers);if(c.length===0)return r;let p=Ut(i,c),y=Ut(a,c);if(!p||!y||p!==y)return r;continue}if(t!==n)return r}}function ce(e,t){return t&&e.isStringLiteralLike(t)?t.text:void 0}function qt(e,t){return e.getLineAndCharacterOfPosition(t.getStart(e)).line+1}function Gt(e,t){if(e.isImportDeclaration(t)){let s=t.importClause;if(!s)return!1;if(s.isTypeOnly)return!0;let r=s.namedBindings;return!!(r&&e.isNamedImports(r)&&r.elements.length>0&&r.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(s=>s.isTypeOnly))}function zt(e,t){let n={noLib:!0,noResolve:!0,target:e.ScriptTarget.Latest},s=e.createCompilerHost(n,!0);return s.getSourceFile=r=>r===t.fileName?t:void 0,s.fileExists=r=>r===t.fileName,s.readFile=r=>r===t.fileName?t.text:void 0,e.createProgram([t.fileName],n,s).getTypeChecker()}function ft(e,t){try{return e.getSymbolAtLocation(t)}catch{return}}function yt(e,t,n,s){let r=s.parent&&e.isShorthandPropertyAssignment(s.parent)&&s.parent.name===s,i;try{i=r?t.getShorthandAssignmentValueSymbol(s.parent):ft(t,s)}catch{i=void 0}return!!i?.declarations?.some(a=>a.getSourceFile().fileName===n.fileName)}function de(e,t){let n,s=[],r=(a,c,p,y=!1)=>s.push({specifier:p,kind:c,line:qt(t,a),typeOnly:y,unresolved:p===void 0,node:a}),i=a=>{if(e.isImportDeclaration(a))r(a,"import",ce(e,a.moduleSpecifier),Gt(e,a));else if(e.isExportDeclaration(a)&&a.moduleSpecifier)r(a,"export",ce(e,a.moduleSpecifier),Gt(e,a));else if(e.isImportEqualsDeclaration(a)&&e.isExternalModuleReference(a.moduleReference))r(a,"require",ce(e,a.moduleReference.expression),a.isTypeOnly===!0);else if(e.isCallExpression(a)){let c=a.expression.kind===e.SyntaxKind.ImportKeyword,y=e.isIdentifier(a.expression)&&a.expression.text==="require"&&!yt(e,n??(n=zt(e,t)),t,a.expression);(c||y)&&r(a,y?"require":"dynamic-import",ce(e,a.arguments[0]))}e.forEachChild(a,i)};return i(t),s}function Nn(e,t){let n=[],s=t;for(;e.isPropertyAccessExpression(s)||e.isElementAccessExpression(s);){if(e.isPropertyAccessExpression(s))n.unshift(s.name.text);else{let r=ce(e,s.argumentExpression);if(r===void 0)return;n.unshift(r)}s=s.expression}if(e.isIdentifier(s))return n.unshift(s.text),{root:s,segments:n}}function Dn(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 Bt(e,t){let n=t[0]==="globalThis"?t.slice(1):t;for(let s=n.length;s>=1;s-=1){let r=n.slice(0,s).join(".");if(e.has(r))return r}}function pe(e,t,n){if(n.length===0)return[];let s=new Set(n),r=zt(e,t),i=new Map,a=new Set;for(let o of t.statements)if(e.isVariableStatement(o))for(let l of o.declarationList.declarations)e.isIdentifier(l.name)&&a.add(l.name.text);let c=o=>{let l=Nn(e,o);if(!l)return;let g=ft(r,l.root),u=g?i.get(g):void 0;return u?[...u,...l.segments.slice(1)]:yt(e,r,t,l.root)||a.has(l.root.text)?void 0:l.segments};for(let o of t.statements)if(e.isVariableStatement(o))for(let l of o.declarationList.declarations){if(!l.initializer||!e.isIdentifier(l.name))continue;let g=c(l.initializer),u=ft(r,l.name);!g||!u||i.set(u,g)}let p=[],y=new Set,h=(o,l)=>{let g=qt(t,l),u=`${o}:${l.getStart(t)}`;y.has(u)||(y.add(u),p.push({name:o,line:g,node:l}))},m=o=>{let l=o.parent&&(e.isPropertyAccessExpression(o.parent)||e.isElementAccessExpression(o.parent))&&o.parent.expression===o;if((e.isPropertyAccessExpression(o)||e.isElementAccessExpression(o))&&!l){let g=c(o),u=g?Bt(s,g):void 0;u&&h(u,o)}else e.isIdentifier(o)&&s.has(o.text)&&Dn(e,o)&&!yt(e,r,t,o)&&h(o.text,o);if(e.isVariableDeclaration(o)&&e.isObjectBindingPattern(o.name)&&o.initializer){let g=c(o.initializer);if(g)for(let u of o.name.elements){if(!e.isIdentifier(u.name))continue;let b=u.propertyName?ce(e,u.propertyName)??u.propertyName.text:u.name.text,v=Bt(s,[...g,b]);v&&h(v,o.initializer)}}e.forEachChild(o,m)};return m(t),p}function mt(e,t,n){let s=[];for(let r of n?.dependencies??de(e,t)){if(r.typeOnly||!r.specifier)continue;let i=Ie(r.specifier);i&&s.push({capability:i,symbol:r.specifier,line:r.line,source:"import-based"})}for(let r of n?.ambientUses??pe(e,t,dt)){let i=He(r.name);i&&s.push({capability:i,symbol:r.name,line:r.line,source:"ambient-global"})}return s.sort((r,i)=>r.line-i.line||r.capability.localeCompare(i.capability)||r.symbol.localeCompare(i.symbol))}var gt={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."},ht=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 At(e,t){return t.flatMap((s,r)=>(s.prefixes??s.intentPrefixes??[]).map(i=>({layer:s.name,layerIndex:r,prefix:i.endsWith(".")?i:`${i}.`}))).filter(({prefix:s})=>e.startsWith(s)).sort((s,r)=>r.prefix.length-s.prefix.length||s.layerIndex-r.layerIndex)[0]?.layer}function te(e){return/^(Domain|Application|Adapter|Workflow|Job|Presentation|Reporting|Metadata|Security|Audit|Observability|Kernel)\.[A-Za-z0-9_.]+$/.test(e)}function Ee(e){if(!e.publishCall)return[];let t=[];return(e.rawIntentName!==void 0&&te(e.rawIntentName)||e.objectHasIntent)&&t.push({ruleId:"RAW_EVENT_PUBLISH",message:gt.RAW_EVENT_PUBLISH}),e.arkPublishCandidate&&!e.hasSource&&t.push({ruleId:"PUBLISH_MISSING_SOURCE",message:gt.PUBLISH_MISSING_SOURCE}),t}function x(e,t,n){return{ruleId:e,code:e,message:t,...n}}function ue(e,t){return e.slice(0,t).split(`
2
2
  `).length}function Mn(e){let t=[],n=/['"`]([A-Za-z][A-Za-z0-9_.]*)['"`]/g,s;for(;(s=n.exec(e))!==null;)t.push({value:s[1],index:s.index});return t}function Hn(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 s of n){let r;for(;(r=s.re.exec(e))!==null;){let i=r.index+r[0].indexOf(r[1]),a=r[0],c=s.kind==="import"&&/\bimport\s+type\b/.test(a)||s.kind==="export"&&/\bexport\s+type\b/.test(a);t.push({value:r[1],index:i,kind:s.kind,typeOnly:c})}}return t.sort((s,r)=>s.index-r.index)}function Vn(e,t){let n=e.createSourceFile("generated.ts",t,e.ScriptTarget.Latest,!0),s=[],r=i=>{e.isStringLiteralLike(i)&&s.push({value:i.text,index:i.getStart(n)}),e.forEachChild(i,r)};return r(n),s}function jn(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 Un(e){let t=e.toLowerCase();return["sequelize","prisma","typeorm","mongoose","knex"].some(n=>t===n||t.startsWith(`${n}/`))}function Gn(e){let t=e.toLowerCase();return["adapter","infra","persistence","repository","repositories","integration","database"].some(n=>t.includes(n))}function ke(e,t){return t&&e.isStringLiteralLike(t)?t.text:void 0}function Bn(e,t){if(t&&(e.isIdentifier(t)||e.isStringLiteralLike(t)))return t.text}function Kt(e,t,n){if(!(!t||!e.isObjectLiteralExpression(t)))return t.properties.find(s=>!e.isPropertyAssignment(s)&&!e.isShorthandPropertyAssignment(s)?!1:Bn(e,s.name)===n)}function xe(e,t,n){return Kt(e,t,n)!==void 0}function Se(e,t,n){let s=Kt(e,t,n);return s&&e.isPropertyAssignment(s)?s.initializer:void 0}function qn(e,t){let n=Se(e,t,"metadata");return xe(e,n,"source")}function Yt(e,t){return t?e.isIdentifier(t)?/^[A-Z]/.test(t.text):e.isPropertyAccessExpression(t)?Yt(e,t.name):!1:!1}function zn(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 Kn(e,t){if(!e.isCallExpression(t))return!1;let n=t.arguments[0],s=ke(e,n);return s!==void 0&&te(s)||xe(e,n,"intent")||Yt(e,n)}function Yn(e,t){if(!e.isCallExpression(t))return!1;let[n,s,r]=t.arguments;return qn(e,n)||xe(e,s,"source")||xe(e,r,"source")}function Wn(e,t){if(!e.isCallExpression(t))return;let[n,s,r]=t.arguments,i=Se(e,n,"metadata");return ke(e,Se(e,i,"source"))??ke(e,Se(e,s,"source"))??ke(e,Se(e,r,"source"))}function Jn(e,t,n,s){let r=e.createSourceFile("generated.ts",t,e.ScriptTarget.Latest,!0),i=n,a=i?.filePath,c=i?.layer,p=[],y=m=>r.getLineAndCharacterOfPosition(m.getStart(r)).line+1,h=m=>{if(zn(e,m)){let o=m.arguments[0],l=ke(e,o);for(let u of Ee({publishCall:!0,rawIntentName:l,objectHasIntent:xe(e,o,"intent"),arkPublishCandidate:Kn(e,m),hasSource:Yn(e,m)}))p.push(x(u.ruleId,u.message,{line:y(m),filePath:a}));let g=Wn(e,m);if(s&&c&&g&&te(g)){let u=s.resolveLayer(g);u&&u!==c&&p.push(x("PUBLISH_SOURCE_LAYER_MISMATCH",`Publish source "${g}" resolves to ${u}, but the target file is classified as ${c}.`,{line:y(m),filePath:a,target:g,fromLayer:c,toLayer:u}))}}e.forEachChild(m,h)};return h(r),p}function Wt(e={}){let t=new Set((e.intents||[]).map(i=>typeof i=="string"?i:i.name)),n=e.forbiddenPatterns||[],s=new Set(e.infrastructureLayers??[]),r=e.enforceIntentAllowlist??t.size>0;return{validate(i,a){let c=[],p=a,y=p?.filePath,h=p?.layer,m=e.typescript,o=m?m.createSourceFile(y??"generated.ts",i,m.ScriptTarget.Latest,!0):void 0,l=o?de(e.typescript,o):void 0,g=l?l.filter(d=>d.specifier!==void 0).map(d=>({value:d.specifier,index:d.node.getStart(o),kind:d.kind,typeOnly:d.typeOnly})):Hn(i),u=e.typescript?Vn(e.typescript,i):Mn(i);if(e.typescript&&!e.allowNonLiteralDynamicImport?.(y))for(let d of l?.filter(({unresolved:f})=>f)??[]){let f=d.kind==="require";c.push(x(f?"DYNAMIC_REQUIRE_NOT_ALLOWLISTED":"DYNAMIC_IMPORT_NOT_ALLOWLISTED",`Non-literal ${f?"require call":"dynamic import"} cannot be resolved statically; add the reviewed file to dynamicImportAllowlist.`,{line:d.line,filePath:y}))}let b=h!==void 0&&(s.has(h)||Gn(h)),v=h!==void 0?` If "${h}" 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 d of n)if(d instanceof RegExp){d.lastIndex=0;let f=d.exec(i);d.lastIndex=0,f&&c.push(x("FORBIDDEN_PATTERN",`Forbidden pattern matched: ${d}`,{line:f.index===void 0?void 0:ue(i,f.index),filePath:y,suggestion:"Remove infrastructure imports from domain/application layers."+v}))}else i.includes(d)&&c.push(x("FORBIDDEN_SUBSTRING",`Forbidden substring: ${d}`,{line:ue(i,i.indexOf(d)),filePath:y}));for(let d of g){let f=e.resolveImportTarget?.(d.value,y)??(e.resolveImportLayer?{layer:e.resolveImportLayer(d.value,y)}:void 0),R=typeof y=="string"?e.resolveImportTarget?.(y)??(e.resolveImportLayer?{layer:h,relPath:void 0}:void 0):void 0,E=f?.layer;if(E&&h){let O=K(e.architectureProfile?.rules,h,E,{fromPath:R?.relPath,toPath:f?.relPath,layers:e.architectureLayers});if(O){if(d.typeOnly&&!O.peerIsolation)continue;let L=!!O.peerIsolation;c.push(x("LAYER_IMPORT_VIOLATION",O.message??(L?`Layer "${h}" must not import across slices into "${E}".`:`Layer "${h}" must not import "${E}".`),{line:ue(i,d.index),source:d.value,target:d.value,filePath:y,fromLayer:h,toLayer:E,suggestion:L?"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:d.kind,peerIsolation:L,...d.typeOnly?{typeOnly:!0}:{}}}));continue}continue}b||d.typeOnly||!jn(d.value)&&!Un(d.value)||c.push(x("FORBIDDEN_IMPORT",`Forbidden ${d.kind} target: "${d.value}".`,{line:ue(i,d.index),source:d.value,target:d.value,filePath:y,suggestion:"Route infrastructure access through an allowed adapter or port boundary."+v,details:{importKind:d.kind}}))}if(e.policies)for(let d of e.policies){let f=d.check({source:i,context:a});if(f!==!0)if(Array.isArray(f))for(let R of f)c.push(x("POLICY_VIOLATION",R.message,{filePath:y,suggestion:`Fix violation of policy "${d.name}".`}));else f===!1?c.push(x("POLICY_VIOLATION",`Policy ${d.name} failed on generated code`)):c.push(x("POLICY_VIOLATION",f.message))}if(r&&t.size>0)for(let d of u)te(d.value)&&!t.has(d.value)&&c.push(x("UNKNOWN_INTENT",`Unknown intent reference: "${d.value}"`,{line:ue(i,d.index),filePath:y,target:d.value,suggestion:`Register intent "${d.value}" via defineIntent() or remove the reference.`}));if(e.architectureProfile&&h)for(let d of u){if(!te(d.value))continue;let f=e.architectureProfile.resolveLayer(d.value);if(!f)continue;let R=K(e.architectureProfile.rules,h,f);R&&c.push(x("LAYER_REFERENCE_VIOLATION",R.message??`Layer "${h}" must not reference "${f}" through "${d.value}".`,{line:ue(i,d.index),filePath:y,target:d.value,fromLayer:h,toLayer:f,suggestion:"Route the dependency through an allowed intent, port, or event.",details:{rule:R}}))}if(e.extensions)for(let d of e.extensions)try{let f=d.analyze(i,a);c.push(...f)}catch(f){c.push(x("EXTENSION_ERROR",`Extension "${d.name}" failed: ${f instanceof Error?f.message:String(f)}`))}if(e.typescript&&o&&h&&e.forbiddenGlobals?.[h]?.length)try{let d=e.forbiddenGlobals[h];c.push(...pe(e.typescript,o,d).map(f=>x("FORBIDDEN_GLOBAL",`${h} must not use the ambient global "${f.name}".`,{line:f.line,filePath:y,target:f.name,fromLayer:h,suggestion:"Inject the capability through a port (e.g. a Clock, IdGenerator, or HttpPort) instead of reaching for the ambient global."})));for(let f of l??[]){if(f.typeOnly||!f.specifier)continue;let R=J(f.specifier,d);R&&c.push(x("FORBIDDEN_GLOBAL",`${h} must not use module "${f.specifier}" because it is the import form of forbidden global "${R}".`,{line:f.line,filePath:y,source:f.specifier,target:f.specifier,fromLayer:h,details:{importKind:f.kind,forbiddenGlobal:R},suggestion:"Inject the capability through a port instead of importing the ambient global module form."}))}}catch(d){c.push(x("AST_ANALYZER_ERROR",`TypeScript AST analyzer failed: ${d instanceof Error?d.message:String(d)}`))}if(e.typescript&&o&&h&&e.capabilityWalls?.[h]?.length)try{let d=new Set(e.capabilityWalls[h]),f=e.forbiddenGlobals?.[h]??[];for(let R of mt(e.typescript,o))d.has(R.capability)&&(R.source==="ambient-global"&&Ce(R.symbol,f)||R.source==="import-based"&&J(R.symbol,f)||c.push(x("CAPABILITY_VIOLATION",R.source==="import-based"?`${h} denies the ${R.capability} capability; found import of "${R.symbol}".`:`${h} denies the ${R.capability} capability; found ambient "${R.symbol}".`,{line:R.line,filePath:y,target:R.symbol,capability:R.capability,fromLayer:h,suggestion:"Define a small port (ClockPort, HttpPort, StoragePort) and bind the implementation in an adapter layer."})))}catch(d){c.push(x("AST_ANALYZER_ERROR",`TypeScript AST analyzer failed: ${d instanceof Error?d.message:String(d)}`))}if(e.typescript)try{c.push(...Jn(e.typescript,i,a,e.architectureProfile))}catch(d){c.push(x("AST_ANALYZER_ERROR",`TypeScript AST analyzer failed: ${d instanceof Error?d.message:String(d)}`))}return{mode:"lexical-compatibility",completeness:"partial",completenessReasons:["LEXICAL_EVIDENCE_INCOMPLETE"],valid:!1,lexicalValid:c.length===0,violations:c}}}}var Zn="1.1",Ue="https://unpkg.com/arkgate@2/schemas/ark.config.schema.json",Jt=["DomainModel","ApplicationOrchestration","PersistenceAdapters","IntegrationAdapters","WorkflowSagaEngine","BackgroundJobsScheduling","PresentationAdapters","ReportingReadModels","ExtensibilityMetadata","SecurityAuditObservability","Kernel"],Xn=new Set(["PresentationAdapters->ApplicationOrchestration","ApplicationOrchestration->DomainModel","WorkflowSagaEngine->ApplicationOrchestration","WorkflowSagaEngine->DomainModel","BackgroundJobsScheduling->ApplicationOrchestration"]);function Qn(){let e=[];for(let t of Jt)for(let n of Jt)t===n||Xn.has(`${t}->${n}`)||e.push({from:t,to:n,allowed:!1});return e}var Ge=Qn(),bt=[{from:"unversioned",to:"1.0"},{from:"1.0",to:"1.1"}],Z={type:"array",items:{type:"string",minLength:1},uniqueItems:!0},Rt={$schema:"https://json-schema.org/draft/2020-12/schema",$id:Ue,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:Ue,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:{...Z,minItems:1,default:["src"]},exclude:{...Z,default:[]},excludeGenerated:{type:"boolean",default:!0},frameworkOverlay:{type:"string",minLength:1},layers:{type:"array",default:[],items:{$ref:"#/$defs/layer"}},rules:{type:"array",default:Ge,items:{$ref:"#/$defs/rule"}},cyclePolicy:{type:"string",enum:["strict","soft","framework-soft","off"],default:"strict"},dynamicImportAllowlist:{...Z,default:[]},safety:{$ref:"#/$defs/safety",default:{maxTsSuppressions:0,maxAnyCasts:0,allowInMemory:!1,allowDisabledPeerIsolation:!1}},arkRules:{type:"object",additionalProperties:{type:"string",minLength:1},default:{}}},$defs:{layer:{type:"object",additionalProperties:!1,required:["name","patterns"],properties:{name:{type:"string",minLength:1},patterns:{...Z,minItems:1},exclude:Z,intentPrefixes:Z,description:{type:"string",minLength:1},forbiddenGlobals:Z,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:{...Z,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}}}}},Y=class extends Error{issues;source;constructor(t,n){super(`Invalid ArkGate config (${t}):
3
3
  ${n.map(s=>`- ${s.path}: ${s.message}`).join(`
4
4
  `)}`),this.name="ArkConfigValidationError",this.source=t,this.issues=n}};function Zt(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function je(e,t){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)?`${e}.${t}`:`${e}[${JSON.stringify(t)}]`}function fe(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function er(e,t){let n="#/$defs/";if(e.startsWith(n))return t.$defs[e.slice(n.length)]}function we(e,t,n,s,r){if(t.$ref){let i=er(t.$ref,s);if(!i){r.push({path:n,message:`schema reference ${t.$ref} cannot be resolved`});return}we(e,i,n,s,r);return}if(t.const!==void 0&&!Object.is(e,t.const)){r.push({path:n,message:`must equal ${JSON.stringify(t.const)}`});return}if(t.enum&&!t.enum.some(i=>Object.is(i,e))){r.push({path:n,message:`must be one of ${t.enum.map(String).join(", ")}`});return}if(t.type==="object"){if(!Zt(e)){r.push({path:n,message:`must be an object; received ${fe(e)}`});return}let i=t.properties??{};for(let a of t.required??[])e[a]===void 0&&r.push({path:je(n,a),message:"is required"});if(t.additionalProperties===!1)for(let a of Object.keys(e))a in i||r.push({path:je(n,a),message:"unknown field"});else if(t.additionalProperties!==void 0&&t.additionalProperties!==!0&&typeof t.additionalProperties=="object"){let a=t.additionalProperties;for(let c of Object.keys(e))c in i||we(e[c],a,je(n,c),s,r)}for(let[a,c]of Object.entries(i))e[a]!==void 0&&we(e[a],c,je(n,a),s,r);return}if(t.type==="array"){if(!Array.isArray(e)){r.push({path:n,message:`must be an array; received ${fe(e)}`});return}if(t.minItems!==void 0&&e.length<t.minItems&&r.push({path:n,message:`must contain at least ${t.minItems} item(s)`}),t.uniqueItems){let i=e.map(a=>JSON.stringify(a));new Set(i).size!==i.length&&r.push({path:n,message:"must not contain duplicate items"})}t.items&&e.forEach((i,a)=>we(i,t.items,`${n}[${a}]`,s,r));return}if(t.type==="string"){if(typeof e!="string"){r.push({path:n,message:`must be a string; received ${fe(e)}`});return}t.minLength!==void 0&&e.length<t.minLength&&r.push({path:n,message:`must contain at least ${t.minLength} character(s)`});return}if(t.type==="boolean"){typeof e!="boolean"&&r.push({path:n,message:`must be a boolean; received ${fe(e)}`});return}if(t.type==="integer"){if(!Number.isInteger(e)){r.push({path:n,message:`must be an integer; received ${fe(e)}`});return}t.minimum!==void 0&&e<t.minimum&&r.push({path:n,message:`must be at least ${t.minimum}`})}}function tr(e){return{...e,$schema:e.$schema===void 0?Ue: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?Ge.map(t=>({...t})):e.rules}}function nr(){let e=new Set(["1.1"]);for(let t of bt)t.from!=="unversioned"&&e.add(t.from),e.add(t.to);return e}function rr(e,t="ark.config.json"){if(!Zt(e))throw new Y(t,[{path:"$",message:`must be an object; received ${fe(e)}`}]);let n=nr(),s=e.schemaVersion===void 0?"unversioned":typeof e.schemaVersion=="string"?e.schemaVersion:null;if(s===null)throw new Y(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(e.schemaVersion)}; expected 1.1`}]);if(s!=="unversioned"&&!n.has(s))throw new Y(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(s)}; expected 1.1`}]);let r=s,i={...e},a=0;for(;r!=="1.1"&&a<bt.length+1;){a+=1;let p=bt.find(y=>y.from===r);if(!p)throw new Y(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(r)}; expected 1.1`}]);r=p.to,i.schemaVersion=r}if(r!=="1.1")throw new Y(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(s)}; expected 1.1`}]);let c=s==="unversioned"?"unversioned":s==="1.0"?"1.0":null;return{candidate:tr(i),migratedFrom:c}}function Be(e,t="ark.config.json"){let{candidate:n,migratedFrom:s}=rr(e,t),r=[];if(we(n,Rt,"$",Rt,r),r.length>0)throw new Y(t,r);return{config:n,migratedFrom:s}}function vt(e,t="ark.config.json"){let n;try{n=JSON.parse(e)}catch(s){throw new Y(t,[{path:"$",message:`invalid JSON: ${s instanceof Error?s.message:String(s)}`}])}return Be(n,t)}function Xt(e){let t={$schema:typeof e.$schema=="string"&&e.$schema.length>0?e.$schema:Ue,schemaVersion:"1.1"};for(let[n,s]of Object.entries(e))n!=="$schema"&&n!=="schemaVersion"&&(t[n]=s);return t}function sr(e){return e.endsWith(".")?e:`${e}.`}function ir(e,t){let n=e.prefixes.length?Math.max(...e.prefixes.map(r=>r.length)):0;return(t.prefixes.length?Math.max(...t.prefixes.map(r=>r.length)):0)-n}function ze(e){let t=e.layers.map(r=>({...r,prefixes:r.prefixes.map(sr)})),n=[...t].sort(ir),s=[...e.rules??[]];return{name:e.name,layers:t,rules:s,resolveLayer(r){return t.find(i=>i.match?.(r))?.name??n.find(i=>i.prefixes.some(a=>r.startsWith(a)))?.name}}}function Qt(e,t={}){return ze({name:t.name??e.name??"ark.config.json",layers:e.layers.map((n,s)=>({name:n.name,prefixes:n.intentPrefixes??[],description:n.description,order:s+1})),rules:e.rules??[]})}var ar=[{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}],qe=ze({name:"Ark 11-layer Hexagonal Event-Driven Profile",layers:ar,rules:Ge.map(e=>({...e}))}),or={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 en(e={}){let t=e.rootDir??"src",n=e.optionalLayers??!0,s=t==="."?"":`${t}/`;return Xt({include:e.include??[t],layers:qe.layers.map(r=>({name:r.name,patterns:(or[r.name]??[r.name]).map(i=>`${s}${i}/**`),intentPrefixes:r.prefixes,optional:n})),rules:[...qe.rules]})}function w(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 k(e){if(e===null||typeof e!="object")return JSON.stringify(e);if(Array.isArray(e))return`[${e.map(k).join(",")}]`;let t=e;return`{${Object.keys(t).sort().map(n=>`${JSON.stringify(n)}:${k(t[n])}`).join(",")}}`}var ne="1.1";var tn=["network","filesystem","clock","randomness","environment","process","persistence"];function W(e,t){let n=k(e),s=k(t);return n<s?-1:n>s?1:0}function B(e){return[...new Set(e)].sort((t,n)=>t<n?-1:t>n?1:0)}function $e(e){let t={schemaVersion:"1.1",include:B(e.include??[]),exclude:B(e.exclude??[]),excludeGenerated:e.excludeGenerated!==!1,dynamicImportAllowlist:B(e.dynamicImportAllowlist??[]),layers:e.layers.map(n=>({name:n.name,patterns:B(n.patterns??[]),exclude:B(n.exclude??[]),forbiddenGlobals:B(n.forbiddenGlobals??[]),intentPrefixes:B(n.intentPrefixes??[]),capabilityDeny:B(n.capabilities?.deny??[]),pure:n.pure===!0})).sort(W),safety:{maxTsSuppressions:e.safety?.maxTsSuppressions??0,maxAnyCasts:e.safety?.maxAnyCasts??0,allowInMemory:e.safety?.allowInMemory===!0,allowDisabledPeerIsolation:e.safety?.allowDisabledPeerIsolation===!0}};return w(k(t))}function lr(e){let t=e.completenessReasons.map(o=>({code:o.code,message:o.message,...o.file?{file:o.file}:{}})).sort(W),n=e.files.map(o=>({...o,typeOnlyExportNames:B(o.typeOnlyExportNames)})).sort((o,l)=>o.path<l.path?-1:o.path>l.path?1:0),s=e.dependencies.map(o=>({...o,...o.namedBindings?{namedBindings:B(o.namedBindings)}:{}})).sort(W),r=e.capabilityUses.map(o=>({...o})).sort(W),i=e.ambientUses.map(o=>({...o})).sort(W),a=e.publishCalls.map(o=>({...o})).sort(W),c=e.intentReferences.map(o=>({...o})).sort(W),p=e.safetyUses.map(o=>({...o})).sort(W),y=(e.classShapes??[]).map(o=>({...o,mutatingMethods:[...o.mutatingMethods??[]].map(l=>({...l}))})).sort(W),h=e.files.map(({path:o,contentHash:l})=>({path:o,contentHash:l})).sort((o,l)=>o.path<l.path?-1:o.path>l.path?1:0),m=w(k(h));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:s,capabilityUses:r,ambientUses:i,publishCalls:a,intentReferences:c,safetyUses:p,classShapes:y}}function rn(e){let t=lr(e);return{...t,factsHash:w(k(t))}}function It(e){return rn(an(D(e,"$"),!1))}function D(e,t){if(!e||typeof e!="object"||Array.isArray(e))throw new Error(`${t} must be an object.`);return e}function V(e,t,n){let s=new Set(t),r=Object.keys(e).find(i=>!s.has(i));if(r)throw new Error(`${n}.${r} is not part of schema ${"1.1"}.`)}function P(e,t,n){let s=e[t];if(typeof s!="string"||s.length===0)throw new Error(`${n}.${t} must be a non-empty string.`);return s}function ye(e,t,n){if(e[t]!==void 0)return P(e,t,n)}function U(e,t,n){let s=P(e,t,n),r=s.replace(/\\/g,"/");if(!r||r.startsWith("/")||/^[A-Za-z]:\//.test(r)||/[\u0000-\u001f\u007f]/.test(r))throw new Error(`${n}.${t} must be a canonical project-relative path.`);let i=[];for(let c of r.split("/"))if(!(!c||c==="."))if(c===".."){if(i.length===0)throw new Error(`${n}.${t} must be a canonical project-relative path.`);i.pop()}else i.push(c);let a=i.join("/");if(!a||a!==s)throw new Error(`${n}.${t} must be a canonical project-relative path.`);return a}function $(e,t,n){if(typeof e[t]!="boolean")throw new Error(`${n}.${t} must be a boolean.`);return e[t]}function sn(e,t,n){let s=e[t];if(!Number.isInteger(s)||Number(s)<0)throw new Error(`${n}.${t} must be a non-negative integer.`);return Number(s)}function me(e,t,n){let s=sn(e,t,n);if(s===0)throw new Error(`${n}.${t} must be a positive integer.`);return s}function G(e,t,n){let s=e[t];if(!Array.isArray(s))throw new Error(`${n}.${t} must be an array.`);return s}function X(e,t,n,s){let r=e[t];if(typeof r!="string"||!n.includes(r))throw new Error(`${s}.${t} must be one of ${n.join(", ")}.`);return r}function nn(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 cr(e,t,n){let s=new Set;for(let r of e){let i=t(r);if(s.has(i))throw new Error(`${n} must not contain duplicate facts (${i}).`);s.add(i)}}function an(e,t){V(e,["schemaVersion","completeness","completenessReasons","resolverIdentity","compilerIdentity","compilerOptionsHash","tsconfigHash","evidenceRequirementsHash","projectPackageName","files","dependencies","capabilityUses","ambientUses","publishCalls","intentReferences","safetyUses","classShapes",...t?["candidateTreeHash","factsHash"]:[]],"$");let n=X(e,"schemaVersion",["1.0","1.1"],"$"),s=X(e,"completeness",["complete","partial","unavailable"],"$"),r=G(e,"completenessReasons","$").map((b,v)=>{let d=`$.completenessReasons[${v}]`,f=D(b,d);V(f,["code","message","file"],d);let R=f.file===void 0?void 0:U(f,"file",d);return{code:P(f,"code",d),message:P(f,"message",d),...R?{file:R}:{}}});if(s==="complete"&&r.length>0)throw new Error("$.completenessReasons must be empty when completeness is complete.");if(s!=="complete"&&r.length===0)throw new Error("$.completenessReasons must explain partial or unavailable facts.");let i=G(e,"files","$").map((b,v)=>{let d=`$.files[${v}]`,f=D(b,d);return V(f,["path","contentHash","parseStatus","parseDiagnosticCount","exportsOnlyTypes","typeOnlyExportNames","hasTopLevelSideEffects"],d),{path:U(f,"path",d),contentHash:P(f,"contentHash",d),parseStatus:X(f,"parseStatus",["parsed","invalid"],d),parseDiagnosticCount:sn(f,"parseDiagnosticCount",d),exportsOnlyTypes:$(f,"exportsOnlyTypes",d),typeOnlyExportNames:nn(f.typeOnlyExportNames,`${d}.typeOnlyExportNames`),hasTopLevelSideEffects:$(f,"hasTopLevelSideEffects",d)}}),a=G(e,"dependencies","$").map((b,v)=>{let d=`$.dependencies[${v}]`,f=D(b,d);V(f,["from","specifier","kind","typeOnly","line","resolution","target","namedBindings","targetTypeOnlyExports","sourcePureTypeModule","namedBindingsTypeOnly","portProofEligible"],d);let R=ye(f,"specifier",d),E=ye(f,"target",d),O=X(f,"resolution",["resolved-project","resolved-external","unresolved","dynamic"],d);if(O==="resolved-project"&&!E)throw new Error(`${d}.target is required for resolved-project dependencies.`);if(O!=="resolved-project"&&E)throw new Error(`${d}.target is only allowed for resolved-project dependencies.`);if(O!=="dynamic"&&!R)throw new Error(`${d}.specifier is required unless resolution is dynamic.`);return{from:U(f,"from",d),...R?{specifier:R}:{},kind:X(f,"kind",["import","export","dynamic-import","require"],d),typeOnly:$(f,"typeOnly",d),line:me(f,"line",d),resolution:O,...E?{target:U(f,"target",d)}:{},...f.namedBindings!==void 0?{namedBindings:nn(f.namedBindings,`${d}.namedBindings`)}:{},...f.targetTypeOnlyExports!==void 0?{targetTypeOnlyExports:$(f,"targetTypeOnlyExports",d)}:{},...f.sourcePureTypeModule!==void 0?{sourcePureTypeModule:$(f,"sourcePureTypeModule",d)}:{},...f.namedBindingsTypeOnly!==void 0?{namedBindingsTypeOnly:$(f,"namedBindingsTypeOnly",d)}:{},...f.portProofEligible!==void 0?{portProofEligible:$(f,"portProofEligible",d)}:{}}}),c=G(e,"capabilityUses","$").map((b,v)=>{let d=`$.capabilityUses[${v}]`,f=D(b,d);return V(f,["file","line","symbol","capability","source"],d),{file:U(f,"file",d),line:me(f,"line",d),symbol:P(f,"symbol",d),capability:X(f,"capability",tn,d),source:X(f,"source",["ambient-global","import-based"],d)}}),p=G(e,"ambientUses","$").map((b,v)=>{let d=`$.ambientUses[${v}]`,f=D(b,d);return V(f,["file","line","symbol"],d),{file:U(f,"file",d),line:me(f,"line",d),symbol:P(f,"symbol",d)}}),y=G(e,"publishCalls","$").map((b,v)=>{let d=`$.publishCalls[${v}]`,f=D(b,d);V(f,["file","line","rawIntentName","objectHasIntent","arkPublishCandidate","hasSource","sourceIntent"],d);let R=ye(f,"rawIntentName",d),E=ye(f,"sourceIntent",d);return{file:U(f,"file",d),line:me(f,"line",d),...R?{rawIntentName:R}:{},objectHasIntent:$(f,"objectHasIntent",d),arkPublishCandidate:$(f,"arkPublishCandidate",d),hasSource:$(f,"hasSource",d),...E?{sourceIntent:E}:{}}}),h=G(e,"intentReferences","$").map((b,v)=>{let d=`$.intentReferences[${v}]`,f=D(b,d);return V(f,["file","line","intent"],d),{file:U(f,"file",d),line:me(f,"line",d),intent:P(f,"intent",d)}}),m=G(e,"safetyUses","$").map((b,v)=>{let d=`$.safetyUses[${v}]`,f=D(b,d);V(f,["file","line","kind","symbol"],d);let R=ye(f,"symbol",d),E=X(f,"kind",["ts-suppression","any-cast","dynamic-import","dynamic-require","in-memory-store"],d);if(E==="in-memory-store"&&!R)throw new Error(`${d}.symbol is required for in-memory-store facts.`);if(E!=="in-memory-store"&&R)throw new Error(`${d}.symbol is only allowed for in-memory-store facts.`);return{file:U(f,"file",d),line:me(f,"line",d),kind:E,...R?{symbol:R}:{}}});cr(i,b=>b.path,"$.files");let o=new Set(i.map(b=>b.path));for(let b of i){if(b.parseStatus==="parsed"&&b.parseDiagnosticCount!==0)throw new Error(`$.files[${b.path}].parseDiagnosticCount must be 0 when parseStatus is parsed.`);if(b.parseStatus==="invalid"&&b.parseDiagnosticCount===0)throw new Error(`$.files[${b.path}].parseDiagnosticCount must be positive when parseStatus is invalid.`)}if(s==="complete"&&i.some(b=>b.parseStatus==="invalid"))throw new Error("$.completeness cannot be complete when a candidate file failed to parse.");for(let b of a)if(!o.has(b.from))throw new Error(`$.dependencies references missing source file ${b.from}.`);for(let[b,v]of[["$.capabilityUses",c],["$.ambientUses",p],["$.publishCalls",y],["$.intentReferences",h],["$.safetyUses",m]])for(let d of v)if(!o.has(d.file))throw new Error(`${b} references missing file ${d.file}.`);let l=ye(e,"projectPackageName","$"),u=(e.classShapes===void 0?[]:G(e,"classShapes","$")).map((b,v)=>{let d=`$.classShapes[${v}]`,f=D(b,d);V(f,["file","className","exported","hasPublicMutableFields","hasPublicSetters","hasPublicConstructor","hasStaticFactory","mutatingMethods","dataOnly"],d);let R=G(f,"mutatingMethods",d).map((E,O)=>{let L=`${d}.mutatingMethods[${O}]`,_=D(E,L);return V(_,["name","referencesGuardOrPublish"],L),{name:P(_,"name",L),referencesGuardOrPublish:$(_,"referencesGuardOrPublish",L)}});return{file:U(f,"file",d),className:P(f,"className",d),exported:$(f,"exported",d),hasPublicMutableFields:$(f,"hasPublicMutableFields",d),hasPublicSetters:$(f,"hasPublicSetters",d),hasPublicConstructor:$(f,"hasPublicConstructor",d),hasStaticFactory:$(f,"hasStaticFactory",d),mutatingMethods:R,...f.dataOnly===void 0?{}:{dataOnly:$(f,"dataOnly",d)}}});return{schemaVersion:n,completeness:s,completenessReasons:r,resolverIdentity:P(e,"resolverIdentity","$"),compilerIdentity:P(e,"compilerIdentity","$"),compilerOptionsHash:P(e,"compilerOptionsHash","$"),tsconfigHash:P(e,"tsconfigHash","$"),evidenceRequirementsHash:P(e,"evidenceRequirementsHash","$"),...l?{projectPackageName:l}:{},files:i,dependencies:a,capabilityUses:c,ambientUses:p,publishCalls:y,intentReferences:h,safetyUses:m,classShapes:u}}function Q(e){let t=D(e,"$"),n=P(t,"factsHash","$"),s=P(t,"candidateTreeHash","$"),r=rn(an(t,!0));if(r.factsHash!==n)throw new Error(`$.factsHash does not match the canonical payload (${r.factsHash}).`);if(s!==r.candidateTreeHash)throw new Error(`$.candidateTreeHash does not match the canonical file tree (${r.candidateTreeHash}).`);return r}var dr=["network","filesystem","clock","randomness","environment","process","persistence"],S={type:"string",minLength:1},ge={type:"integer",minimum:1},q={type:"string",minLength:1,pattern:"^(?!/)(?![A-Za-z]:/)(?!.*\\\\)(?!.*//)(?!.*(?:^|/)\\.{1,2}(?:/|$))(?!.*[\\u0000-\\u001f\\u007f])(?!.*\\/$).+$"},Ct={$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:S,message:S,file:q}}},resolverIdentity:S,compilerIdentity:S,compilerOptionsHash:S,tsconfigHash:S,candidateTreeHash:S,evidenceRequirementsHash:S,projectPackageName:S,files:{type:"array",uniqueItems:!0,items:{type:"object",additionalProperties:!1,required:["path","contentHash","parseStatus","parseDiagnosticCount","exportsOnlyTypes","typeOnlyExportNames","hasTopLevelSideEffects"],properties:{path:q,contentHash:S,parseStatus:{enum:["parsed","invalid"]},parseDiagnosticCount:{type:"integer",minimum:0},exportsOnlyTypes:{type:"boolean"},typeOnlyExportNames:{type:"array",items:S},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:q,specifier:S,kind:{enum:["import","export","dynamic-import","require"]},typeOnly:{type:"boolean"},line:ge,resolution:{enum:["resolved-project","resolved-external","unresolved","dynamic"]},target:q,namedBindings:{type:"array",items:S},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:q,line:ge,symbol:S,capability:{enum:dr},source:{enum:["ambient-global","import-based"]}}}},ambientUses:{type:"array",items:{type:"object",additionalProperties:!1,required:["file","line","symbol"],properties:{file:q,line:ge,symbol:S}}},publishCalls:{type:"array",items:{type:"object",additionalProperties:!1,required:["file","line","objectHasIntent","arkPublishCandidate","hasSource"],properties:{file:q,line:ge,rawIntentName:S,objectHasIntent:{type:"boolean"},arkPublishCandidate:{type:"boolean"},hasSource:{type:"boolean"},sourceIntent:S}}},intentReferences:{type:"array",items:{type:"object",additionalProperties:!1,required:["file","line","intent"],properties:{file:q,line:ge,intent:S}}},safetyUses:{type:"array",items:{type:"object",additionalProperties:!1,required:["file","line","kind"],properties:{file:q,line:ge,kind:{enum:["ts-suppression","any-cast","dynamic-import","dynamic-require","in-memory-store"]},symbol:S},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:q,className:S,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:S,referencesGuardOrPublish:{type:"boolean"}}}}}}},factsHash:S},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 Et="1.0";function F(e){return`${e.from}->${e.to}`}function Pe(e,t,n,s="dependency"){return{id:`${e}:${s}:${F(t)}`,classification:e,subject:"dependency",from:t.from,to:t.to,message:n,...e==="missing"?{nextAction:`Add the planned dependency ${F(t)} to the candidate, then preflight again.`}:e==="contradictory"?{nextAction:`Replace the reverse dependency with ${F(t)}, then preflight again.`}:e==="unplanned"?{nextAction:s==="dependency-removed"?`Restore the removed dependency ${F(t)} in the candidate, then preflight again.`:`Remove the unplanned dependency ${F(t)} from the candidate, then preflight again.`}:{}}}function he(e){let t=[],n=new Map(e.changeMap.map.files.map(o=>[o.path,o])),s=new Map(e.changes.map(o=>[o.path,o])),r=new Map(e.changeMap.map.dependencies.map(o=>[F(o),o])),i=new Map(e.baseDependencies.map(o=>[F(o),o])),a=new Map(e.candidateDependencies.map(o=>[F(o),o]));for(let o of[...n.values()].sort((l,g)=>l.path.localeCompare(g.path))){let l=s.get(o.path);l?l.operation!==o.operation?t.push({id:`contradictory:file:${o.path}`,classification:"contradictory",subject:"file",path:o.path,expectedOperation:o.operation,actualOperation:l.operation,message:`${o.path} was planned as ${o.operation} but the actual operation is ${l.operation}.`,nextAction:`Change ${o.path} to the planned ${o.operation} operation, then preflight again.`}):t.push({id:`satisfied:file:${o.path}`,classification:"satisfied",subject:"file",path:o.path,expectedOperation:o.operation,actualOperation:l.operation,message:`${o.path} matches the planned ${o.operation} operation.`}):t.push({id:`missing:file:${o.path}`,classification:"missing",subject:"file",path:o.path,expectedOperation:o.operation,message:`${o.path} was planned as ${o.operation} but is absent from the actual change.`,nextAction:`${o.operation[0].toUpperCase()}${o.operation.slice(1)} ${o.path} in the complete change set, then preflight again.`})}for(let o of[...s.values()].sort((l,g)=>l.path.localeCompare(g.path)))n.has(o.path)||t.push({id:`unplanned:file:${o.path}`,classification:"unplanned",subject:"file",path:o.path,actualOperation:o.operation,message:`${o.path} has an unplanned ${o.operation} operation.`,nextAction:`Remove ${o.path} from the change set, then preflight again.`});let c=new Set;for(let o of[...r.values()].sort((l,g)=>F(l).localeCompare(F(g)))){if(a.has(F(o))){t.push(Pe("satisfied",o,`${o.from} -> ${o.to} exists in the candidate architecture.`));continue}let l={from:o.to,to:o.from};a.has(F(l))?(c.add(F(l)),t.push(Pe("contradictory",o,`${o.from} -> ${o.to} was planned, but the candidate contains the reverse edge.`))):t.push(Pe("missing",o,`${o.from} -> ${o.to} is absent from the candidate architecture.`))}let p=new Set([...n.keys(),...s.keys()]);for(let[o,l]of[...a].sort(([g],[u])=>g.localeCompare(u)))i.has(o)||r.has(o)||c.has(o)||!p.has(l.from)&&!p.has(l.to)||t.push({...Pe("unplanned",l,`${l.from} -> ${l.to} was added without a matching planned dependency.`,"dependency-added"),actualOperation:"added"});let y=new Set(e.changeMap.map.files.filter(o=>o.operation==="delete").map(o=>o.path));for(let[o,l]of[...i].sort(([g],[u])=>g.localeCompare(u)))a.has(o)||y.has(l.from)||y.has(l.to)||!p.has(l.from)&&!p.has(l.to)||t.push({...Pe("unplanned",l,`${l.from} -> ${l.to} was removed without a planned file deletion.`,"dependency-removed"),actualOperation:"removed"});let h={satisfied:0,missing:1,contradictory:2,unplanned:3};t.sort((o,l)=>h[o.classification]-h[l.classification]||(o.subject===l.subject?0:o.subject==="file"?-1:1)||o.id.localeCompare(l.id));let m={satisfied:t.filter(o=>o.classification==="satisfied").length,missing:t.filter(o=>o.classification==="missing").length,contradictory:t.filter(o=>o.classification==="contradictory").length,unplanned:t.filter(o=>o.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 pr="1.0",St="https://unpkg.com/arkgate/schemas/ark.arkrules.schema.json",cn=["aggregate-private-state","always-valid-factory","domain-event-on-mutation","orchestration-only","thin-adapter","no-anemic-model","invariant-coverage"],ur=["no-anemic-model"],on={type:"array",items:{type:"string",minLength:1},uniqueItems:!0},kt={$schema:"https://json-schema.org/draft/2020-12/schema",$id:St,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:St},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:[...cn]},mode:{type:"string",enum:["advisory","enforced"],default:"advisory"},appliesTo:on,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:on}}}},re=class extends Error{issues;source;constructor(t,n){super(`Invalid ArkRules (${t}):
package/docs/README.md CHANGED
@@ -57,8 +57,9 @@ These are **not** the day-to-day product path. They stay in the repo for evidenc
57
57
  | Field adoption kit (scaffolding, not closed) | [field/](field/) |
58
58
  | Runtime hardening (experimental) | [production-hardening.md](production-hardening.md) |
59
59
 
60
- Prepared major: [releases/4.0.0.md](releases/4.0.0.md) (`arkgate@4.0.0` — layers + optional **ArkRules**).
61
- Last npm `latest` until publish: [releases/3.9.2.md](releases/3.9.2.md) (`arkgate@3.9.2`).
60
+ Current major on npm `latest`: [releases/4.0.0.md](releases/4.0.0.md) (`arkgate@4.0.0` — layers + optional **ArkRules**).
61
+ Next prepared: [releases/4.0.1.md](releases/4.0.1.md) (`arkgate@4.0.1` — not yet `latest`).
62
+ Previous: [releases/3.9.2.md](releases/3.9.2.md) (`arkgate@3.9.2`).
62
63
  Config: [configuration.md](configuration.md) · Agent skills dual-plane: [agent-guide.md](agent-guide.md).
63
64
 
64
65
  ---
@@ -53,6 +53,8 @@ structure / invariants). Case study shape:
53
53
 
54
54
  **Upgrade note (4.0):** `ark upgrade --no-install` can refresh skills/gates while leaving
55
55
  `package.json` on an older pin—doctor exposes `packageVersionTruth` when the CLI is ahead.
56
+ Prefer project-local `npx arkgate upgrade …` over bare PATH `ark` — global **2.x** is mutative
57
+ and unsafe next to 3.8+/4.0 ([field footgun](releases/4.0.0.md#field-footgun--global-arkgate-2x-on-path)).
56
58
 
57
59
  ## 3. Make the contract real (via `/ark-contract`)
58
60
 
@@ -119,20 +119,36 @@ policy.
119
119
 
120
120
  Sibling schema export: `arkgate/schema/arkrules` (`schemas/ark.arkrules.schema.json`).
121
121
 
122
+ **Two planes (never one score):**
123
+
124
+ | Plane | Question | Where |
125
+ |-------|----------|--------|
126
+ | **[Layer]** (inter-layer) | Who may import whom? Pure / forbidden globals / capabilities? | `layers[]` + `rules[]` |
127
+ | **[ArkRules]** (intra-layer, opt-in) | How is code shaped *inside* a layer, and which named business policies are catalogued with coverage evidence? | `arkRules` map + `arkrules/<ExactLayerName>.json` |
128
+
129
+ Absence of `arkRules` is valid: only the Layers plane runs; inter-layer verdict is unchanged.
130
+
122
131
  Each `arkrules/<Layer>.json` may declare:
123
132
 
124
- | Section | Purpose | Modes |
125
- |---------|---------|--------|
126
- | `structure[]` | Closed sensor ids (e.g. `aggregate-private-state`, `always-valid-factory`, `thin-adapter`) | `advisory` (default) or `enforced` |
127
- | `invariants[]` | Stable ids + description + optional coverage (`test` / `symbol`) | `advisory` or `enforced` |
133
+ | Section | Purpose | Modes | What it really enforces |
134
+ |---------|---------|--------|-------------------------|
135
+ | `structure[]` | Closed sensor ids (e.g. `orchestration-only`, `thin-adapter`, `aggregate-private-state`, `always-valid-factory`, `domain-event-on-mutation`, `no-anemic-model`) | `advisory` (default) or `enforced` | **Heuristics of module shape** — not proof that logic was extracted to Domain. Tier-2 sensors (`no-anemic-model`) stay advisory-only (cannot promote to enforced). |
136
+ | `invariants[]` | Stable ids + description + `coverage` (`test` / `symbol`) + optional `appliesTo` globs | `advisory` or `enforced` | **Named policy + evidence** (symbol in source and/or test title/content). Does **not** execute business logic at check time and does **not** replace behavior/property tests. |
128
137
 
129
138
  **Reporting:** diagnostics carry `evidence.arkruleId` + `evidence.arkruleSource`. Label residual
130
- **`[Layer]`** (import edges / capabilities) vs **`[ArkRules]`** (structure / invariants) in agent
131
- output. Doctor JSON: `rulesUnderContract` (counts, never a score).
139
+ **`[Layer]`** vs **`[ArkRules]`** in agent output. Doctor / HTML: `rulesUnderContract` (catalog +
140
+ counts, **never a score**). Showcase HTML lists per-layer totals, structure sensors, uncovered
141
+ invariants, and a covered sample when the map is active.
132
142
 
133
143
  **Promotion:** advisory→enforced is strengthening when coverage evidence exists; demote/delete is
134
144
  a hash-bound policy weakening. Empty `appliesTo: []` fails closed; zero-match globs emit
135
- `ARKRULE_SCOPE_EMPTY` (advisory warn / enforced fail).
145
+ `ARKRULE_SCOPE_EMPTY` (advisory warn / enforced fail). Enforced + proven uncovered →
146
+ `INVARIANT_UNCOVERED` with `failsStrict` (partial evidence stays honest, never fake-green).
147
+
148
+ **What they do not do:** prove business semantics end-to-end; replace Layers import edges;
149
+ make “green” mean elegant Shape. Promoting structure to enforced can force rename-to-pass
150
+ heuristics — prefer judgment extraction via `/ark-fix` / `/ark-loop` when the real goal is
151
+ Domain ownership.
136
152
 
137
153
  ```bash
138
154
  # Brownfield candidates (not a score)
@@ -189,6 +189,7 @@ production deployment would need to satisfy; it is not a readiness certification
189
189
  ## Release notes (maintainers)
190
190
 
191
191
  Ship notes for a version live under [releases/](https://github.com/pedroknigge/arkgate/tree/main/docs/releases)
192
- (prepared: [4.0.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.0.0.md);
193
- last published: [3.9.2.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/3.9.2.md)).
192
+ (current on npm: [4.0.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.0.0.md); prepared:
193
+ [4.0.1.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.0.1.md); previous:
194
+ [3.9.2.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/3.9.2.md)).
194
195
  Publish path: signed annotated tag → GitHub Release → `publish-npm.yml` (see [CONTRIBUTING.md](https://github.com/pedroknigge/arkgate/blob/main/CONTRIBUTING.md)).
@@ -95,7 +95,9 @@ Examples:
95
95
  | “modes you pick” for Suggest/Adapt/Enforce | Those are **status lights**, not settings |
96
96
  | Skill-shopping lists as the default curriculum | Progressive disclosure: one door first |
97
97
  | “Healthy / done” while design-weak | False done |
98
- | “ArkRules prove business correctness” | They enforce *declared* structure/coverage evidence, not arbitrary logic |
98
+ | “ArkRules prove business correctness” | They enforce *declared* structure/coverage evidence, not arbitrary logic or full semantic proof |
99
+ | “Structure enforced = Domain extraction done” | Structure sensors are **heuristics**; extraction is judgment (`/ark-fix` / pilot) |
100
+ | “Covered invariant = E2E business tests” | Coverage = symbol/test evidence for a named policy, not a runtime test runner |
99
101
  | Blurring import edges with invariants | Always label **`[Layer]`** vs **`[ArkRules]`** |
100
102
 
101
103
  ---
package/docs/use.md CHANGED
@@ -40,12 +40,14 @@ ArkGate is **not** a web framework, ORM, or app runtime. It is architecture enfo
40
40
 
41
41
  ### Two planes (you choose)
42
42
 
43
- | Plane | Plain English | Config |
44
- |-------|---------------|--------|
45
- | **Layers** | Who may talk to whom (imports, purity) | `ark.config.json` layers + rules |
46
- | **ArkRules** (optional) | Habits *inside* a layer (aggregates, factories, named invariants) | `arkRules` + `arkrules/<Layer>.json` |
43
+ | Plane | Plain English | Config | Enforces |
44
+ |-------|---------------|--------|----------|
45
+ | **Layers** | Who may talk to whom | `layers[]` + `rules[]` | Import direction, purity, forbidden globals, capabilities, peer isolation |
46
+ | **ArkRules** (optional) | Habits *inside* a layer + named policies | `arkRules` + `arkrules/<Layer>.json` | Structure **heuristics** (module shape); invariant **catalog + coverage evidence** (not full business proof) |
47
47
 
48
- Start always gives you **layers**. ArkRules templates may ship with start/init; they begin **advisory** until you promote them. Doctor may show `rulesUnderContract` counts (not a score).
48
+ Start always gives you **layers**. ArkRules templates may ship with start/init; they begin **advisory** until you promote them. Doctor / HTML show `rulesUnderContract` (catalog, **not a score**). No `arkRules` map is fine — only Layers run.
49
+
50
+ **Do not confuse:** green Layers ≠ perfect design (Shape residual can remain). Covered invariants ≠ “the business always does the right thing” — they mean the named policy is declared and has symbol/test evidence.
49
51
 
50
52
  ---
51
53
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arkgate",
3
- "version": "4.0.0",
3
+ "version": "4.0.1",
4
4
  "description": "ArkGate — architecture co-pilot for AI TypeScript (write gate, CI gate, plan/loop; optional ArkRules)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/pedroknigge/arkgate",
7
7
  "source": "github"
8
8
  },
9
- "version": "4.0.0",
9
+ "version": "4.0.1",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "arkgate",
14
- "version": "4.0.0",
14
+ "version": "4.0.1",
15
15
  "runtimeHint": "npx",
16
16
  "transport": {
17
17
  "type": "stdio"
@@ -45,8 +45,20 @@ ArkGate has **two opt-in planes**. The user chooses which to use; you **always l
45
45
 
46
46
 
47
47
  ### Explain + ArkRules
48
- - HTML/plain tour: section **Layers** and section **ArkRules** (structure + invariants + residual).
49
- - Never merge them into one “architecture score.”
48
+ - HTML/plain tour: section **Layers** and section **Rules under contract (ArkRules)**
49
+ when `arkRules` is active the showcase lists **per-layer counts**, **structure sensors**
50
+ (id / sensor / mode), **uncovered** invariants (call them out), and a **covered sample**.
51
+ Inactive map stays a short opt-in note. Counts are never a score.
52
+ - Spoken tour: name 2–4 real invariant IDs and one structure sensor from this repo’s
53
+ `arkrules/*` (open the files — do not invent). Residual candidates → `--rules-inventory`.
54
+ - **Teach the product model (required when arkRules is active):**
55
+ - **[Layer]** = dependency direction / purity / capabilities.
56
+ - **[ArkRules] structure** = module-shape **heuristics** (orchestration-only, thin-adapter, …);
57
+ enforced is not proof of Domain extraction.
58
+ - **[ArkRules] invariants** = named business policies as **data + coverage evidence**
59
+ (symbol/test); not a runtime engine and not a substitute for behavior tests.
60
+ - Green edges + covered catalog ≠ elegant Shape (design-weak residual stays honest).
61
+ - Never merge Layers and ArkRules into one “architecture score.”
50
62
 
51
63
  ## Subagent fan-out (optional, host-dependent)
52
64
 
@@ -117,9 +129,10 @@ the same files or weaken the gate.
117
129
  (SUGGEST / ADAPT / ENFORCE), and the plan's safe-to-auto vs decision counts.
118
130
 
119
131
  The HTML report is the visual twin of this skill: architecture map, files per layer,
120
- dependency direction, matrix, violations, enforcement points, Ark fitness score, and a
121
- **Senior diagnostics** block (coupling fan-in/out, deny density, purity surface, pattern
122
- forensics, baseline taxonomy) for tech leads.
132
+ dependency direction, matrix, violations, **ArkRules under contract** (when mapped),
133
+ enforcement points, Ark fitness score, and a **Senior diagnostics** block (coupling
134
+ fan-in/out, deny density, purity surface, pattern forensics, baseline taxonomy) for
135
+ tech leads.
123
136
 
124
137
  When explaining the **plan**, name the four `mechanical-safe` remediation kinds only
125
138
  (type-only move, pure-type file relocate, `import type` of pure-type modules,
@@ -43,7 +43,10 @@ ArkGate has **two opt-in planes**. The user chooses which to use; you **always l
43
43
 
44
44
  ## Safety contract
45
45
 
46
- - `ark upgrade` is read-only. It reports the selected profile and hosts, every
46
+ - Always invoke the **project-local** CLI (`npx arkgate` /
47
+ `node node_modules/arkgate/bin/ark.mjs`). Bare PATH `ark` / `arkgate` is unsafe
48
+ when a global 2.x install shadows the project (mutative legacy upgrade).
49
+ - `ark upgrade` (managed era) is read-only. It reports the selected profile and hosts, every
47
50
  managed asset, its content state, and the exact next command.
48
51
  - The first `ark upgrade --apply` updates the dependency and lockfile, then runs
49
52
  the newly installed CLI to produce another read-only preview. It does **not**
@@ -72,16 +75,54 @@ ArkGate has **two opt-in planes**. The user chooses which to use; you **always l
72
75
 
73
76
  ## Procedure
74
77
 
75
- 1. **Establish versions and context.** Read the installed
78
+ 1. **Resolve the project CLI (mandatory before any upgrade command).** Prefer the
79
+ **project-local** binary — never bare `ark` / `arkgate` from PATH unless you
80
+ prove it is this project's install.
81
+
82
+ Resolution order:
83
+
84
+ 1. `node node_modules/arkgate/bin/ark.mjs` from the repository root (both `arkgate`
85
+ and `ark` package bins map to this file).
86
+ 2. Package-manager exec from the project: `npx arkgate`, `pnpm exec arkgate`,
87
+ `yarn arkgate`, etc.
88
+
89
+ **Do not** use bare `ark` / `arkgate` from PATH unless `which ark` (or the
90
+ resolved realpath) is under this project's `node_modules/arkgate`, or the
91
+ binary reports the **same** version as `node_modules/arkgate/package.json` and
92
+ supports managed upgrade.
93
+
94
+ **Capability probe (abort if missing):** run
95
+ `node node_modules/arkgate/bin/ark.mjs upgrade --help` (or the resolved local
96
+ equivalent) and require a **managed upgrade** surface — help text must mention
97
+ `--plan-digest` (and read-only `upgrade --json` preview). If the only available
98
+ CLI is old (global Homebrew / npm global 2.x, or any binary whose help lacks
99
+ `--plan-digest`), **stop**: skill incomplete; do **not** preview or apply.
100
+ Global 2.x `ark upgrade` is mutative and can rewrite managed skills, forcing a
101
+ later `--accept-conflicts` recovery.
102
+
103
+ **Recovery (preferred → optional):**
104
+
105
+ - Preferred: package-manager runner from project / `--root`
106
+ (`npx arkgate upgrade …` / `pnpm exec arkgate upgrade …` / `yarn arkgate upgrade …`).
107
+ This works when arkgate is **hoisted** and a nested package has no shallow
108
+ `node_modules/arkgate`.
109
+ - Secondary: `node node_modules/arkgate/bin/ark.mjs upgrade …` from the
110
+ **workspace install root** (not a nested package lacking a local install).
111
+ - Optional: refresh a global install with `npm i -g arkgate@latest` only if the
112
+ user wants a global binary; still prefer project-local for this procedure.
113
+
114
+ Record the resolved CLI path/version, read
76
115
  `node_modules/arkgate/package.json`, query `npm view arkgate version`, identify
77
116
  the repository package manager, and open the intervening entries in the
78
117
  shipped `CHANGELOG.md` (fall back to registry or release notes and name that
79
118
  source). Do not infer “latest” from `node_modules` alone.
80
119
 
81
- 2. **Preview managed content.** Run:
120
+ 2. **Preview managed content.** Using the **project-local** CLI from step 1
121
+ (never a bare PATH `ark` that failed the probe), run:
82
122
 
83
123
  ```bash
84
- ark upgrade --json
124
+ npx arkgate upgrade --json
125
+ # or: node node_modules/arkgate/bin/ark.mjs upgrade --json
85
126
  ```
86
127
 
87
128
  Pass `--root <path>` and `--tools <active-host>` when selection would otherwise
@@ -89,10 +130,10 @@ ArkGate has **two opt-in planes**. The user chooses which to use; you **always l
89
130
  that customized files remain non-applying and that any deletion/conflict is
90
131
  blocked.
91
132
 
92
- 3. **Update and re-preview.** If the registry is newer, run:
133
+ 3. **Update and re-preview.** If the registry is newer, run (project-local CLI):
93
134
 
94
135
  ```bash
95
- ark upgrade --apply
136
+ npx arkgate upgrade --apply
96
137
  ```
97
138
 
98
139
  This updates through the detected package manager and hands control to the new
@@ -105,20 +146,25 @@ ArkGate has **two opt-in planes**. The user chooses which to use; you **always l
105
146
  off, and prove `pnpm install --frozen-lockfile` succeeds.
106
147
 
107
148
  4. **Apply only the reviewed candidate.** When there are no blocked assets, run
108
- the preview's exact `nextCommand`, whose shape is:
149
+ the preview's **exact** `nextCommand` as emitted (JSON field / human “Apply the
150
+ exact preview with: …”). That command is already **project-local**
151
+ (`npx arkgate` / `pnpm exec arkgate` / `yarn arkgate` — never bare PATH `ark`).
152
+ Do **not** rewrite it to bare `ark upgrade`; pasting through a global 2.x PATH
153
+ reintroduces the mutative footgun. Shape:
109
154
 
110
155
  ```bash
111
- ark upgrade --apply --no-install --plan-digest <preview-digest>
156
+ npx arkgate upgrade --apply --no-install --plan-digest <preview-digest>
112
157
  ```
113
158
 
114
159
  If recorded deletion/conflict recovery is desired, ask first and then add
115
160
  `--accept-conflicts`. Never add it merely to make the run green. Run a second
116
161
  preview and require `summary.changed: 0`.
117
162
 
118
- 5. **Verify enforcement and architecture.** Run `ark-check --doctor --json` and
163
+ 5. **Verify enforcement and architecture.** Run
164
+ `npx arkgate-check --doctor --json` (or the project-local `ark-check`) and
119
165
  the same fail-closed architecture command used by managed apply (normally
120
- `ark-check --root . --config ark.config.json --strict-merge --json`). Require
121
- `completeness: "complete"` and `ok: true`. Treat provider-unavailable CI
166
+ `npx arkgate-check --root . --config ark.config.json --strict-merge --json`).
167
+ Require `completeness: "complete"` and `ok: true`. Treat provider-unavailable CI
122
168
  required-check evidence as `unverified`, never as proof that merges are
123
169
  blocked. If new violations appear, hand off to `/ark-fix` for a small set or
124
170
  `/ark-loop` / `/ark-autopilot` for residual debt; do not regenerate a baseline