Sign In

arkgate

Package Overview
Dependencies
Maintainers
1
Versions
54
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

arkgate - npm Package Compare versions

Comparing version
4.5.7
to
4.6.0
+296
bin/lib/agent-homes.mjs
/**
* Shared agent home skill catalogs (Claude / Grok), Codex-parity monotonic install.
* Repo catalogs stay per-project; these homes are the machine floor (never downgrade).
*/
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { arkCommand } from '../ark-shared.mjs';
import { isTempOrUpgradeRoot } from './codex-home.mjs';
import {
arkPackageVersion,
assessSkillCatalogParity,
detectActiveAgentHost,
isValidSemver,
isVersionOlder,
skillTemplateNames,
skillTemplates,
} from './skill-install.mjs';
import {
HOME_SKILL_CATALOG,
HOME_SKILL_PENDING_CATALOG,
installSkillCatalog,
skillInstallLine,
} from './skill-write.mjs';
/** @typedef {'claude'|'grok'} AgentHomeHost */
const HOSTS = {
claude: {
id: 'claude',
label: 'Claude',
envKey: 'CLAUDE_HOME',
defaultDirName: '.claude',
flag: '--claude-home',
},
grok: {
id: 'grok',
label: 'Grok',
envKey: 'GROK_HOME',
defaultDirName: '.grok',
flag: '--grok-home',
},
};
export function agentHomeHostIds() {
return Object.keys(HOSTS);
}
export function claudeHomeDir(env = process.env, homeDir = os.homedir()) {
return resolveHomeDir(HOSTS.claude, env, homeDir);
}
export function grokHomeDir(env = process.env, homeDir = os.homedir()) {
return resolveHomeDir(HOSTS.grok, env, homeDir);
}
export function claudeSkillsDir(env = process.env, homeDir = os.homedir()) {
return path.join(claudeHomeDir(env, homeDir), 'skills');
}
export function grokSkillsDir(env = process.env, homeDir = os.homedir()) {
return path.join(grokHomeDir(env, homeDir), 'skills');
}
export function usesDefaultClaudeHome(env = process.env, homeDir = os.homedir()) {
return usesDefaultHome(HOSTS.claude, env, homeDir);
}
export function usesDefaultGrokHome(env = process.env, homeDir = os.homedir()) {
return usesDefaultHome(HOSTS.grok, env, homeDir);
}
function resolveHomeDir(spec, env, homeDir) {
const configured = env?.[spec.envKey];
if (typeof configured === 'string' && configured.trim() !== '') {
return path.resolve(configured);
}
return path.resolve(homeDir, spec.defaultDirName);
}
function usesDefaultHome(spec, env, homeDir) {
const configured = env?.[spec.envKey];
if (typeof configured !== 'string' || configured.trim() === '') return true;
return path.resolve(configured) === path.resolve(homeDir, spec.defaultDirName);
}
function skillsDirFor(host, env = process.env) {
return host === 'grok' ? grokSkillsDir(env) : claudeSkillsDir(env);
}
function readHomeCatalogFloor(skillsDir) {
const readOne = (file) => {
try {
const value = JSON.parse(fs.readFileSync(file, 'utf8'));
const version = typeof value?.packageVersion === 'string' ? value.packageVersion : null;
const valid =
value &&
value.schemaVersion === '1.0' &&
isValidSemver(version) &&
Array.isArray(value.skills);
return { exists: true, valid, version: valid ? version : null };
} catch (error) {
if (error && error.code === 'ENOENT') return { exists: false, valid: true, version: null };
return { exists: true, valid: false, version: null };
}
};
const catalog = readOne(path.join(skillsDir, HOME_SKILL_CATALOG));
const pending = readOne(path.join(skillsDir, HOME_SKILL_PENDING_CATALOG));
let floorVersion = catalog.version;
if (pending.version && (!floorVersion || isVersionOlder(floorVersion, pending.version))) {
floorVersion = pending.version;
}
return {
floorVersion,
pendingVersion: pending.version,
hasMetadata: catalog.exists || pending.exists,
metadataInvalid:
(catalog.exists && !catalog.valid) || (pending.exists && !pending.valid),
};
}
function homeInPlay(parity, catalogState) {
return parity.presentCount > 0 || catalogState.hasMetadata;
}
/**
* Detect Claude/Grok user-home ark-* catalogs that lag this package.
* Absent homes are not debt. Stamp-only body-match is not content-behind
* (assessSkillCatalogParity already treats identity match as current).
*
* @param {string} root
* @param {NodeJS.ProcessEnv} [env]
* @returns {Array<{
* host: AgentHomeHost,
* label: string,
* skillsDir: string,
* missing: number,
* stale: number,
* presentCount: number,
* expectedCount: number,
* packageVersion: string|null,
* catalogVersion: string|null,
* pendingRecoveryRequired: boolean,
* catalogMetadataInvalid: boolean,
* catalogStateReason: string|null,
* flag: string,
* }>}
*/
export function detectAgentHomeGaps(root, env = process.env) {
if (!fs.existsSync(path.join(root, 'AGENTS.md'))) return [];
if (fs.existsSync(path.join(root, 'templates', 'skills'))) return [];
const skillNames = skillTemplateNames();
if (skillNames.length === 0) return [];
const packageVersion = arkPackageVersion();
const gaps = [];
for (const host of agentHomeHostIds()) {
const spec = HOSTS[host];
const dir = skillsDirFor(host, env);
const skillFile = (name) => path.join(dir, name, 'SKILL.md');
const parity = assessSkillCatalogParity(skillNames, skillFile, packageVersion);
const catalogState = readHomeCatalogFloor(dir);
if (!homeInPlay(parity, catalogState)) continue;
const newerFloor =
catalogState.floorVersion &&
isValidSemver(packageVersion) &&
isVersionOlder(packageVersion, catalogState.floorVersion);
const pendingRecoveryRequired =
catalogState.pendingVersion !== null && !newerFloor;
const needsAttention =
!newerFloor &&
(parity.missing > 0 ||
parity.stale > 0 ||
pendingRecoveryRequired ||
catalogState.metadataInvalid);
if (!needsAttention) continue;
gaps.push({
host,
label: spec.label,
skillsDir: dir,
missing: parity.missing,
stale: parity.stale,
presentCount: parity.presentCount,
expectedCount: skillNames.length,
packageVersion,
catalogVersion: catalogState.floorVersion,
pendingRecoveryRequired,
catalogMetadataInvalid: catalogState.metadataInvalid,
catalogStateReason: catalogState.metadataInvalid
? 'invalid catalog metadata'
: pendingRecoveryRequired
? 'interrupted catalog commit'
: null,
flag: spec.flag,
});
}
return gaps;
}
/**
* Claude home is loaded by Claude Code and often by Cursor. Treat both as in-session.
* Grok home is urgent only on a Grok session (or when ARK_ACTIVE_HOST=grok).
*/
export function agentHomeConcernIsActive(host, env = process.env) {
const active = detectActiveAgentHost(env);
if (host === 'claude') return active === 'claude' || active === 'cursor' || !active;
if (host === 'grok') return active === 'grok' || !active;
return true;
}
export function agentHomeRefreshCommand(root, gap) {
return arkCommand(
root,
'ark-check',
`--install-agent-gates --skills-only ${gap.flag} --force`
);
}
/**
* @param {{
* root: string,
* skills?: Array<[string, string]>,
* version: string|null,
* force?: boolean,
* claudeHome?: boolean,
* grokHome?: boolean,
* agentHomes?: boolean,
* json?: boolean,
* env?: NodeJS.ProcessEnv,
* }} args
* @returns {Array<{ host: string, results: object[] }>}
*/
export function installRequestedAgentHomes(args) {
const env = args.env ?? process.env;
const wantClaude = Boolean(args.claudeHome || args.agentHomes);
const wantGrok = Boolean(args.grokHome || args.agentHomes);
if (!wantClaude && !wantGrok) return [];
const skills = args.skills ?? skillTemplates();
const version = args.version ?? arkPackageVersion();
const installed = [];
const targets = [
wantClaude ? { host: 'claude', spec: HOSTS.claude, dir: claudeSkillsDir(env), usesDefault: usesDefaultClaudeHome(env) } : null,
wantGrok ? { host: 'grok', spec: HOSTS.grok, dir: grokSkillsDir(env), usesDefault: usesDefaultGrokHome(env) } : null,
].filter(Boolean);
for (const target of targets) {
if (isTempOrUpgradeRoot(args.root) && target.usesDefault) {
if (!args.json) {
console.log('');
console.log(
`${target.spec.label} home skills: skipped (temp/upgrade --root must not mutate default ~/${target.spec.defaultDirName}).`
);
}
installed.push({
host: target.host,
skipped: true,
reason: 'temp-root-default-home',
results: [],
});
continue;
}
if (!args.json) {
console.log('');
console.log(
`${target.spec.label} home skills (scope=home-shared; source=${version ? `arkgate@${version}` : 'arkgate@unknown'}; target=${target.dir}/<name>/SKILL.md):`
);
console.log(
' Compatibility: monotonic downgrade protection requires ArkGate 4.2.0+ writers; older packages cannot lower this catalog.'
);
}
try {
fs.mkdirSync(target.dir, { recursive: true });
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
if (!args.json) console.error(` FAILED to create ${target.dir} (${message})`);
installed.push({
host: target.host,
skipped: false,
results: [{ relativePath: target.dir, status: 'failed', message }],
});
continue;
}
const results = [];
for (const result of installSkillCatalog({
directory: target.dir,
skills,
packageVersion: version,
force: args.force,
scope: 'home',
})) {
if (!args.json) console.log(skillInstallLine(result));
results.push(result);
}
installed.push({ host: target.host, skipped: false, results });
}
return installed;
}
/**
* Human-facing product copy (4.6). JSON field names stay stable; this module
* owns labels people read in doctor, HTML, and compact router.
*
* Brands kept: ArkGate, ArkRules. Dialect (design-weak, hard write, …) maps to
* common software words. See docs/product-voice.md.
*/
/** Status-light leftover-design qualifier (was “design-weak”). */
export const LEFTOVER_DESIGN_LABEL = 'leftover design work';
/**
* Operating-mode title for humans (and doctor JSON `designFitness.label` prefix).
* @param {string|null|undefined} mode suggest|adapt|enforce
* @param {boolean} leftoverDesign
*/
export function operatingModeTitle(mode, leftoverDesign) {
const light = String(mode || 'enforce').toUpperCase();
return leftoverDesign ? `${light} · ${LEFTOVER_DESIGN_LABEL}` : light;
}
/** Short HTML/doctor badge text. */
export const LEFTOVER_DESIGN_BADGE = LEFTOVER_DESIGN_LABEL;
export const POST_GREEN_HUMAN =
'Imports check out, but the design is still messy. Map leftover work with /ark-explore shape-focus, then apply one small refactor via /ark-autopilot with your OK. A clean import check is not done; pattern bets are never auto-applied.';
export const POST_GREEN_LEDE =
'Import rules are clean, but leftover design work remains. That does not fail the check — it only means “done” is still wrong until you tidy shape.';
export const HARD_WRITE_HUMAN = 'pre-write block';
export const ADVISORY_WRITE_HUMAN = 'warning only (not blocked)';
+1
-1

@@ -151,3 +151,3 @@ /**

if (profile === 'compact') {
lines.push('### Primary path', '', '1. Run doctor (`ark-check --doctor`) — status light + primary next action.', '2. Read the improvement compass (not a score). Name residual lenses in plain language; never “done” on green edges alone while residual remains.', '3. Call `ark_identity` with `project.expectedRoot` at the exact project root; reuse root + `projectId` on Ark MCP calls.', '4. Read the contract with `ark_manifest` (same expectation). `ark://manifest` is compatibility-only / unverified.', '5. Place files inside configured layers; validate; run the check command above on violations — fix architecture, do not weaken the gate.', '6. Single door: edges debt → fix; design-weak / residual shape lenses → map then guided apply with user OK.', '', '### Contract layers (summary)', '', formatAgentProjectionLayers(layers), '');
lines.push('### Primary path', '', '1. Run doctor (`ark-check --doctor`) — status light + primary next action.', '2. Read the improvement compass (not a score). Name leftover work in plain language; never “done” on green imports alone while leftover design work remains.', '3. Call `ark_identity` with `project.expectedRoot` at the exact project root; reuse root + `projectId` on Ark MCP calls.', '4. Read architecture config with `ark_manifest` (same expectation). `ark://manifest` is compatibility-only / unverified.', '5. Place files inside configured layers; validate; run the check command above on violations — fix architecture, do not weaken the gate.', '6. Single door: import-rule debt → fix; leftover design work / residual shape lenses → map then guided apply with user OK.', '', '### Contract layers (summary)', '', formatAgentProjectionLayers(layers), '');
}

@@ -154,0 +154,0 @@ else {

@@ -346,3 +346,3 @@ /**

| Make architecture sound (guided apply path) | **/ark-autopilot** | explore-only, coverage-only |
| **Messy / spaghetti / design-weak after green / Shape residual** | **Single path:** \`/ark-explore\` shape-focus → dual-plan B, then \`/ark-autopilot\` only to apply B with OK | coverage, think, loop-as-done, skill-shopping |
| **Messy / leftover design work after green** | **Single path:** \`/ark-explore\` shape-focus → plan B, then \`/ark-autopilot\` only to apply B with OK | coverage, think, loop-as-done, skill-shopping |
| Map / residual / dual-plan seed only (no apply, already know you want recon) | \`/ark-explore\` | coverage (fitness only) |

@@ -355,3 +355,3 @@ | Greenfield shape / empty tree | \`/ark-architect\` | adopt |

| Drive plan **A** to goal.met | \`/ark-loop\` | explore (unless A empty + design residual → single Shape path above) |
| Ark **fitness** only (governed%, gates, baseline, install gaps) | \`/ark-coverage\` | Shape / design-weak (use single path above) |
| Ark **fitness** only (governed%, gates, baseline, install gaps) | \`/ark-coverage\` | leftover design work (use single path above) |
| One design decision, 2–3 options | \`/ark-think\` | full Shape residual (use single path) |

@@ -362,3 +362,3 @@ | Explain / HTML report tour | \`/ark-explain\` | explore |

**Post-green door (Q01):** when doctor reports ENFORCE · design-weak, the **primary** next action is the single Shape path above — not a choice among explore / coverage / think. Doctor JSON: \`postGreenPath\` / \`primaryNextAction\`.
**Post-green door:** when doctor reports ENFORCE · leftover design work, the **primary** next action is the single Shape path above — not a choice among explore / coverage / think. Doctor JSON: \`postGreenPath\` / \`primaryNextAction\`.

@@ -412,4 +412,4 @@ **Phases (brownfield honesty):** Align (contract truth) → Stabilize (real baseline) → Shape (golden pattern + pilot). Empty plan A after Stabilize still leaves Shape work — that is the single post-green path, not “healthy finished.”

2. Read the **Improvement compass** section (not a score). Name residual lenses in plain language when present (SoC, DIP, domain, …). Out-of-scope lenses (performance, app security tooling, full resilience) stay honest — do not invent Ark enforcement for them.
3. Before trusting MCP evidence: call \`ark_identity\` with \`project.expectedRoot\` set to this project's exact absolute root, then reuse that root plus the returned \`projectIdentity.projectId\` on every Ark MCP call. A descendant path is authoritative only with that matching id. Missing tool, non-\`matched\` binding, or wrong root means the process is stale: restart the host and use the local CLI meanwhile.
4. Day to day: call \`ark_manifest\` with the same project expectation; place new files with \`ark_place\`; validate after edits; run \`${checkCmd}\`. The \`ark://manifest\` resource is compatibility-only and always unverified/non-authoritative. On a gate deny, fix the architecture — do not weaken the contract.
3. Before trusting MCP evidence: call \`ark_identity\` with \`project.expectedRoot\` set to this project's exact absolute root, then reuse that root plus the returned \`projectIdentity.projectId\` on every Ark MCP call. A descendant path is authoritative only with that matching id. Missing tool, non-\`matched\` binding, or wrong root means this is not proven to be the right project: restart the host and use the local CLI meanwhile.
4. Day to day: call \`ark_manifest\` with the same project expectation; place new files with \`ark_place\`; validate after edits; run \`${checkCmd}\`. The \`ark://manifest\` resource is compatibility-only and always unverified. On a gate deny, fix the architecture — do not weaken \`ark.config.json\`.
5. If MCP is unavailable: inspect \`ark.config.json\` and run \`${checkCmd}\`.

@@ -419,4 +419,4 @@

- **Edges debt** (import/capability violations) → fix with the gate / plan; skill pack only if doctor names a skill.
- **Design-weak / residual shape lenses** (compass residual while edges may look green) → map first, then guided apply with user OK — never “you’re done” on green edges alone.
- Empty plan A + residual lenses / design-weak → **not finished**.
- **Design leftover / residual shape lenses** (compass leftover while imports may look green) → map first, then guided apply with user OK — never “you’re done” on green imports alone.
- Empty plan A + leftover design work → **not finished**.

@@ -423,0 +423,0 @@ **Two-axis done (never collapse):**

@@ -12,2 +12,3 @@ /**

import { detectContractFalseGreenRisk } from './field-install.mjs';
import { operatingModeTitle, LEFTOVER_DESIGN_LABEL } from './product-copy.mjs';

@@ -480,7 +481,2 @@ /** Stable smell ids (doctor JSON + plan B + skills). */

const designWeak = isDesignWeak(smells, ctx);
const mode =
typeof ctx.operatingMode === 'string' &&
/^(?:suggest|adapt|enforce)$/.test(ctx.operatingMode)
? ctx.operatingMode.toUpperCase()
: null;
return {

@@ -492,5 +488,5 @@ status: designWeak ? 'design-weak' : smells.length > 0 ? 'smells-with-open-edges' : 'ok',

label: designWeak
? `${mode ? `${mode} · ` : ''}design-weak — edges clean; Shape residual remains (see designSmells / plan B)`
? `${operatingModeTitle(ctx.operatingMode, true)} — import rules check out; leftover design work remains (see designSmells / plan B)`
: smells.length > 0
? 'Design smells present alongside open edge debt'
? 'Design smells present alongside open import-rule debt'
: 'No deterministic design smells detected',

@@ -497,0 +493,0 @@ };

@@ -15,2 +15,8 @@ /** Coverage, plan, and doctor CLI surfaces (roadmap #11). */

import { describePackageVersionDualTruth } from './field-install.mjs';
import {
detectAgentHomeGaps,
agentHomeConcernIsActive,
agentHomeRefreshCommand,
} from './agent-homes.mjs';
import { operatingModeTitle } from './product-copy.mjs';
export { summarizeRulesUnderContract };

@@ -344,3 +350,3 @@

statement =
'No active edge violations — contract edges are clean, but design smells remain (design-weak). Shape residual is plan B only; not healthy finished.';
'No active import-rule violations — imports check out, but design smells remain (leftover design work). Shape work is plan B only; not healthy finished.';
}

@@ -528,2 +534,3 @@ if (completeness !== ANALYSIS_COMPLETENESS.complete) statement = analysisIncompleteStatement(completeness);

const skillGaps = detectSkillGaps(root);
const agentHomeGaps = detectAgentHomeGaps(root);
// Dual-truth: CLI version vs package.json pin (field residual after upgrade --no-install).

@@ -765,2 +772,3 @@ const packageVersionTruth = describePackageVersionDualTruth(root);

skillGaps,
...(agentHomeGaps.length > 0 ? { agentHomeGaps } : {}),
staleRunnerFiles: staleRunners,

@@ -843,12 +851,9 @@ writePath: {

suggest:
'thin or new tree; the contract is not yet the control plane. You do not pick this light. Next: ark start (preview), then ark start --apply; re-check with --doctor.',
'thin or new tree; architecture config is not yet in charge. You do not pick this light. Next: ark start (preview), then ark start --apply; re-check with --doctor.',
adapt:
'contract and tree still disagree, or debt is open. Write path does not fully protect you yet. You do not pick this light. Next: do doctor top action #1 (often /ark-adopt, /ark-contract, or /ark-autopilot).',
'config and tree still disagree, or debt is open. The write path does not fully protect you yet. You do not pick this light. Next: do doctor top action #1 (often /ark-adopt, /ark-contract, or /ark-autopilot).',
enforce:
'honest coverage and clean checked edges. You arrived here; you never turn Enforce on. Next: keep the host write path and CI check; only NEW violations should fail.',
'honest coverage and clean checked imports. You arrived here; you never turn Enforce on. Next: keep the host write path and CI check; only NEW violations should fail.',
};
const modeTitle =
designFitness.designWeak
? `${mode.toUpperCase()} · design-weak`
: mode.toUpperCase();
const modeTitle = operatingModeTitle(mode, designFitness.designWeak);
line(

@@ -858,3 +863,3 @@ modeMark,

designFitness.designWeak
? 'checked edges are honest; design smells remain. Green is not elegant design. You do not pick this light. Next: one Shape door — /ark-explore shape-focus → dual-plan B; apply B only with /ark-autopilot and your OK. Empty plan A is not done.'
? 'import rules check out; design smells remain. Green is not elegant design. You do not pick this light. Next: one Shape door — /ark-explore shape-focus → plan B; apply B only with /ark-autopilot and your OK. A clean import check is not done.'
: modeHelp[mode]

@@ -923,3 +928,3 @@ }`

line(' ', color.dim(`success: ${np.successSignal}`));
line(' ', color.dim('never multi-pilot batch; patternBets never mechanical-safe'));
line(' ', color.dim('never multi-pilot batch; pattern bets are never auto-applied'));
}

@@ -943,3 +948,3 @@ }

(goldenPattern.newCodeHome ? ` Prefer: ${goldenPattern.newCodeHome}.` : '') +
' Advisory only — does not clear design-weak or replace the gate.'
' Advisory only — does not clear leftover design work or replace the gate.'
);

@@ -1049,3 +1054,3 @@ } else if (goldenPattern.invalid) {

} else if (designFitness.designWeak) {
line(warn, `None on checked edges — edges match the contract; design residual remains (${modeTitle}). Not healthy finished.`);
line(warn, `None on checked imports — import rules match the config; leftover design work remains (${modeTitle}). Not healthy finished.`);
} else {

@@ -1169,2 +1174,21 @@ line(ok, 'None — the code matches the contract on checked edges');

}
for (const gap of agentHomeGaps) {
const parts = [
gap.missing > 0 ? `${gap.missing} missing` : null,
gap.stale > 0 ? `${gap.stale} content-behind-package` : null,
gap.catalogStateReason,
].filter(Boolean);
const deferred = !agentHomeConcernIsActive(gap.host);
const summary = `${gap.label} shared agent skills ${parts.join(', ')}`;
if (deferred) {
line(color.dim('·'), color.dim(`${summary} (deferred — not this session)`));
} else {
line(warn, summary);
actions.push(
gap.catalogMetadataInvalid
? `repair invalid ${gap.label} home catalog metadata after verifying the newest installed version`
: `refresh ${gap.label} shared agent skills (${agentHomeRefreshCommand(root, gap)})`
);
}
}

@@ -1171,0 +1195,0 @@ console.log('');

@@ -157,3 +157,3 @@ /**

if (g.examplePath) s += ` Example: ${g.examplePath}.`;
s += ' Does not clear design-weak or replace the gate.';
s += ' Does not clear leftover design work or replace the gate.';
return s;

@@ -160,0 +160,0 @@ }

@@ -227,9 +227,9 @@ /**

if (host === 'cursor' && !hardWriteActive) {
return `Cursor: hard preToolUse is supported for Write/StrReplace when .cursor/hooks.json is installed + trusted; without runtime-observed hook evidence, hard is unverified. ${mergeBoundary}.`;
return `Cursor: pre-write block is supported for Write/StrReplace when .cursor/hooks.json is installed + trusted; without runtime-observed hook evidence, the block is unverified. ${mergeBoundary}.`;
}
if (host === 'codex') {
return `Codex: write path is advisory / best-effort at write (not Claude/Grok/Cursor hard). ${mergeBoundary}.`;
return `Codex: edits are warning only (not blocked) at write time. ${mergeBoundary}.`;
}
if (host === 'opencode') {
return `OpenCode: write path is advisory / best-effort (MCP + optional plugin; not Claude/Grok/Antigravity/Cursor hard). ${mergeBoundary}.`;
return `OpenCode: edits are warning only (not blocked). ${mergeBoundary}.`;
}

@@ -239,5 +239,5 @@ if ((host === 'claude' || host === 'grok' || host === 'antigravity') && !hardWriteActive) {

host === 'claude' ? 'Claude' : host === 'grok' ? 'Grok' : 'Antigravity';
return `${label}: hard PreToolUse is supported for listed ops when installed + trusted; without runtime-observed hook evidence, hard is unverified. ${mergeBoundary}.`;
return `${label}: pre-write block is supported for listed ops when installed + trusted; without runtime-observed hook evidence, the block is unverified. ${mergeBoundary}.`;
}
return null;
}

@@ -27,2 +27,3 @@ /**

import { computePhysicalCohesion } from './physical-cohesion.mjs';
import { POST_GREEN_LEDE, operatingModeTitle } from './product-copy.mjs';

@@ -387,9 +388,7 @@ function esc(value) {

const title = designWeak
? mode === 'enforce'
? 'ENFORCE · design-weak'
: `${(mode || 'edges').toUpperCase()} · design-weak`
: 'Design smells (edges still open)';
? operatingModeTitle(mode || 'enforce', true)
: 'Design smells (imports still open)';
const lede = designWeak
? 'Contract edges are clean, but lived design residual remains. This does not fail PASS — it blocks “healthy finished” until Shape work lands.'
: 'Design smells exist alongside open edge debt. Fix edges first; treat smells as Shape residual after green.';
? POST_GREEN_LEDE
: 'Design smells exist alongside open import-rule debt. Fix imports first; treat smells as leftover design work after green.';

@@ -416,3 +415,3 @@ const smellItems = smells

<p class="dim" style="margin:.15rem 0 .4rem;font-size:.86rem">
Judgment only — never mechanical-safe · never multi-pilot batch
Judgment only — never auto-applied · never multi-pilot batch
</p>

@@ -495,3 +494,3 @@ <ul class="senior-list">

<span class="badge design-ok" title="No deterministic design smells with clean edges">Design depth · OK</span>
<span class="dim" style="font-size:.86rem">No design-weak residual detected</span>
<span class="dim" style="font-size:.86rem">No leftover design work detected</span>
</div>

@@ -498,0 +497,0 @@ <p class="dim" style="margin:.45rem 0 0;font-size:.88rem">

@@ -83,2 +83,3 @@ /**

import { inspectCodexInstallActivation, printCodexActivationHandoff, reportPartialInstall } from './install-activation.mjs';
import { installRequestedAgentHomes } from './agent-homes.mjs';
import {

@@ -651,2 +652,13 @@ hasHardWriteHook,

installRequestedAgentHomes({
root,
skills,
version,
force: args.force,
claudeHome: args.claudeHome,
grokHome: args.grokHome,
agentHomes: args.agentHomes,
json: args.json,
});
// Optional legacy/home fallback. Normal Codex installs use the project-scoped

@@ -653,0 +665,0 @@ // .codex/config.toml above, avoiding cross-project primary binding conflicts.

@@ -9,2 +9,4 @@ /**

import { POST_GREEN_HUMAN } from './product-copy.mjs';
/** Stable product id for JSON / tests. */

@@ -20,4 +22,3 @@ export const POST_GREEN_PATH_ID = 'clarify-for-ai';

*/
export const POST_GREEN_PRIMARY_ACTION =
'Shape residual (design-weak): edges are clean, design is not finished. Map with /ark-explore shape-focus → dual-plan B; apply B only via /ark-autopilot with your OK. Empty plan A is not done; pattern bets are never mechanical-safe.';
export const POST_GREEN_PRIMARY_ACTION = POST_GREEN_HUMAN;

@@ -24,0 +25,0 @@ /** Short label for tables / metrics. */

@@ -19,3 +19,3 @@ /**

const HOME_SKILL_LOCK_STALE_MS = 5 * 60 * 1000;
const HOME_SKILL_LOCK_ATTEMPTS = 100;
const HOME_SKILL_LOCK_ATTEMPTS = 200;
const HOME_SKILL_LOCK_RETRY_MS = 25;

@@ -22,0 +22,0 @@ const UUID_PATTERN =

@@ -37,2 +37,18 @@ /**

{
id: 'plain-language-doctor',
title: 'Doctor in plain language',
try: 'npx arkgate-check --doctor',
inspect: 'Status light + leftover design work (not a score)',
why:
'Doctor and the HTML report use common words (import rules, leftover design work, pre-write block). ArkGate and ArkRules stay as product names.',
},
{
id: 'shared-agent-homes',
title: 'Shared agent skills (home)',
try: 'npx arkgate-check --install-agent-gates --skills-only --agent-homes --force',
inspect: 'doctor.agentHomeGaps (Claude/Grok ~/.*/skills when those catalogs exist)',
why:
'Project skills follow this pin. Shared homes stay on the newest ArkGate on the machine (additive; never downgrade). Orphan 2.x global skills stop coaching the wrong version.',
},
{
id: 'deep-module-coach',

@@ -39,0 +55,0 @@ title: 'Deep-module coach (hot paths + deepening)',

@@ -610,6 +610,6 @@ # ArkGate — Agent Integration Guide

|------|-----------------|-------------|
| Claude Code | `.claude/settings.json` hook + `.mcp.json` / `claude mcp add` | `.claude/skills/<name>/SKILL.md` |
| Cursor | `.cursor/mcp.json` + `.cursor/rules/ark.mdc` | `.cursor/commands/` |
| Claude Code | `.claude/settings.json` hook + `.mcp.json` / `claude mcp add` | **Repo:** `.claude/skills/<name>/SKILL.md`; **home:** `$CLAUDE_HOME/skills` (default `~/.claude/skills`, `--claude-home`) |
| Cursor | `.cursor/mcp.json` + `.cursor/rules/ark.mdc` | `.cursor/commands/` (Cursor also loads Claude **home** skills from `~/.claude/skills`) |
| OpenAI Codex | `.codex/config.toml` (project primary, relative `--root .`; configured on disk is not runtime-active until restart + `ark_identity` match); optional legacy `$CODEX_HOME/config.toml` fallback uses absolute roots and scoped secondaries — see [ai-gates.md](ai-gates.md) | **Repo:** `.agents/skills/<name>/SKILL.md`; **home:** `$CODEX_HOME/skills/<name>/SKILL.md` (`--codex-home`) |
| **Grok Build** | `.grok/hooks/ark-write-gate.json` + `.grok/config.toml` / `.mcp.json` | `.grok/skills/<name>/SKILL.md` |
| **Grok Build** | `.grok/hooks/ark-write-gate.json` + `.grok/config.toml` / `.mcp.json` | **Repo:** `.grok/skills/<name>/SKILL.md`; **home:** `$GROK_HOME/skills` (default `~/.grok/skills`, `--grok-home`) |
| Google Antigravity | `.agents/hooks.json` (+ `GEMINI.md` for shared Gemini consumers) | `.agents/skills/<name>/SKILL.md` |

@@ -622,6 +622,9 @@ | OpenCode | `opencode.json` MCP (`type: local`; advisory) | `.opencode/skills/<name>/SKILL.md` |

When several repositories share one machine, repo catalogs stay pinned and isolated; unchanged
skill bodies are not rewritten for a version stamp. The optional `$CODEX_HOME/skills` catalog is
monotonic across ArkGate 4.2.0+ installers. Pre-4.2 binaries ignore its metadata and lock, so
upgrade legacy repos before they write the optional home catalog. See
[AI gates — Codex skill catalog](ai-gates.md#codex-skill-catalog-skillmd-not-flat-prompts).
skill bodies are not rewritten for a version stamp. Shared **home** catalogs (Codex since 4.2;
Claude/Grok since 4.6) are the machine floor: always latest additive, never downgrade. Refresh
with `--agent-homes` (or `--claude-home` / `--grok-home` / `--codex-home`). Absent home trees
are normal — doctor stays quiet until `ark-*` skills exist there. Pre-4.2 binaries ignore Codex
home metadata and lock, so upgrade legacy repos before they write the optional Codex home
catalog. See [AI gates — Codex skill catalog](ai-gates.md#codex-skill-catalog-skillmd-not-flat-prompts)
and [shared Claude/Grok homes](ai-gates.md#shared-claude--grok-home-skills).

@@ -628,0 +631,0 @@ ### Install skills — Ark and ecosystem {#install-skills-ark-and-ecosystem}

@@ -449,2 +449,21 @@ # Gating AI Agents with ArkGate

### Shared Claude / Grok home skills {#shared-claude--grok-home-skills}
Project catalogs follow that checkout’s ArkGate pin (they may lag). Shared user-home catalogs
are the **machine floor**:
| Scope | Path | Flag |
|-------|------|------|
| Claude home | `$CLAUDE_HOME/skills` (default `~/.claude/skills`) | `--claude-home` |
| Grok home | `$GROK_HOME/skills` (default `~/.grok/skills`) | `--grok-home` |
| All three + Codex | same monotonic protocol | `--agent-homes` |
Doctor reports `agentHomeGaps` only when those catalogs already contain `ark-*` skills and
lag the installed package. Temp/upgrade `--root` never mutates default user homes. Cursor
sessions treat a stale Claude home as urgent because Cursor loads `~/.claude/skills`.
```bash
npx arkgate-check --install-agent-gates --skills-only --agent-homes --force
```
### Codex skill catalog (SKILL.md, not flat prompts)

@@ -451,0 +470,0 @@

@@ -38,5 +38,5 @@ # Develop with ArkGate

|------|-------------|-----|-------|
| Claude · Grok · Antigravity | Hard PreToolUse when installed + trusted | Advisory | Required status context |
| Codex · OpenCode | Best-effort / advisory | Advisory | Required status context |
| Cursor | Advisory only | Advisory | Required status context |
| Claude · Grok · Antigravity | Pre-write block when installed + trusted | Advisory | Required status context |
| Codex · OpenCode | Warning only (not blocked) | Advisory | Required status context |
| Cursor | Pre-write block for Write/StrReplace when `.cursor/hooks.json` is trusted | Advisory | Required status context |

@@ -43,0 +43,0 @@ Full matrix and install commands: [ai-gates.md](ai-gates.md) · canonical table in [README](../README.md#host-enforcement-support).

@@ -212,4 +212,4 @@ # ArkGate package surface policy

Ship notes for a version live under [releases/](https://github.com/pedroknigge/arkgate/tree/main/docs/releases)
(current published: [4.5.6.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.5.6.md);
prior published: [4.5.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.5.0.md), [4.4.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.4.0.md), [4.3.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.3.0.md),
(current published: [4.5.7.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.5.7.md);
prior published: [4.5.6.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.5.6.md), [4.5.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.5.0.md), [4.4.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.4.0.md), [4.3.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.3.0.md),
[4.2.1.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.2.1.md);

@@ -216,0 +216,0 @@ previous: [4.2.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.2.0.md),

@@ -19,7 +19,8 @@ # ArkGate product voice

- **Gate side:** machine-readable contract + write gate + CI. Deterministic. Fail-closed.
Green must mean something real. Two planes: **Layers** (inter) always; **ArkRules** (intra)
opt-in.
- **Co-pilot side:** where code belongs, who talks to whom, how; dual plan **A** (edges) +
**B** (shape); one pilot at a time; never silent judgment codemod; never weaken the contract.
- **Gate side:** architecture config (`ark.config.json`) + pre-write block where the host
supports it + required CI. Deterministic. Don’t show green if we could not verify.
Two planes: **import rules** (who may import whom) always; **ArkRules** (structure rules
inside a layer) opt-in.
- **Coach side:** where code belongs, who talks to whom, how; fix imports first, then leftover
design work; one small refactor at a time; never silent auto-reshape; never weaken the config.
- **Agent contract surface (4.3.0):** agents read **guardrail catalogs** and **scan** evidence;

@@ -33,3 +34,3 @@ they **process** (judge / coach) outside the package. Projection and skills never become the

experts keep full JSON. Full-AI workflows get the same single door — not a skill menu exam.
- **False done is forbidden:** Enforce ≠ elegant design. `design-weak` / residual must not
- **False done is forbidden:** “Rules on” ≠ elegant design. Leftover design work must not
read as “healthy finished.” Empty ArkRules inventory is not a score. MCP configuration on

@@ -52,53 +53,56 @@ disk is not proof that the current process belongs to this project.

|-----|------|
| Ship it 🚀 your architecture is crushed! | Checked edges are clean. Residual design smells mean the tree is still design-weak. Next: `/ark-explore` shape-focus. |
| Ship it 🚀 your architecture is crushed! | Import rules check out. Leftover design smells mean the tree is still messy. Next: `/ark-explore` shape-focus. |
| You don’t need to understand anything. | Doctor reports one status light and one primary next action. Run `ark-check --doctor`. |
| Become an architect in 60 seconds. | Install pins the contract and compact router. Full guided cleanup is `/ark-autopilot` after skills install. |
| Become an architect in 60 seconds. | Install pins `ark.config.json` and a short agent router. Full guided cleanup is `/ark-autopilot` after skills install. |
---
## Lexicon (prefer)
## Lexicon (prefer) — 4.6 common words
| Term | Use for |
|------|---------|
| **contract** | `ark.config.json` layers, rules, include — the machine-readable architecture file |
| **Layers plane** | Inter-layer edges: imports, placement, purity, isolation |
| **ArkRules** (opt-in) | Intra-layer structure sensors + domain invariant catalogs as data (`arkrules/*`) |
| **advisory ArkRules** | Default sensor mode — **not** merge teeth; does not fail CI/merge alone (FG-ARKRULES-ADVISORY-ONLY) |
| **extraMergeTeeth** | Only when enforced structure/invariant rules exist **and** classification is honest (≥50% governed, ≥1 populated layer) |
| **dual-plane residual** | Label findings **`[Layer]`** vs **`[ArkRules]`** — never blur them |
| **rulesUnderContract** | Doctor/inventory counts for ArkRules — **never a score** |
| **type-only placement debt** | `import type` edges on the violations list with `failsStrict:false` — prefer SharedTypes / owning layer; not runtime coupling |
| **gate** / **write gate** | Host boundary that blocks or advises on invalid writes |
| **edges** | Allowed import graph (plan **A** / remediation) |
| **baseline** | Frozen known debt; does not make a wrong contract honest |
| **remediation** | Fixing violations against the contract |
| **pilot** | One extraction / reshape cluster at a time |
| **shape** | Design residual after edges are clean (plan **B**) |
| **design-weak** | Edges clean under Enforce, but design smells / pattern residual remain — not “done” |
| **residual** | Work still open after a green edge check (usually Shape / plan **B**) |
| **co-pilot** | Guidance that proposes order and pilots without silent codemod |
| **fail-closed** | Incomplete analysis or unproven enforcement never looks green |
| **honest coverage** | Governed % and empty scope that cannot false-green |
| **mechanical-safe** | Deterministic auto-apply class only |
| **judgment** | Human/agent design work; never silent auto-apply as mechanical-safe |
| **doctor** | Control plane: status light + next action |
| **compact router** | Default onboarding agent instructions (not the full skill pack) |
| **hard write** | Non-bypassable PreToolUse block for listed ops (Claude/Grok when installed + trusted) |
| **advisory write** | MCP/rules coach only (Cursor/Codex at write time) — not a hard block |
| **project identity** | Stable canonical root + config identity returned by `ark_identity`; separate from contract and process identity |
| **matched binding** | Live MCP answered for the exact project root, or for a contained descendant together with the matching project id; only this binding is authoritative |
| **authoritative manifest** | Contract returned by `ark_manifest` after a matched identity handshake |
| **compatibility manifest resource** | `ark://manifest` through standard `resources/read`; always unverified/non-authoritative because the request cannot portably carry a project expectation |
| **configured on disk** | Host files name an Ark MCP command; says nothing about which process is currently running |
| **runtime observed** | A live `ark_identity` response matched this workspace; never infer it from `.codex/config.toml` or hook files |
| **required CI / status context** | Merge hard boundary when the repository makes the Ark job a **required GitHub status context** (CLI: `arkgate-check --strict-merge` / `ark-check --strict-merge`) |
| **contract ready** | Project/layers/ArkRules honesty residual clear — not the same as “hard local write” |
| **environment residual** | Permanent host/provider posture (e.g. soft-write Codex) kept in evidence without forcing global **Not finished** |
| **guardrail catalog** | Closed vocabulary of allowed sensors, capabilities, diagnostic `ruleId`s, and skill roles — agents and copy choose from the catalog; they do not invent free-form enforcement claims |
| **scan** | Deterministic engine / CLI / MCP evidence pass (layers, ArkRules sensors, status facts, prepare-write). Same inputs → same verdict. No LLM. |
| **process** (agent judgment) | Skill- or agent-side coaching: placement, dual-plan, pilot choice, remediation order. Improves prevention; **never** package pass/fail |
| **diagnostic code** / **ruleId** | Stable public violation id (e.g. `LAYER_IMPORT_VIOLATION`) with shared why/fix anchors — catalog-linked, not prose-only ([diagnostics.md](diagnostics.md)) |
| **agent projection** | Version-matched AGENTS/CLAUDE (or equivalent) block generated from package + contract; **non-authoritative** — enforcement is ark-check / hooks / CI |
| **finding ref** | Stable id for a finding across turns (ruleId + target key), so agents re-address without fuzzy message match |
| **status snapshot** | One machine-readable project/session manifest (`ark status --json` shape): identity, activation honesty, last check, residual counts, thin compass residual map — not a numeric score |
**Brands (keep):** **ArkGate** (product / npm `arkgate`) and **ArkRules** (opt-in structure rules
inside a layer). Gloss on first mention; do not rebrand.
Human copy prefers the **common** column. JSON field names (`designWeak`, `ruleId`, MCP tools)
stay stable unless a change explicitly adds an alias.
| Prefer (human) | Was / JSON | Use for |
|----------------|------------|---------|
| **architecture config** | contract | `ark.config.json` layers, rules, include |
| **import rules** / **allowed dependencies** | Layers plane / edges | Who may import whom; placement, purity, isolation |
| **ArkRules** (opt-in; gloss: structure rules inside a layer) | ArkRules | Intra-layer sensors + domain invariant catalogs (`arkrules/*`) |
| **advisory ArkRules** | advisory ArkRules | Default sensor mode — **not** merge teeth; does not fail CI/merge alone |
| **extra merge checks** | extraMergeTeeth | Only when enforced structure/invariant rules exist **and** classification is honest |
| **label `[Layer]` vs `[ArkRules]`** | dual-plane residual | Never blur import-rule findings with ArkRules findings |
| **ArkRules counts** | rulesUnderContract | Doctor/inventory counts — **never a score** |
| **type-only import debt** | type-only placement debt | `import type` on the violations list with `failsStrict:false` |
| **pre-write block** | hard write | Host actually blocks listed edit ops (installed + trusted) |
| **warning only (not blocked)** | advisory write | MCP/rules coach; not a hard block |
| **import graph** | edges | Allowed imports (fix these first) |
| **baseline** | baseline | Frozen known debt; does not make a wrong config honest |
| **fix** | remediation | Fixing violations against the config |
| **one small refactor** | pilot | One extraction / reshape cluster at a time |
| **shape / leftover design work** | **design-weak** / residual | Imports clean under Enforce, but design smells remain — not “done” |
| **coach** | co-pilot | Guidance that proposes order without silent auto-reshape |
| **don’t show green if unverified** | fail-closed | Incomplete analysis or unproven enforcement never looks green |
| **honest coverage** | honest coverage | Governed % and empty scope that cannot false-green |
| **safe to auto-apply** | mechanical-safe | Deterministic auto-apply class only |
| **your judgment** | judgment | Human/agent design work; never silent auto-apply |
| **doctor** | doctor | Status light + next action |
| **short agent router** | compact router | Default onboarding agent instructions (not the full skill pack) |
| **right project?** | matched binding / project identity | Live MCP answered for this exact project root (+ id). `ark_identity` |
| **authoritative config read** | authoritative manifest | `ark_manifest` after a matched identity handshake |
| **compatibility manifest** | `ark://manifest` | Always unverified — request cannot carry a project expectation |
| **configured on disk** | configured on disk | Host files name an Ark MCP command; not proof of the live process |
| **runtime observed** | runtime observed | A live `ark_identity` matched this workspace |
| **required CI status** | required CI / status context | Merge hard boundary: required GitHub status running `arkgate-check --strict-merge` |
| **config ready** | contract ready | Project/import-rules/ArkRules honesty clear — not the same as a local pre-write block |
| **host limitation** | environment residual | Permanent soft-write host (e.g. Codex) — do not paint the whole project unfinished |
| **allowed rule ids** | guardrail catalog | Closed vocabulary of sensors, capabilities, `ruleId`s, skill roles |
| **check (tool)** | scan | Deterministic engine / CLI / MCP. Same inputs → same verdict. No LLM. |
| **coaching / your judgment** | process | Skill- or agent-side. **Never** package pass/fail |
| **diagnostic code** / **ruleId** | ruleId | Stable public violation id — catalog-linked ([diagnostics.md](diagnostics.md)) |
| **agent summary** | agent projection | Version-matched AGENTS/CLAUDE block; **non-authoritative** |
| **finding id** | finding ref | Stable id (ruleId + target key) across turns |
| **status snapshot** | status snapshot | `ark status --json`: identity, activation, last check, leftover counts — not a score |
| **shared agent skills (home)** | Codex/Claude/Grok home catalog | Machine floor: always latest additive; never downgrade |
| **session recipe** | Agent loop: bind identity → read status → act on residual / findingRef; run doctor when status compass mode is not `full` |

@@ -164,11 +168,11 @@ | **compass mode** | Status honesty label for the projected residual map: `full` \| `subset` \| `unavailable` — never invent green residual |

|----|---------|
| Name the status light + plain fact + term + next action | “Enforce · design-weak. Checked edges are honest; design smells remain. Next: one Shape door — explore → dual-plan B → autopilot with OK.” |
| Name the status light + plain fact + next action | “Enforce · leftover design work. Import rules check out; design smells remain. Next: one Shape door — explore → plan B → autopilot with OK.” |
| Rank one primary door under residual | Doctor **Primary next action** #1; **Also** only for secondary |
| Label expert skills as escapes | “Install skill pack only when doctor or a STOP handoff names a skill.” |
| State host write honesty | “Cursor/Codex: advisory write. Required GitHub status context is the hard merge boundary.” |
| State host write honesty | “Cursor: pre-write block for Write/StrReplace when hooks are trusted. Codex: warning only (not blocked). Required GitHub status is the merge boundary.” |
| Soft-write ≠ unfinished project | “Architecture contract ready; Codex local writes are advisory.” Keep `soft-write-host` in evidence; reserve **Not finished** for contract/project debt. |
| Keep Suggest on start → doctor | New-here primary is finish `start`, not a competing recommend/architect curriculum |
| Qualify edge-clean under design-weak | “None on checked edges … design residual remains. Not healthy finished.” |
| Prefer fail-closed over fake hard | Incomplete analysis, unobserved hooks, and soft MCP never paint as hard green |
| State project binding before verdict | “Ark MCP matched this workspace; `ark_manifest` evidence is authoritative.” Otherwise: “Ark MCP is configured, but runtime identity is unverified. Restart and call `ark_identity` with the exact project root.” |
| Qualify import-clean under leftover design | “None on checked imports … leftover design work remains. Not healthy finished.” |
| Prefer unverified-as-not-green | Incomplete analysis, unobserved hooks, and soft MCP never paint as a hard green pre-write block |
| State project binding before verdict | “Ark MCP matched this workspace; `ark_manifest` evidence is for this project.” Otherwise: “Ark MCP is configured, but we have not proven this is the right project. Restart and call `ark_identity` with the exact project root.” |
| Keep inventory claims evidence-bound | “Possible rule candidate in the configured Application layer.” A filename or technical constant alone is not Domain evidence. |

@@ -178,3 +182,3 @@ | Honesty clear ≠ architecture healthy | `productHonesty.finished` means residual **architecture** honesty sensors are clear — not a green graph score. Open blocking violations, ADAPT/SUGGEST with debt, dual-truth pin, or design residual keep `unfinished: true`. Permanent soft-write alone does **not**. |

| Prefer catalog language for agent DX | “Stable `ruleId` with why/fix anchors.” Not a free-form list of “things that might be wrong.” |
| Name scan before process | “Scan: two layer import violations. Process: fix the Application→Domain edge first.” |
| Name the check before coaching | “Check: two layer import violations. Next: fix the Application→Domain import first.” |
| Label projection non-enforcing | “Regenerated agent contract for this package version. Enforcement remains ark-check / hooks / required CI.” |

@@ -197,3 +201,3 @@ | Keep status counts honest | “Inventory and residual counts are evidence — not a health score.” |

| Skill-shopping lists as the default curriculum | Progressive disclosure: one door first |
| “Healthy / done” while design-weak | False done |
| “Healthy / done” while leftover design work remains | False done |
| “Honesty clear” as “architecture finished” | Honesty clear only means residual honesty sensors are quiet; graph/mode debt is separate |

@@ -242,12 +246,13 @@ | “Not finished” solely because host is Codex/Cursor | Soft-write is environment residual; do not paint a green whole-tree project as unfinished architecture |

- One contract. One gate. One co-pilot.
- One architecture config. One check. One coach.
- Green must mean something real.
- You arrive at Enforce; you never turn it on.
- Enforce does not mean the design is elegant — only that checked edges are honest.
- Empty plan A is not “architecture healthy” when design residual remains.
- One pilot at a time. Pattern bets are never mechanical-safe.
- Enforce does not mean the design is elegant — only that checked imports are honest.
- A clean import check is not “architecture healthy” when leftover design work remains.
- One small refactor at a time. Pattern bets are never auto-applied.
- Doctor is the control plane: status light + next action.
- Scan is deterministic. Process is judgment. Only the gate decides pass/fail.
- The check is deterministic. Coaching is judgment. Only the gate decides pass/fail.
- Guardrails are a catalog, not free generation.
- Agent docs project the contract; they never replace the gate.
- Agent docs summarize the config; they never replace the gate.
- **ArkGate** and **ArkRules** are product names — gloss them; don’t invent a second brand.

@@ -273,6 +278,6 @@ ## Hero phrases (forbidden)

|-------|------------|
| **Suggest** | Thin or new tree. Contract is not yet the control plane. Next: `ark start` preview, then `--apply`; re-run doctor. |
| **Adapt** | Contract and tree still disagree, or debt is open. Write path does not fully protect you yet. Next: doctor top action #1. |
| **Enforce** | Honest coverage and clean checked edges. Keep host write path + required CI. |
| **Enforce · design-weak** | Checked edges are honest; design smells remain. Green is not elegant design. Next: one Shape door — map (`/ark-explore` shape-focus) → dual-plan B → apply B only with `/ark-autopilot` and OK. |
| **Suggest** | Thin or new tree. Architecture config is not yet in charge. Next: `ark start` preview, then `--apply`; re-run doctor. |
| **Adapt** | Config and tree still disagree, or debt is open. The write path does not fully protect you yet. Next: doctor top action #1. |
| **Enforce** | Honest coverage and clean checked imports. Keep the host write path + required CI. |
| **Enforce · leftover design work** | Import rules check out; design smells remain. Green is not elegant design. Next: one Shape door — map (`/ark-explore` shape-focus) → plan B → apply B only with `/ark-autopilot` and OK. |

@@ -282,3 +287,3 @@ ### Primary next action

- Lead with the **outcome**, then the **skill or command**, then the **constraint** (never mechanical-safe / never skill-shop).
- When design-weak, rank the single Shape path first; do not list explore / coverage / think as equal first choices.
- When leftover design work remains, rank the single Shape path first; do not list explore / coverage / think as equal first choices.

@@ -295,4 +300,4 @@ ### Deny / gate failure

Print “Healthy — nothing to do” **only** when there is no design-weak residual and no open top actions.
Otherwise name the residual.
Print “Healthy — nothing to do” **only** when there is no leftover design work and no open top actions.
Otherwise name the leftover work.

@@ -328,3 +333,4 @@ ---

- [ ] No false done under design-weak / incomplete analysis.
- [ ] Technical terms present (contract, gate, edges, pilot) without slang.
- [ ] Technical terms present (architecture config, import rules, ArkGate, ArkRules) without slang.
- [ ] Leftover design work is never called “done”.
- [ ] Expert skills are labeled expert — not the default curriculum.

@@ -331,0 +337,0 @@ - [ ] Scan vs process is not blurred with package LLM pass/fail.

@@ -56,3 +56,3 @@ # ArkGate documentation

| Release notes (by version) | [releases/](releases/) · [CHANGELOG.md](../CHANGELOG.md) |
| Epic plans (seeded + shipped) | [plans/](plans/) — maintainer seeds (e.g. [field-upgrade-mcp-truth](plans/field-upgrade-mcp-truth/README.md) **shipped in 4.5.6**; deep-module coach **shipped in 4.5.5**; domain fitness & session truth for **4.5.0**; improvement compass for **4.4.0**; agent contract surface for **4.3.0**). Product how-to stays in use/develop/agent-guide; plans are not required reading to use the package. |
| Epic plans (seeded + shipped) | [plans/](plans/) — maintainer seeds (e.g. [understandable-ark-4.6](plans/understandable-ark-4.6/README.md) **4.6.0**; [field-upgrade-mcp-truth](plans/field-upgrade-mcp-truth/README.md) **shipped in 4.5.6**; deep-module coach **shipped in 4.5.5**; domain fitness & session truth for **4.5.0**; improvement compass for **4.4.0**; agent contract surface for **4.3.0**). Product how-to stays in use/develop/agent-guide; plans are not required reading to use the package. |
| Claims audit | [audit/claims-matrix.md](audit/claims-matrix.md) |

@@ -62,3 +62,4 @@ | Field adoption kit (scaffolding, not closed) | [field/](field/) |

Current published: [releases/4.5.6.md](releases/4.5.6.md) (`arkgate@4.5.6` on npm `latest`).
Current published: [releases/4.5.7.md](releases/4.5.7.md) (`arkgate@4.5.7` on npm `latest`).
Prepared: [releases/4.6.0.md](releases/4.6.0.md) (`arkgate@4.6.0`).
Prior: [releases/4.4.0.md](releases/4.4.0.md) (`arkgate@4.4.0`).

@@ -65,0 +66,0 @@ Previous: [releases/4.3.0.md](releases/4.3.0.md) · [releases/4.2.1.md](releases/4.2.1.md) · [releases/4.2.0.md](releases/4.2.0.md) · [releases/4.1.1.md](releases/4.1.1.md).

@@ -5,3 +5,3 @@ # Use ArkGate

**One contract. One gate. One co-pilot.**
**One architecture config. One check. One coach.**

@@ -25,3 +25,3 @@ ---

| Agent broke architecture | Fix the edge doctor names (or re-run check) |
| Code is green but still a mess | Shape residual — see below |
| Code is green but still a mess | Leftover design work — see below |
| New ArkGate version | Follow doctor / upgrade guidance |

@@ -52,3 +52,3 @@

| Before merge | Make the Ark job a **required GitHub status context** running `arkgate-check --strict-merge` (alias `ark-check`) |
| Anytime | Doctor: Suggest / Adapt / Enforce (+ design-weak if residual) |
| Anytime | Doctor: Suggest / Adapt / Enforce (+ leftover design work if the design is still messy) |

@@ -102,5 +102,5 @@ **Codex / Cursor / OpenCode:** local write stays advisory forever — that is not unfinished architecture. Doctor may say **contract ready** while still reminding you that local writes are advisory; **Not finished** is reserved for real project/contract debt.

1. Doctor confirms design-weak (and residual lenses on the improvement compass)
1. Doctor confirms leftover design work (and residual lenses on the improvement compass)
2. Guided map / dual plan (skill pack: `/ark-explore` then `/ark-autopilot` with your OK)
3. One pilot at a time · re-run doctor
3. One small refactor at a time · re-run doctor

@@ -111,2 +111,4 @@ Install skills only when you want that guided path:

npx arkgate-check --install-agent-gates --skills-only --force
# optional: refresh shared Claude/Grok/Codex home skills (never downgrades)
# npx arkgate-check --install-agent-gates --skills-only --agent-homes --force
```

@@ -113,0 +115,0 @@

{
"name": "arkgate",
"version": "4.5.7",
"description": "ArkGate — architecture co-pilot for AI TypeScript (write gate, CI gate, plan/loop; optional ArkRules)",
"version": "4.6.0",
"description": "ArkGate \u2014 architecture co-pilot for AI TypeScript (write gate, CI gate, plan/loop; optional ArkRules)",
"type": "module",

@@ -6,0 +6,0 @@ "main": "./dist/index.cjs",

+12
-10

@@ -5,3 +5,3 @@ <div align="center">

**One contract. One gate. One co-pilot.**
**One architecture config. One check. One coach.**

@@ -20,4 +20,4 @@ Your AI writes most of the code. ArkGate keeps that work inside an architecture you can trust —

> **ArkGate 4.5.6** is on npm `latest` — field upgrade truth, multi-project MCP honesty, skill drift.
> [4.5.6 notes](docs/releases/4.5.6.md) · [4.5.5](docs/releases/4.5.5.md) · [4.5.0](docs/releases/4.5.0.md) · [Docs hub](docs/README.md) · [Product voice](docs/product-voice.md)
> **ArkGate 4.6.0** is prepared — clearer language + shared agent home skills.
> [4.6.0 notes](docs/releases/4.6.0.md) · [4.5.7](docs/releases/4.5.7.md) (npm `latest`) · [4.5.6](docs/releases/4.5.6.md) · [Docs hub](docs/README.md) · [Product voice](docs/product-voice.md)

@@ -48,5 +48,5 @@ ---

That is the product. Doctor is the control plane — when stuck, do **primary next action #1**.
Doctor also shows an **improvement compass** (architecture lenses such as separation of concerns and
dependency inversion — **not a score**). Residual lenses mean Shape work may remain even when edges
are green. Details: [use.md — Improvement compass](docs/use.md#improvement-compass-not-a-score).
Doctor also shows **what to improve next** (architecture lenses such as separation of concerns and
dependency inversion — **not a score**). Leftover lenses mean design work may remain even when
imports are green. Details: [use.md — Improvement compass](docs/use.md#improvement-compass-not-a-score).

@@ -70,3 +70,3 @@ ```text

|------|------|
| **While the AI writes** | Hard PreToolUse on supported hosts; advisory MCP elsewhere |
| **While the AI writes** | Pre-write block on supported hosts; warning only elsewhere |
| **Before merge** | `arkgate-check` as a **required** CI status |

@@ -78,4 +78,4 @@

|-------|----------------|--------|
| **Layers** (always) | Who may talk to whom — imports, placement, purity, isolation | `ark.config.json` layers + rules |
| **ArkRules** (opt-in) | Habits *inside* a layer — structure sensors + domain invariants as data | `arkRules` → `arkrules/<Layer>.json` |
| **Layers** (always) | Who may import whom — imports, placement, purity, isolation | `ark.config.json` layers + rules |
| **ArkRules** (opt-in; structure rules inside a layer) | Habits *inside* a layer — structure sensors + domain invariants as data | `arkRules` → `arkrules/<Layer>.json` |

@@ -183,2 +183,4 @@ Absence of ArkRules changes no inter-layer verdict. Label residual **`[Layer]`** vs **`[ArkRules]`**.

npx arkgate-check --install-agent-gates --tools claude,cursor,codex,grok
# optional: refresh shared home skills (Claude/Grok/Codex; never downgrades)
# npx arkgate-check --install-agent-gates --skills-only --agent-homes --force
# optional: same 13 skills via Agent Skills ecosystem (no new names)

@@ -217,3 +219,3 @@ # npx skills add ./node_modules/arkgate/templates/agent-skills

| Security | [SECURITY.md](SECURITY.md) |
| Current release (4.5.6 on npm `latest`) | [docs/releases/4.5.6.md](docs/releases/4.5.6.md) · [CHANGELOG](CHANGELOG.md) |
| Current release (4.5.7 on npm `latest`) | [docs/releases/4.5.7.md](docs/releases/4.5.7.md) · [CHANGELOG](CHANGELOG.md) |
| Prior (4.5.0) | [docs/releases/4.5.0.md](docs/releases/4.5.0.md) |

@@ -220,0 +222,0 @@ | Prior (4.4.0) | [docs/releases/4.4.0.md](docs/releases/4.4.0.md) |

{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"name": "io.github.pedroknigge/arkgate",
"description": "ArkGate — architecture co-pilot for AI TypeScript (write gate, CI, plan/loop)",
"description": "ArkGate \u2014 architecture co-pilot for AI TypeScript (write gate, CI, plan/loop)",
"repository": {

@@ -9,3 +9,3 @@ "url": "https://github.com/pedroknigge/arkgate",

},
"version": "4.5.7",
"version": "4.6.0",
"packages": [

@@ -15,3 +15,3 @@ {

"identifier": "arkgate",
"version": "4.5.7",
"version": "4.6.0",
"runtimeHint": "npx",

@@ -18,0 +18,0 @@ "transport": {

@@ -193,3 +193,3 @@ ---

| **Enforce** | Honest coverage + clean checked **edges** | Confirm gates + CI; emit dual-plan B only if residual found |
| **Enforce · design-weak** | Edges clean; design smells remain | **Primary Shape door:** explore shape-focus → dual-plan **B** → apply **one** pilot with user OK. Empty plan A ≠ done. Never mechanical-safe B. False-done forbidden. |
| **Enforce · leftover design work** | Imports clean; design still messy | **Primary Shape door:** explore shape-focus → dual-plan **B** → apply **one** small refactor with user OK. Empty plan A ≠ done. Never mechanical-safe B. False-done forbidden. |

@@ -196,0 +196,0 @@ - **Setup (Suggest):** no config → `ark start` (start freezes origin after config, before gates).

---
name: ark-explore
description: Specialized map skill — decision-grade recon of layers + ArkRules opportunities + dual-plan seed (no apply). Primary post-green door when design-weak. Not the default day-to-day path (use doctor + place/gate; guided apply is /ark-autopilot). CLI is a sensor; you read the tree. No gate bypass.
description: Specialized map skill — decision-grade recon of layers + ArkRules opportunities + dual-plan seed (no apply). Primary post-green door when leftover design work remains. Not the default day-to-day path (use doctor + place/gate; guided apply is /ark-autopilot). CLI is a sensor; you read the tree. No gate bypass.
---

@@ -26,3 +26,3 @@

**Anti false-done:** empty plan A + residual lenses / design-weak → **Incomplete? yes**. Green edges alone
**Anti false-done:** empty plan A + leftover design work → **Incomplete? yes**. Green imports alone
are not “architecture finished.”

@@ -63,3 +63,3 @@

| Map / “what next?” / residual after ENFORCE | User wants edits applied → `/ark-autopilot` or `/ark-fix` |
| **Primary post-green door:** messy / spaghetti / design-weak / “clarify for AI” | Skill-shopping coverage or think for the same residual |
| **Primary post-green door:** messy / leftover design work / “clarify for AI” | Skill-shopping coverage or think for the same leftover work |
| Spaghetti brownfield: patterns concurrent, design-weak under green check | Only “governed% + gates installed?” numbers → `/ark-coverage` |

@@ -69,3 +69,3 @@ | Dual-plan **seed** (A remediation + B pattern bets) without applying | One design trade-off between 2–3 options already mapped → `/ark-think` |

**Post-green single path:** when doctor `postGreenPath` / ENFORCE · design-weak is active, **this skill
**Post-green single path:** when doctor `postGreenPath` / ENFORCE · leftover design work is active, **this skill
(shape-focus / dual-plan seed) is the map half of the one door** — then `/ark-autopilot` only

@@ -81,3 +81,3 @@ to apply B with user OK. Do not send the user to coverage or think as equal first choices.

| **Enforce** | Confirm edges; if residual smells/patterns appear, auto-upgrade to dual-plan seed / shape-focus |
| **Enforce · design-weak** | **Primary post-green map door** — shape-focus + dual-plan B + extraction cards. False-done forbidden. Never claim healthy because plan A is empty. |
| **Enforce · leftover design work** | **Primary post-green map door** — shape-focus + dual-plan B + extraction cards. False-done forbidden. Never claim healthy because plan A is empty. |

@@ -84,0 +84,0 @@ `/ark-autopilot`, `/ark-adopt`, and `/ark-coverage` embed a **lighter** version of this pass.

@@ -24,3 +24,3 @@ ---

**Anti false-done:** empty plan A + residual lenses / design-weak → **Incomplete? yes**. Green edges alone
**Anti false-done:** empty plan A + leftover design work → **Incomplete? yes**. Green imports alone
are not “architecture finished.”

@@ -62,2 +62,3 @@

| Multiple checkouts / monorepo packages | One `expectedRoot` per project; upgrade **each** pin; restart MCP after bump; prefer project-local CLI until identity matched **and** process version aligns. |
| Stale `~/.claude/skills` or `~/.grok/skills` | Shared homes should be the newest ArkGate on the machine (additive; never downgrade). Refresh: `--install-agent-gates --skills-only --agent-homes --force`. Project skills may lag with the pin. |
| Active host not in `--tools` / manifest | Preview `hostSelection` notes it and suggests `--tools` expansion. |

@@ -64,0 +65,0 @@

@@ -10,3 +10,3 @@ # ArkGate Agent Skills package

Package version when last generated context: **arkgate@4.5.6**
Package version when last generated context: **arkgate@4.6.0**
Schema: agent-skills package contract `1.0`

@@ -13,0 +13,0 @@

@@ -193,3 +193,3 @@ ---

| **Enforce** | Honest coverage + clean checked **edges** | Confirm gates + CI; emit dual-plan B only if residual found |
| **Enforce · design-weak** | Edges clean; design smells remain | **Primary Shape door:** explore shape-focus → dual-plan **B** → apply **one** pilot with user OK. Empty plan A ≠ done. Never mechanical-safe B. False-done forbidden. |
| **Enforce · leftover design work** | Imports clean; design still messy | **Primary Shape door:** explore shape-focus → dual-plan **B** → apply **one** small refactor with user OK. Empty plan A ≠ done. Never mechanical-safe B. False-done forbidden. |

@@ -196,0 +196,0 @@ - **Setup (Suggest):** no config → `ark start` (start freezes origin after config, before gates).

---
name: ark-explore
description: Specialized map skill — decision-grade recon of layers + ArkRules opportunities + dual-plan seed (no apply). Primary post-green door when design-weak. Not the default day-to-day path (use doctor + place/gate; guided apply is /ark-autopilot). CLI is a sensor; you read the tree. No gate bypass.
description: Specialized map skill — decision-grade recon of layers + ArkRules opportunities + dual-plan seed (no apply). Primary post-green door when leftover design work remains. Not the default day-to-day path (use doctor + place/gate; guided apply is /ark-autopilot). CLI is a sensor; you read the tree. No gate bypass.
---

@@ -26,3 +26,3 @@

**Anti false-done:** empty plan A + residual lenses / design-weak → **Incomplete? yes**. Green edges alone
**Anti false-done:** empty plan A + leftover design work → **Incomplete? yes**. Green imports alone
are not “architecture finished.”

@@ -63,3 +63,3 @@

| Map / “what next?” / residual after ENFORCE | User wants edits applied → `/ark-autopilot` or `/ark-fix` |
| **Primary post-green door:** messy / spaghetti / design-weak / “clarify for AI” | Skill-shopping coverage or think for the same residual |
| **Primary post-green door:** messy / leftover design work / “clarify for AI” | Skill-shopping coverage or think for the same leftover work |
| Spaghetti brownfield: patterns concurrent, design-weak under green check | Only “governed% + gates installed?” numbers → `/ark-coverage` |

@@ -69,3 +69,3 @@ | Dual-plan **seed** (A remediation + B pattern bets) without applying | One design trade-off between 2–3 options already mapped → `/ark-think` |

**Post-green single path:** when doctor `postGreenPath` / ENFORCE · design-weak is active, **this skill
**Post-green single path:** when doctor `postGreenPath` / ENFORCE · leftover design work is active, **this skill
(shape-focus / dual-plan seed) is the map half of the one door** — then `/ark-autopilot` only

@@ -81,3 +81,3 @@ to apply B with user OK. Do not send the user to coverage or think as equal first choices.

| **Enforce** | Confirm edges; if residual smells/patterns appear, auto-upgrade to dual-plan seed / shape-focus |
| **Enforce · design-weak** | **Primary post-green map door** — shape-focus + dual-plan B + extraction cards. False-done forbidden. Never claim healthy because plan A is empty. |
| **Enforce · leftover design work** | **Primary post-green map door** — shape-focus + dual-plan B + extraction cards. False-done forbidden. Never claim healthy because plan A is empty. |

@@ -84,0 +84,0 @@ `/ark-autopilot`, `/ark-adopt`, and `/ark-coverage` embed a **lighter** version of this pass.

@@ -24,3 +24,3 @@ ---

**Anti false-done:** empty plan A + residual lenses / design-weak → **Incomplete? yes**. Green edges alone
**Anti false-done:** empty plan A + leftover design work → **Incomplete? yes**. Green imports alone
are not “architecture finished.”

@@ -62,2 +62,3 @@

| Multiple checkouts / monorepo packages | One `expectedRoot` per project; upgrade **each** pin; restart MCP after bump; prefer project-local CLI until identity matched **and** process version aligns. |
| Stale `~/.claude/skills` or `~/.grok/skills` | Shared homes should be the newest ArkGate on the machine (additive; never downgrade). Refresh: `--install-agent-gates --skills-only --agent-homes --force`. Project skills may lag with the pin. |
| Active host not in `--tools` / manifest | Preview `hostSelection` notes it and suggests `--tools` expansion. |

@@ -64,0 +65,0 @@

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display