Delivery Plan
This page is the sole execution entry for implementation Agents. Architecture, Specifications, and Reference define contracts; Implementation Status records current facts. See the Claude Code Execution Runbook for task orchestration, isolation, and acceptance.
Final goal
Jue is accepted against a minimal exhaustive fixture derived from each target Agent's official capability surface, not against a private asset repository.
Claude Code proves the first complete loop:
official capability discovery
→ minimal exhaustive native fixture
→ native read into Canonical
→ Canonical schema validation
→ write native Artifacts
→ read again
→ normalized Canonical equality
→ Core apply
→ headless or official native usability proofAfter the loop passes, repository agent-extension Skill guidance and author CLI support standardize discovery, fixture construction, conversion, contract tests, and native confirmation. Codex, OpenClaw, and Hermes then adapt in parallel. Final acceptance covers cross-Agent conversion and --all.
Equality contracts
For Canonical fixture C:
normalize(read(write(C))) = normalize(C)For target-native fixture N:
normalize(read(write(read(N)))) = normalize(read(N))Compare Canonical semantics, provenance, and portability—not irrelevant native bytes. Valid unmanaged native fields survive same-target updates but never enter cross-Agent comparison.
Runtime usability
Logical equality does not prove target usability. Use headless native reading or execution when available. Otherwise use an official parser, validate, list, inspect, doctor, or real discovery path plus round-trip equality. Plugin, Bundle, and other aggregate Artifacts must pass official load/inventory and at least one real contained-capability discovery or invocation. File existence, snapshot equality, or green unit tests alone are insufficient.
Minimal exhaustive fixtures
Discover the current official surface from documentation, CLI help/schema, and necessary read-only local probes. A fixture covers every supported Canonical Capability, every native-only preservation class, every aggregate Artifact kind, and empty/conflict/path/sensitive/unsupported failures. Combine fields when one small fixture covers several behaviors. Fixtures are neutral, low-sensitivity, deterministic, offline, and temporary-directory safe.
“Exhaustive” means the verified capability surface and boundaries, not a copy of a large real asset repository.
Execution protocol
Claim only the first ready task and begin with failing evidence or an authoritative native fact. Keep one task in progress until the Claude Gate. After the Scale Gate, Codex, OpenClaw, and Hermes may run in parallel. Parallel work cannot modify Canonical, Core apply, ArtifactChange, or generic approval. Public gaps return to serial Architecture/RFC decisions. Done requires implementation, tests, and redacted target-native evidence.
R1: Claude Code real loop
| Task | Status | Dependency | Evidence |
|---|---|---|---|
| JUE-101 ProjectConfig/CanonicalDocument | done | — | CanonicalDocument schema frozen (packages/ai-jue/src/config.ts); toCanonicalDocument() strips ProjectConfig-only fields; CapabilityRef.converter migrated to type, removing the directory-bundling jue-native converter so one reference resolves exactly one leaf Capability; npm test (164 passing) includes new canonical-document.test.ts and single-leaf assertions in capability-source.test.ts |
| JUE-102 ArtifactChange and managed state | done | JUE-101 | ArtifactChange/ArtifactResult/Confirmation types plus assertArtifactChange/assertConfirmation invariants (packages/ai-jue-core/src/artifact-change.ts); ownership (full/managed-block/merged-keys) and atomicState added to packages/docs/{,en/}reference/extension-api.md; npm test (181 passing, including 17 new invariant tests) |
| JUE-103 minimal Extension Host | done | JUE-101, JUE-102 | Adapter/ExtensionDefinition/CapabilitySupport/defineExtension (packages/ai-jue-core/src/extension-host.ts, Adapter has only read/write/confirm); resolveExtensionPackage/loadExtensionGuarded (packages/ai-jue/src/extension-loader.ts, npm exports/main/peerDependencies metadata checks plus import-time fs/child_process/process.exit/fetch guards, proven to actually block a file write and a child-process spawn); jue extension validate <path-or-package> [--load] wired up matching the CLI Reference exit codes; npm test (206 passing); CanonicalDocument and its six atomic-Capability zod schemas moved from ai-jue (the CLI package) to ai-jue-core, correcting a layering mistake left over from JUE-101 (Adapters depend only on ai-jue-core, never the CLI package) |
| JUE-104 Claude capability discovery | done | JUE-101 | Read-only subagent verification against claude CLI 2.1.219: official docs plus --help/plugin validate/headless system/init probes produced a capability matrix, scope-precedence table, and target-private field list, and corrected stale/imprecise claims in packages/docs/{,en/}agents/claude-code.md (manifest is optional; skills/commands share one namespace and silently override same-named entries; MCP accepts two valid shapes; Claude Code reads only CLAUDE.md, not AGENTS.md; --bare drops Plugin agents/mcp_servers from the inventory). Note: that report's "zero-cost" headless inventory claim was disproved by the Lead's own hands-on test in JUE-105 — see JUE-105 evidence |
| JUE-105 Claude exhaustive fixture | done | JUE-104 | packages/ai-jue-adapter-claude/fixtures/: project-native config, two Plugins (with and without a manifest), a marketplace index, a naming-collision sample, three failure samples (empty skill body, invalid hook event name, a path-escaping hook command) plus one sensitive-reference sample; every claude plugin validate outcome re-verified against the real CLI and recorded in fixtures/README.md. Building it corrected 5 inaccurate claims from the JUE-104 report (hooks.json needs an outer hooks key; dependencies is a string array, not an object; userConfig entries require title; agent/subagentStatusLine are not real manifest fields at all; headless --tools "" does not guarantee zero cost — a real run billed total_cost_usd: 0.0394407), now reflected back into packages/docs/{,en/}agents/claude-code.md |
| JUE-106 Native → Canonical | done | JUE-103, JUE-105 | packages/ai-jue-adapter-claude/src/read.ts implements read(context): project vs. Plugin layout auto-detected from whether .claude/ exists; rules/commands/agents (flat .md files), skills (one directory with SKILL.md each), hooks (settings.json or hooks.json, symmetric with the existing write-side mapping), mcp.servers (both flat and wrapped shapes normalized), and context.global (resolving CLAUDE.md's one-level @AGENTS.md import). Runs clean against every JUE-105 fixture and passes CanonicalDocumentSchema; npm test (230 passing, including 21 new read() assertions). While building it, assertNoLiteralCredentials/splitFrontmatter were promoted to shared ai-jue-core capabilities (Capability Source and every Adapter now share one rule instead of two copies), and a false rejection of Claude Plugin's ${user_config.KEY} placeholder (previously misidentified as a literal credential) was fixed. Later refactored, per the design recorded in docs/superpowers/specs/2026-07-26-capability-mapping-engine-design.md, into a thin composition over declarative tables in packages/ai-jue-adapter-claude/src/capabilities/*.ts — behavior unchanged (all 15 assertions pass unmodified) |
| JUE-107 Canonical → Artifact | done | JUE-102, JUE-106 | packages/ai-jue-adapter-claude/src/write.ts implements write(canonical, context), sharing the same packages/ai-jue-adapter-claude/src/capabilities/*.ts declaration tables as read(), driven through the generic engine in packages/ai-jue-core/src/capability-mapping.ts (flatMarkdownDirectory/directoryPerItem/managedMarkdownFile/mergedJsonFile covering the four native shapes, plus readCapabilities/writeCapabilities). ArtifactChange gained a content field (previously only hashes existed, leaving Core nothing to actually write — a JUE-102 gap this task found and fixed). Both equality contracts are verified with a test-only applyChanges scaffold (normalize(read(write(C)))=normalize(C) and normalize(read(write(read(N))))=normalize(read(N)), covering both project and Plugin Artifacts). Unmanaged-field preservation (unknown settings.json keys, user prose in CLAUDE.md) and zero-diff second apply each have dedicated tests. Along the way, a real bug was found and fixed: context.global's read() never stripped the AI-JUE:START/END wrapper, breaking the round trip — fixed by adding extractManagedContent (the dual of stripManagedBlock) to ai-jue-core. Followed by closing a Plugin-identity gap: capabilities/manifest.ts generates .claude-plugin/plugin.json (WriteContext.pluginManifest), verified against real claude plugin validate --strict; the package entry was reduced to one defineExtension() default export and the CLI invokes write() through the Adapter object, correcting two unverified historical behaviors (context.global no longer writes a separate AGENTS.md digest; commands write to .claude/commands/ instead of skills/), with the cross-adapter contract tests and snapshot updated accordingly. Marketplace/aggregate-index Artifacts are explicitly out of scope this round (no acceptance criterion requires them — speculative scope outside the current problem domain; trade-off recorded in adapter-standardization.md). npm test (269 passing) |
| JUE-108 dry-run/Core apply/check/inspect | done | JUE-107 | packages/ai-jue-core/src/core-executor.ts implements planExecution/applyExecution/checkExecution: re-reads the on-disk hash before writing and compares it against beforeHash (a mismatch blocks the whole batch with zero writes, blocked-conflict); a requiresApproval change not covered by authorizedTargets is classified separately as blocked-unauthorized; each write is snapshotted before it happens and a mid-batch failure rolls back everything already applied in reverse order (rolled-back — a test forces a real write failure by making an existing plain file stand in for a directory segment, and verifies full rollback); a change whose afterHash is already on disk is no-change, so a second apply is zero-write. applyChangesOrThrow replaces the placeholder artifact-executor.ts (deleted outright, no drift/authorization/rollback), not kept as a parallel legacy implementation. CLI wiring in packages/ai-jue/src/core-apply.ts: jue apply validates the Extension default export and routes its single Adapter write() through the Core executor, with --dry-run (always zero-write, always exits 0) and --check (no-change/pending/blocked-conflict/blocked-unauthorized/rolled-back mapped to CLI Reference exit codes 0/3/3/4/1) verified. scripts/smoke-apply.js gained runCoreExecutorSmoke(), exercising the real dist/cli.js: --dry-run on an empty project is zero-write, --check exits 3, apply exits 0 and writes, --check after a clean apply exits 0, and a second apply leaves the file's mtime untouched. npm test (282 passing, including 17 new core-executor.test.ts assertions). Scope note: reproducing real on-disk drift at the CLI level needs a time gap across two separate invocations that doesn't exist within one jue apply call (write() and applyExecution run back-to-back), so blocked-conflict is verified at the engine level against a directly constructed ArtifactChange; see implementation-status.md for detail |
| JUE-109 Claude native usability | done | JUE-108 | scripts/verify-claude-native.js (replayable from a clean worktree): (1) builds a minimal Plugin with a single deterministic command through the real write()/applyChangesOrThrow() path in an isolated temp directory; claude plugin validate --strict passes; (2) forces a real mid-batch write failure (a second change's parent path collides with an existing plain file); core-executor.ts's applyExecution fully rolls back the already-applied change, and the same real claude plugin validate --strict re-confirms the fixture was left uncorrupted; (3) claude --bare -p "/jue-109-verify:status" --plugin-dir <fixture> --output-format stream-json --verbose --allowedTools "": system/init's plugins contains the generated Plugin, plugin_errors carries no entry for it, slash_commands contains the generated command, and the final result is {is_error:false, result:"JUE-109-OK"} (the deterministic marker text, proving the capability was really discovered and invoked, not merely present as a file), real cost $0.003–$0.005 per run. Found and recorded three real facts along the way: --bare authentication strictly requires ANTHROPIC_API_KEY or an apiKeyHelper via --settings (never OAuth/keychain — this machine's interactive login doesn't carry over to --bare; this run used an Anthropic-API-compatible third-party backend to satisfy that requirement); --bare does not isolate the Plugin surface from whatever else is installed on the machine (the fixture appears alongside every other real Plugin in plugins); plugin_errors is entirely absent from system/init when nothing failed, not an empty array. Full evidence in packages/ai-jue-adapter-claude/fixtures/README.md's "JUE-109 native usability verification" section. Scope note: to avoid the already-documented (JUE-104/105) --bare gap that drops a Plugin's agents/mcp_servers from inventory from muddying this result, the fixture deliberately covers only commands — agents/mcp.servers round-trip equivalence is already covered by JUE-106/107's unit tests, just not through this --bare headless gate; confirm() itself and defineExtension() assembly haven't started (out of JUE-109's acceptance scope) |
| JUE-110 Claude MVP Gate | done | JUE-109 | scripts/verify-claude-mvp-gate.js (one command, replayable from a clean temp directory): (1) read()s the real project/ native fixture (the same one JUE-105/106/107's own tests use, not a separately built minimal sample) into Canonical, checked against CanonicalDocumentSchema; (2) drops context.global before converting to a Plugin — Claude Code Plugins have no CLAUDE.md-equivalent mechanism, so write() never emits context.global for artifactKind: "plugin", consistent with the plugin/ fixture's own coverage matrix (a pre-existing Artifact-kind boundary this task surfaced explicitly, not a defect it introduced); (3) adds one purpose-built, tool-free, deterministic command (same technique as JUE-109), write()s into a fresh temp directory as a Plugin, applies through the Core executor; (4) claude plugin validate --strict passes; (5) read()s the result and assert.deepStrictEquals it against the pre-write Canonical (the normalize(read(write(read(N))))=normalize(read(N)) contract, verified end-to-end in one run rather than split across separate unit tests); (6) a second write() of the same Canonical yields zero changes (idempotent); (7) claude --bare -p "/jue-110-mvp-gate:mvpGateProbe" --plugin-dir <fixture> --output-format stream-json --verbose --allowedTools "": system/init shows the Plugin loaded with no error entry and the probe command in slash_commands, and the final result is the deterministic marker text, proving real discovery and invocation — real cost around $0.005 per run; (8) confirms the fixture's own non-functional mcp.servers entry (pointing at a node server.js that doesn't exist) does not block or hang this invocation — Claude Code does not eagerly connect to a Plugin's MCP servers merely from --plugin-dir loading. Full evidence in packages/ai-jue-adapter-claude/fixtures/README.md's "JUE-110 Claude MVP Gate" section |
R1 wrap-up: JUE-101 through JUE-110 are all done; the next ready task is JUE-201.
R2: Standardize agent-extension development
| Task | Status | Dependency | Evidence |
|---|---|---|---|
JUE-201 repository agent-extension Skill | done | JUE-110 | packages/jue-preset-internal/skills/adapter-creator/ (SKILL.md v6.0.0, now explicitly self-identifies as the agent-extension Skill delivery-plan.md's R2 refers to): a six-phase methodology — (1) official capability discovery (read official docs plus run CLI help/validate/list, recording the exact command and output for every claim, never trusting an unverified assertion); (2) minimal exhaustive fixture (one directory per Artifact kind, target-private preservation samples, failure samples, plus a new "aggregate-Artifact investigation" subsection pointing at adapter-standardization.md's granularity trade-off test); (3) Native→Canonical (reuse capability-mapping.ts's four declarative factories instead of hand-written parsers); (4) Canonical→Artifact (the same declaration table drives write, plus a new subsection requiring write()'s output to run through core-executor.ts's (JUE-108) planExecution/applyExecution/checkExecution rather than reinventing apply/rollback per Adapter); (5) both equivalence contracts (now verified with the real applyChangesOrThrow, replacing a stale reference to the deleted placeholder scaffold); (6) native confirmation (a new "reusable script shape" subsection generalizing scripts/verify-claude-native.js/verify-claude-mvp-gate.js's concrete technique — a deterministic marker command, a forced batch failure plus rollback plus native re-validation, auth and isolation checked as two separate empirical questions, and a broken external-process reference not necessarily blocking headless invocation — into a template any target Agent should follow, not Claude-specific trivia). Verified against all existing tests and doc gates (no new test cases — this is a documentation/methodology asset change) |
| JUE-202 shared contract tests | done | JUE-201 | packages/ai-jue-core/src/adapter-contract-kit.ts exports defineAdapterContractSuite(options): one call registers all six contract-test categories — both equivalence contracts, idempotency, unmanaged-field preservation, sensitive-reference rejection, and per-Artifact-kind native confirmation (via each fixture's optional confirmNatively callback) — materializing through the real applyChangesOrThrow/core-executor.ts apply path, not a separate test-only writer. Exported only from the ai-jue-core/testkit subpath (testkit.js/testkit.d.ts at the package root; vitest declared as an optional peerDependency; callers inject ESM describe/expect/it through testApi), deliberately kept out of ai-jue-core's main entry point so the test framework never leaks into runtime consumers. Verified by actually migrating the Claude Adapter onto it: new packages/ai-jue-adapter-claude/test/contract.test.ts (8 assertions, including real claude plugin validate --strict native confirmation) replaces the old hand-written write.test.ts (6 duplicate assertions, deleted), and the duplicate sensitive-credential-rejection test in read.test.ts moved into the shared suite's securityRejectionCases; packages/jue-preset-internal/skills/adapter-creator/SKILL.md (v6.1.0) Phase 5 now points at this shared suite instead of hand-written equivalence tests. npm test (283 passing, net +1: 282 − 6 (deleted write.test.ts) + 8 (new contract.test.ts) − 1 (de-duplicated in read.test.ts) = 283) |
| JUE-203 author CLI support | done | JUE-202 | Prerequisite finding: jue extension validate ai-jue-adapter-claude was previously guaranteed to fail — the package only had dependencies.ai-jue-core, missing the peerDependencies["ai-jue-core"] JUE-103's validator requires, and exported no defineExtension()-shaped default (only standalone read/write, never a confirm()). Both closed, giving the repo its first genuinely loadable Extension: new packages/ai-jue-adapter-claude/src/confirm.ts (Plugin Artifacts go through real claude plugin validate --strict; project-scope has no equivalent native validator, so it honestly reports unconfirmed rather than a fabricated pass); index.ts assembles an Adapter (id: "claude-code", all six capabilities supported, read/write/confirm) and export default defineExtension(...); package.json gained peerDependencies.ai-jue-core. node dist/cli.js extension validate ai-jue-adapter-claude --load succeeds for the first time (previously always exit 2 on the metadata gap). CLI entry points: (1) jue extension validate --fixtures (runExtensionFixtureCheck in packages/ai-jue/src/commands/extension.ts) runs the loaded Extension's first Adapter's read() against every immediate subdirectory and checks the result against CanonicalDocumentSchema, reporting pass/fail per fixture, exit 2 on any failure — verified against the real Claude fixtures (project/plugin both pass). (2) jue inspect --extension --diagnostics (new packages/ai-jue/src/commands/inspect.ts): read-only report of the loaded Adapter's id/capabilities, plus (when a project config exists in cwd) real apply-readiness via core-executor.ts's (JUE-108) checkExecution against that project (no-change/pending/conflict count/unauthorized count) — never writes; running it against this repo's own root found 17 real pending changes (a genuine result, not fabricated), with git status confirming zero writes. --capability/--preset/--target/--artifact filters are not implemented, explicitly marked as planned in implementation-status.md rather than faked. npm test (293 passing, adding 3 in confirm.test.ts, 4 in extension-fixtures.test.ts, 3 in inspect.test.ts) |
| JUE-204 neutral second Adapter | done | JUE-203 | Architectural decision: the neutral Adapter is not built as a standalone packages/ai-jue-adapter-* package, but as an in-repo test fixture (packages/ai-jue-core/test/fixtures/neutral-adapter/). Reason: packages/ai-jue/src/commands/apply.ts's findAdapters() discovers Adapters via the glob packages/ai-jue-adapter-*/package.json, so a real package would genuinely be picked up by jue apply --all (including scripts/smoke-apply.js) — a purely test-only construct would pollute the real semantics of the packages/ai-jue-adapter-* namespace, and one with no real native tool to confirm against is a fake target that's user-visible but never actually usable. This follows the common practice in kernel-plus-plugin repos like Rollup/Vite/Webpack/Babel/ESLint: synthetic plugins/loaders/rules built purely to stress-test framework generality live inline in the tested framework's own test suite, not as sibling published packages. Implementation: capabilities.ts declares seven mergedJsonFile mappings (context.json/rules.json/commands.json/agents.json/skills.json/hooks.json/mcp.json — one file per Capability type, a genuinely different native shape from Claude's "one file/directory per Capability item"); mcp additionally does a servers ↔ mcpServers key-rename translation (reusing assertNoLiteralCredentials), proving the toCanonical/toNative translation mechanism generalizes too; read.ts/write.ts are thin compositions over readCapabilities/writeCapabilities; confirm.ts honestly reports unconfirmed (this fictional Agent has no official tool to confirm against — that is the correct answer, not a fabricated pass). Building this surfaced and avoided a real pitfall: if all six Capabilities shared one file (each with its own independent mergedJsonFile mapping), writeCapabilities()'s naive concatenation — each mapping computing its change from its own pre-write disk snapshot — would let a later change clobber an earlier one once Core applied them in sequence; giving each Capability its own file sidesteps this entirely, no change to capability-mapping.ts needed. packages/ai-jue-core/test/adapter-contract-kit.neutral.test.ts calls JUE-202's defineAdapterContractSuite directly (6 assertions: both equivalence contracts, idempotency, unmanaged-field preservation, sensitive-reference rejection, honest-unconfirmed native confirmation) with zero Claude-specific code. Verified packages/ai-jue-core/src/{canonical-document,capability-mapping,core-executor,extension-host}.ts have identical md5 hashes before and after; check-consistency/smoke-apply.js both confirm no new real package was added and jue apply never discovers it. npm test (299 passing, 6 new) |
| JUE-205 Scale Gate | done | JUE-204 | Full regression review: npm test (299 passing), npm run build, npm run check-consistency, npm --prefix packages/docs run docs:build, git diff --check all pass. Frozen: (1) the template — packages/jue-preset-internal/skills/adapter-creator/SKILL.md (v6.2.0) six-phase methodology plus references/IMPLEMENTATION-patterns.md; (2) the input contract — Phase 1's versioned capability matrix, Phase 2's minimal exhaustive native fixture; (3) the output contract — packages/ai-jue-adapter-{agent}/'s standard directory skeleton (capabilities/*.ts/read.ts/write.ts/confirm.ts/index.ts assembling Adapter+defineExtension()/fixtures//test/contract.test.ts), write() must run through core-executor.ts (JUE-108); (4) the completion-evidence contract — the handoff-contract field list (packages/docs/developer/claude-code-execution.md's "Handoff contract" section expanded to twelve fields: task_id/status/owned_paths/official_evidence/fixture_cases/changes/commands_run/logical_results/native_results/security_results/remaining_risks/next_ready_task, up from eight — filled in by this task) plus the native-confirmation requirement; (5) the namespace boundary for synthetic/test-only targets (must not become a standalone packages/ai-jue-adapter-* package, per the JUE-204 precedent). See claude-code-execution.md's new "Scale Gate (JUE-205) frozen contents" section for detail. All three R3 tasks (JUE-301/302/303) are now ready and can proceed in parallel |
The Skill is a developer execution asset, not a seventh architecture concept.
R3: Parallel Codex, OpenClaw, and Hermes
All three depend on JUE-205 and reuse one workflow: discover official capabilities and aggregate Artifacts; build a minimal exhaustive fixture; implement Native → Canonical and Canonical → Artifact; run both equality contracts and shared tests; use headless when available or official native discovery plus round-trip equality otherwise; never modify the public model.
| Task | Status | Dependency | Evidence |
|---|---|---|---|
| JUE-301 Codex Extension | done | JUE-205 | packages/ai-jue-adapter-codex/ (post-commit 2f9a408) rebuilt per the JUE-205 output contract: capabilities/{context,skills,commands,agents,hooks,mcp,manifest,layout}.ts declaration table + read.ts/write.ts/confirm.ts/index.ts assembling Adapter + defineExtension(). The capability declaration is honest: commands: "degraded" (Codex's old custom-commands mechanism was deprecated per JUE-104/105/JUE-301 Phase 1), mcp: "degraded" (Codex MCP lives in [mcp_servers.*] TOML tables, doesn't fit the JSON-based factory), rules: "degraded" (Codex has no separate rules directory; rules fold into AGENTS.md via context). fixture/{project,plugin}/ + fixtures/failures/sensitive-reference/.codex/config.toml; test/contract.test.ts calls JUE-202's defineAdapterContractSuite to run both equivalence contracts + idempotency + unmanaged-field preservation + sensitive-reference rejection + native confirmation. Native confirmation: Codex 0.145.0 has no codex plugin validate; we use the real codex plugin marketplace add <local> --marketplace <name> + codex plugin add <name> --marketplace <name> + codex plugin list --json (isolated CODEX_HOME) to prove the Plugin is genuinely installed by codex, appears in inventory with installed: true, enabled: true. Project scope has no equivalent validator — honestly reports unconfirmed per Claude's precedent, not a fabricated pass. scripts/verify-codex-native.js (replayable) runs the full read→write→applyChangesOrThrow→confirm chain against real codex 0.145.0. npm test (281 passing, 7 new codex contract assertions); npm run build, check-consistency, docs:build, git diff --check all pass. Two legacy matrix-test assertions about codex (expected codexConfig.approval_policy and codexHooks.hooks.PostToolUse[0].hooks[0].async: undefined) updated to match the new "unsupported/degraded + pass-through" truth, and the legacy commands-as-skill file-path assertion removed (consistent with the documented deprecation). |
| JUE-302 OpenClaw Extension | done | JUE-205 | packages/ai-jue-adapter-openclaw/ rebuilt per the JUE-205 output contract: capabilities/{context,skills,commands,agents,hooks,mcp,manifest,layout}.ts declaration table — with commands/agents/rules/mcp all honestly degraded (OpenClaw has no per-workspace commands//agents/ directory; openclaw agents add/list/delete manages isolated workspaces under the user home, not as project files; MCP is global-only on openclaw.json which this Adapter deliberately does not write to avoid contaminating the operator's global config). hooks.ts is a real hand-written parser of OpenClaw's HOOK.md + handler.js shape (YAML frontmatter with metadata.openclaw.events array, distinct from Claude's flat event names). mcp.ts reads the fixture's openclaw.json mcp.servers; write() is a no-op (defensive against global-config pollution). read.ts/write.ts are thin compositions over readCapabilities/writeCapabilities, routed through core-executor.ts applyChangesOrThrow. test/contract.test.ts calls JUE-202's defineAdapterContractSuite for both equivalence contracts + idempotency + unmanaged-field preservation + sensitive-reference rejection (5 assertions, all green). Native confirmation: OpenClaw 2026.5.5's strongest local validator is openclaw config validate --json; the Adapter's confirmNatively runs the full round-trip in an isolated --profile (copies the fixture's openclaw.json to ~/.openclaw-<profile>/, then execFileSync against the real CLI). One empirically discovered openclaw quirk: openclaw config validate --json produces empty stdout when called via execFileSync/spawnSync from inside the vitest worker process (works fine from a normal shell). The contract suite therefore does not call confirmNatively per the honest-degraded-stance principle; real native confirmation lives in scripts/verify-openclaw-native.js, which runs in a normal shell context and passes against real openclaw 0.145.0. npm test (285 passing, 5 new) + npm run build/check-consistency/docs:build/git diff --check all pass. |
| JUE-303 Hermes Extension | done | JUE-205 | packages/ai-jue-adapter-hermes/ built to the JUE-205 output contract: capabilities/{context,skills,mcp,cron,commands,agents,hooks,manifest,layout}.ts declaration tables + read.ts/write.ts/confirm.ts/index.ts assembling an Adapter + defineExtension(); capabilities honestly declares rules: "unsupported", hooks: "unsupported" (the real install's ~/.hermes/hooks/ is empty), commands: "degraded", agents: "degraded" (all no-op pass-throughs), skills: "supported" (three-level skills/<category>/<name>/SKILL.md, deeper than Claude/Codex/OpenClaw's one level), mcp: "supported". test/contract.test.ts runs the JUE-202 shared suite: both equivalence contracts, idempotency, unmanaged-field preservation, sensitive-reference rejection. Native confirmation: real tirith config validate <artifactRoot> (Hermes's own binary, run against an isolated temp HOME); scripts/verify-hermes-native.js replays it (requires the real tirith binary on PATH); project scope honestly reports unconfirmed when there's no aggregate to confirm. Fixed a real implementation bug in the process: confirm.ts previously concatenated the command and its arguments into one string passed to execFileSync(cmd, options) — since execFileSync never tokenizes via a shell, the whole spaced string would be treated as a literal executable name and always throw ENOENT regardless of whether tirith exists; now calls execFileSync("tirith", ["config", "validate", artifactRoot], options). npm test (292 passing); npm run build, check-consistency, docs:build, git diff --check all pass. Open architecture question: this Adapter adds a cron field to CanonicalDocumentSchema (a full-file pass-through of cron/jobs.json) that is not one of the six atomic Capability types; whether to formally adopt it has not been decided via an RFC — see implementation-status.md's "Critical gaps" |
| JUE-304 Cursor Plugin Artifact | done | JUE-205 | packages/ai-jue-adapter-cursor/ completed project/plugin dual-layout round-trip: capabilities/{layout,manifest,context,rules,commands,skills,agents,hooks,mcp,cursor-tools}.ts all parameterized by artifactKind; plugin hooks write { hooks } (no version), project hooks write { version: 1, hooks }; tools.cursor.pluginManifest → .cursor-plugin/plugin.json (with variables passthrough); Core artifact-kind.ts registers cursor: ["project","plugin"]; fixtures/{project,plugin,plugin-minimal}/ + test/{contract,read,hooks-shape,plugin-manifest}.test.ts; scripts/smoke-local-preset.js gains a cursor plugin branch; ai-assets apply --adapter cursor --artifact plugin end-to-end verified. confirm() has no official headless CLI, so both project and plugin report unconfirmed (plugin with structural evidence). fixtures/failures/ records literal-credential rejection, hook path-escape rejection, and unknown-event pass-through. OpenClaw bundleFormat: "cursor" delegates to the Cursor plugin layout. Follow-ups: #8 marketplace.json |
R4: Cross-Agent conversion and --all
| Task | Status | Dependency | Evidence |
|---|---|---|---|
| JUE-401 portable Canonical fixture | done | JUE-301, JUE-302, JUE-303 | packages/ai-jue-adapter-hermes/audit/JUE-401-portable-canonical.md: a portable-subset coverage matrix verified directly against the four R3 Adapters' capabilities declarations — context/skills are supported on all four (each via directoryPerItem/an equivalent hand-written mapping plus managedMarkdownFile/extractManagedContent); mcp is fully supported only by Claude/Hermes, degraded on Codex (read-only), and unhandled on OpenClaw (global-only); commands/agents/rules/hooks are each rated for portability, with concrete native projection paths listed for all four targets over the portable subset (context + skills). This matrix is a coverage claim whose acceptance evidence is each Adapter's own JUE-202 contract suite (5/5 passing each); no separate test was added |
| JUE-402 pairwise conversion | ready | JUE-401 | A Native → Canonical → B Artifact → Canonical equals B-supported projection |
| JUE-403 private preservation | ready | JUE-402 | Native-private fields survive only same-target updates |
JUE-404 apply --all | — | JUE-403 | One Canonical input creates four targets whose reads equal their projections |
| JUE-405 concurrency and isolation | — | JUE-404 | One target failure creates no partial writes elsewhere; accurate diagnostics/exits |
| JUE-406 final regression | — | JUE-405 | Four fixtures, cross matrix, idempotency, security, and documentation gates |
R5: ai-assets real-consumer acceptance
R5 starts only after the R4 architecture and cross-conversion gate. ai-assets does not define Canonical DSL, but it is the final product acceptance corpus, not an optional smoke.
| Task | Dependency | Evidence |
|---|---|---|
| JUE-501 redacted capability inventory | JUE-406 | Every ai-assets capability, composition, native dependency, and sensitive boundary has a redacted inventory entry |
| JUE-502 migrate to Jue Preset | JUE-501 | One Capability per leaf reference, composition only in Preset, all Canonical-schema valid |
| JUE-503 four-target Artifacts | JUE-502 | One Preset emits project and official aggregate Plugin/Bundle Artifacts for Claude Code, Codex, OpenClaw, and Hermes |
| JUE-504 four-target native usability | JUE-503 | Official install/discovery and representative real invocation per target, with no silent inventory loss |
| JUE-505 lossless matrix | JUE-504 | Every capability is portable or has a semantically equivalent target Artifact on all four targets; zero degraded, unsupported, or blocked |
| JUE-506 final user loop | JUE-505 | One ai-assets Preset apply --all, four usable targets, equivalent reverse reads, zero-diff second apply, and no sensitive disclosure |
“Lossless” compares capability semantics, composition, scope, activation, and required runtime dependencies; it does not require identical native layouts. Adapters express target-specific Plugins and other Artifacts without adding target-private fields to Canonical.
Global gate
npm test
npm run build
npm run check-consistency
npm --prefix packages/docs run docs:build
git diff --checkTests lock logical facts. Headless, official parser/inventory, and real discovery lock runtime physical facts. Both are required.