Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# Receipt-bound release tests inspect the PR head's parent when
# Actions checks out its synthetic merge commit.
fetch-depth: 3

- name: Setup Node
uses: actions/setup-node@v4
Expand Down
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,19 @@ required to run the stewardship pipeline.
sane defaults, route context, define workflows, and make the system feel like
one assistant instead of a pile of software.

For coding work, jarvOS-coding bundles a managed Compound Engineering provider
behind the ordinary jarvOS verbs. Say `plan`, `work`, or `complete`; a healthy,
approved provider supplies the stronger planning and execution loop while
jarvOS keeps ownership of the work run, branch, review evidence, submission
gate, and completion decision. Provider learning is a separate, post-verification
tail: `compound` may capture one reusable lesson, but a skipped or failed lesson
never changes a verified coding result. If the provider is missing, modified,
unsupported, or unavailable, jarvOS continues through its native workflow in
the same run and worktree.
For coding work, jarvOS-coding provides a managed run through the public
`plan → accept-plan → work → finish/status/resume` entry. Direct invocation is
the deterministic path: jarvOS owns the work run, branch, review evidence,
submission gate, and completion decision. Automatic learning is a separate
post-verification tail and applies only to verified jarvOS-managed runs in
configured repositories; it never changes a verified coding result.

Natural routing is currently unavailable: the installed skill is not yet backed
by a current authenticated Codex routing receipt. It must not be assumed to
intercept arbitrary Codex edits. Use the direct managed entry until a live
conformance receipt meets the committed selection and zero-false-claim gates.
If the provider is unavailable, the native jarvOS fallback continues in the
same run and same worktree.

Provider installation is managed software, not a JavaScript dependency or a
moving upstream branch. jarvOS ships one reviewed pin, preserves unrelated
Expand Down
95 changes: 93 additions & 2 deletions lib/jarvos-cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@ const path = require('path');
const { spawnSync } = require('child_process');
const { loadHealthModules } = require('./jarvos-doctor-modules');
const { inspectCompoundEngineeringProvider } = require('../modules/jarvos-runtime-kit/src');
const {
inspectProvisionedRepositories,
provisionRepository,
recordOwnerAction,
revokeProvisionedRepository,
updateProvisionedRepository,
} = require('../modules/jarvos-coding/src');

const ROOT = path.resolve(__dirname, '..');
const MIN_NODE_MAJOR = 18;
const COMMANDS = new Set(['help', 'init', 'doctor']);
const COMMANDS = new Set(['help', 'init', 'doctor', 'coding']);
const LEGACY_INIT_ALIASES = new Set(['jarvos-bootstrap', 'jarvos-init']);
const REQUIRED_WORKSPACE_FILES = [
'AGENTS.md',
Expand Down Expand Up @@ -530,6 +537,7 @@ function renderHelp() {
Usage:
jarvos init [--profile minimal] [bootstrap options]
jarvos doctor [--profile minimal|local-openclaw|v0-5-0] [--workspace path] [--config path] [--json]
jarvos coding <repository|accept|learning> ...
jarvos help

Profiles:
Expand All @@ -539,6 +547,82 @@ Compatibility:
jarvos-bootstrap and jarvos-init route to jarvos init for one migration release.`;
}

function renderCodingHelp() {
return `jarvos coding

Owner-only repository provisioning. Every command requires an explicit --registry
path; jarvOS never infers repository authority from the current directory.

Usage:
jarvos coding repository add --registry /absolute/registry.json --repository-json '{...}' [--json]
jarvos coding repository inspect --registry /absolute/registry.json [--json]
jarvos coding repository update --registry /absolute/registry.json --repository-id ID --repository-json '{...}' [--json]
jarvos coding repository revoke --registry /absolute/registry.json --repository-id ID [--json]
jarvos coding accept --registry /absolute/registry.json --repository-id ID --run-id ID --revision DIGEST --packet-digest DIGEST [--json]
jarvos coding learning decline --registry /absolute/registry.json --repository-id ID --run-id ID [--json]
jarvos coding learning reset-retry --registry /absolute/registry.json --repository-id ID --run-id ID [--json]

Repository JSON must supply explicit root, stateRoot, tracker, worktreePolicy,
acceptancePolicy, providerEgressPolicy, credentialReferences, learning, and
learningPublicationTarget. Registry data and owner-action records are restricted
to the invoking owner; normal receipts expose only public labels and opaque IDs.`;
}

function parseCodingArgs(argv = []) {
const result = { positionals: [], options: {}, json: false };
for (let index = 0; index < argv.length; index += 1) {
const value = argv[index];
if (value === '--help' || value === '-h') { result.help = true; continue; }
if (value === '--json') { result.json = true; continue; }
const match = value.match(/^--(registry|repository-id|repository-json|run-id|revision|packet-digest)=(.*)$/);
if (match) { result.options[match[1]] = match[2]; continue; }
if (['--registry', '--repository-id', '--repository-json', '--run-id', '--revision', '--packet-digest'].includes(value)) {
if (!argv[index + 1]) throw new Error(`${value} requires a value`);
result.options[value.slice(2)] = argv[++index]; continue;
}
if (value.startsWith('-')) throw new Error(`unknown coding option: ${value}`);
result.positionals.push(value);
}
return result;
}

function renderCodingReceipt(receipt, json) {
if (json) return JSON.stringify(receipt, null, 2);
const repository = receipt.repository || receipt.repositories?.[0];
const identity = repository ? ` ${repository.label || repository.publicLabel} (${repository.repositoryId})` : '';
return `${receipt.action || 'inspected'} generation ${receipt.generation}${identity}`;
}

function runCoding(argv = []) {
try {
const parsed = parseCodingArgs(argv);
if (parsed.positionals[0] === 'help' || parsed.positionals.length === 0 || parsed.help) {
process.stdout.write(`${renderCodingHelp()}\n`); return 0;
}
const [area, operation] = parsed.positionals;
const options = parsed.options;
let receipt;
if (area === 'repository') {
if (operation === 'inspect') receipt = inspectProvisionedRepositories({ registryPath: options.registry });
else if (operation === 'add') receipt = provisionRepository({ registryPath: options.registry, repository: JSON.parse(options['repository-json'] || '') });
else if (operation === 'update') receipt = updateProvisionedRepository({ registryPath: options.registry, repositoryId: options['repository-id'], repository: JSON.parse(options['repository-json'] || '') });
else if (operation === 'revoke') receipt = revokeProvisionedRepository({ registryPath: options.registry, repositoryId: options['repository-id'] });
else throw new Error('repository operation must be add, inspect, update, or revoke');
} else if (area === 'accept' && operation === undefined) {
receipt = recordOwnerAction({ registryPath: options.registry, repositoryId: options['repository-id'], action: 'accept-plan', runId: options['run-id'], revision: options.revision, packetDigest: options['packet-digest'] });
} else if (area === 'learning' && operation === 'decline') {
receipt = recordOwnerAction({ registryPath: options.registry, repositoryId: options['repository-id'], action: 'decline-learning', runId: options['run-id'] });
} else if (area === 'learning' && operation === 'reset-retry') {
receipt = recordOwnerAction({ registryPath: options.registry, repositoryId: options['repository-id'], action: 'reset-learning-retry', runId: options['run-id'] });
} else throw new Error('coding operation is not supported');
process.stdout.write(`${renderCodingReceipt(receipt, parsed.json)}\n`);
return 0;
} catch (error) {
process.stderr.write(`jarvos coding failed: ${error.message}\n`);
return 1;
}
}

function renderInitHelp() {
const profiles = listProfiles();
const profileLines = profiles.length
Expand Down Expand Up @@ -636,7 +720,7 @@ async function runCli(argv = process.argv.slice(2), env = process.env, invokedAs
const normalizedArgv = normalizeArgvForInvocation(argv, invokedAs);
const parsed = parseArgs(normalizedArgv);
if (parsed.command === 'help'
|| parsed.help && !['doctor', 'init'].includes(parsed.command)) {
|| parsed.help && !['doctor', 'init', 'coding'].includes(parsed.command)) {
process.stdout.write(`${renderHelp()}\n`);
return 0;
}
Expand All @@ -645,6 +729,10 @@ async function runCli(argv = process.argv.slice(2), env = process.env, invokedAs
return runInit(normalizedArgv.slice(1), env);
}

if (parsed.command === 'coding') {
return runCoding(normalizedArgv.slice(1));
}

if (parsed.command === 'doctor') {
if (parsed.help) {
process.stdout.write(`${renderDoctorHelp()}\n`);
Expand Down Expand Up @@ -700,6 +788,9 @@ module.exports = {
parseArgs,
renderDoctor,
renderDoctorHelp,
renderCodingHelp,
parseCodingArgs,
runCoding,
renderHelp,
renderInitHelp,
resolveDoctorContext,
Expand Down
11 changes: 8 additions & 3 deletions modules/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,14 @@ const {
} = require('@jarvos/coding');
```

Both adapters register the `jarvos_coding_take_issue_to_done` MCP-style tool and
a `jarvos-coding` skill descriptor when the host supplies a registry. Both call
the same `runTakeIssueToDone` orchestrator.
Both adapters can register the `jarvos_coding_take_issue_to_done` compatibility
tool and a `jarvos-coding` skill descriptor when the host supplies a registry.
Codex's managed public entry is the lifecycle
`plan → accept-plan → work → finish/status/resume`; direct invocation is the
deterministic access path. Natural routing is currently unavailable, so no
global skill installation claims to intercept arbitrary edits or create a
managed run automatically. Automatic learning applies only after a verified
managed run in a configured repository.

---

Expand Down
26 changes: 16 additions & 10 deletions modules/jarvos-coding/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,14 @@ await codex.runTakeIssueToDone({ issueIdentifier: 'SUP-2214' });

## Managed coding workflow

`createManagedCodingWorkflow(...)` is the provider-neutral route for natural
coding verbs. It owns one durable work run and resolves the approved
Compound Engineering manifest before invoking a provider adapter:
`createManagedCodingWorkflow(...)` is the provider-neutral route behind the
direct managed coding lifecycle. It owns one durable work run and resolves the
approved Compound Engineering manifest before invoking a provider adapter:

```text
plan -> validate draft -> accept one implementation packet -> work -> complete
|
verified learning -> compound (optional)
plan -> validate draft -> accept one implementation packet -> work -> finish
|
status/resume -> verified learning -> compound (optional)
```

The provider is a managed external artifact pinned by
Expand All @@ -158,10 +158,16 @@ reattachment hints.
The Codex adapter is the first conformance-backed CE route. The runtime accepts
CE 3.21.4 only when the discovered installation matches the approved immutable
pin and the reviewed disposable-profile receipt. Run `jarvos doctor` to see the
approved and discovered versions. If the provider is absent, modified,
disabled, or unavailable, `plan`, `work`, and `complete` fall back to the native
jarvOS route in the same work run and worktree. A failed fallback does not make
a second branch, plan, pull request, or completion claim.
approved and discovered versions. Use `plan → accept-plan → work →
finish/status/resume` through the public MCP lifecycle; if the provider is
absent, modified, disabled, or unavailable, the same managed run may use the
native route after reconciliation. A failed fallback does not make a second
branch, plan, pull request, or completion claim.

Natural routing is currently unavailable. Deterministic behavior starts at the
direct coding invocation, and automatic learning applies only after a verified
managed run in a configured repository. Arbitrary unmanaged Codex edits do not
receive automatic learning capture.

Learning capture is deliberately independent of coding completion. It runs only
after live review, tests, pull-request, post-merge, and close evidence establish
Expand Down
6 changes: 5 additions & 1 deletion modules/jarvos-coding/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
"description": "Portable jarvOS coding orchestrator with thin Claude Code, Codex, and OpenClaw host adapters.",
"license": "MIT",
"main": "src/index.js",
"bin": {
"jarvos-coding-mcp": "scripts/jarvos-coding-mcp.js"
},
"files": [
"README.md",
"src/",
"providers/"
"providers/",
"scripts/"
],
"exports": {
".": "./src/index.js"
Expand Down
Loading
Loading