Skip to content

CLI JSON Output

OpenLogos CLI supports --format json on five command families — status, next, verify, smoke, detect, and module list — producing structured JSON for programmatic consumption by external tools like RunLogos.

  • Trigger: Append --format json to any supported command
  • Output target: JSON goes to stdout; errors go to stderr
  • Format: Compact single-line JSON (no indentation), suitable for piping
  • Exit codes: Same as human-readable mode
  • Encoding: UTF-8
  • Field naming: snake_case

All commands share a common envelope:

{
"command": "<command-name>",
"version": "<cli-version>",
"timestamp": "<ISO-8601>",
"data": { ... }
}

Where command is one of: "status", "next", "verify", "smoke", "detect", "module list".

Terminal window
openlogos detect --format json

Returns CLI version, Node.js version, and project detection information:

{
"cli": {
"version": "0.12.9",
"node_version": "v22.0.0"
},
"project": {
"name": "my-project",
"locale": "zh",
"lifecycle": "launched",
"modules": [
{ "id": "core", "name": "核心功能", "lifecycle": "launched" }
],
"description": "项目描述",
"source_roots": { "src": ["src"], "test": ["test"] }
},
"yaml_diagnostics": null
}

project is null when run outside an OpenLogos project.

Terminal window
openlogos status --format json

Returns phase progress, module state, active proposals, and suggestions:

Key fieldDescription
phases[]All 13 phases with key, label, done, skipped, files
modules[]Per-module lifecycle, current phase, phase progress, active change, suggestion
modules[].active_changeProposal step, task progress, deployment decision, conflict detection
modules[].active_change.code_requiredSingle source of truth for “does this proposal need code” (see below)
current_phaseFirst incomplete phase key (or null if all done)
lifecycleProject lifecycle derived from module states
yaml_diagnosticsParse recovery status if YAML has issues

The proposal_step field tracks change proposal lifecycle:

StepMeaning
writingProposal/tasks still has template placeholders
ready-to-deltaProposal + tasks filled, no delta yet, PLAN_APPROVED absent — the plan-exit “approve plan” gate
delta-writingProposal filled; delta tasks not all checked
ready-to-mergeAll delta tasks checked (the spec-exit gate)
merge-generatedopenlogos merge has run
ready-to-implementSpecs merged, code_required, [code] slices not yet written by slice-planner — the slice-exit “approve slices” gate
codingSlices approved; code tasks not all checked
ready-to-verifyAll code tasks checked
verify-passedopenlogos verify passed
verify-failedopenlogos verify failed
ready-to-deployVerify passed, deployment pending (the deliver-entry gate)
deploy-doneDeployment executed
ready-to-smokeDeployment done, smoke pending
smoke-passedopenlogos smoke passed
smoke-failedopenlogos smoke failed

ready-to-delta and ready-to-implement were added by the change-flow redesign and the slice-planner split respectively; consumers (including RunLogos) must recognise them. implementing / in-progress remain legacy-compatible values.

modules[].active_change.code_required (boolean) is the single source of truth for whether a proposal needs code implementation. It equals the internal predicate isCodeRequiredForProposaltrue when the proposal carries a ## [code] requirement (a [code] section, [delta]-added UT-*/ST-*/SMOKE-*, or a proposal-level code declaration), false for pure-doc / pure-spec proposals. Consumers should read this field directly instead of re-guessing with keyword regexes.

  • Appears only when active_change is non-null; with no active proposal the whole object (and this field) is absent, so projects without an active proposal see no new fields (golden zero-drift).
  • Consistency: code_required==falsenext_node.id is never code/plan-slices and the slice subflow (when: code_required) is skipped entirely. code_required==true with [code] still on template ⟹ proposal_step=="ready-to-implement", next_node.id=="plan-slices".

These fields drive external orchestrators. All follow the same mount + omit rule: with modules[] present they mount at modules[].*; legacy projects fall back to the top level; consumers read modules[].* first, then the top level. Each is omitted entirely when inactive, preserving golden zero-drift.

loop_state — present only when the implement loop is active (max_iters > 1; builtin launched satisfies this by default):

FieldTypeDescription
subflow_idstringThe loop’s subflow id (e.g. implement)
untilstringConvergence predicate (tests_green | code_slices_green)
max_itersnumberResolved iteration ceiling
iterationnumberCompleted verify rounds (LOOP_ITERS lines for the current module)
convergedbooleanLast verify round green
escalatedbooleaniteration >= max_iters && !converged (hit the ceiling unconverged)
exhausted_skippableboolean | omittedWhether the loop-exhausted gate can be released by --auto; emitted only when the overlay set-loop wrote exhausted_gate

slice_state — present only when the slice loop is active (until == code_slices_green && max_iters > 1; always on under launched):

FieldTypeDescription
totalnumberTotal [code] slices
donenumberChecked slices (section_complete:code count)
currentstring | omittedFirst unchecked [code] line title; omitted when all done
remainingnumbertotal - done

plan_state — a launched diagnostic object so consumers do not mistake tasks.md checkbox progress for a planning failure:

FieldTypeDescription
plan_readybooleanproposal/tasks out of template, no plan-layer block
plan_gate_pendingbooleanStopped at plan-exit: ready-to-delta && PLAN_APPROVED absent
plan_approvedbooleanPLAN_APPROVED present, or already past ready-to-delta
tasks_template_filledbooleantasks.md out of template with valid section structure
tasks_execution_done / tasks_execution_totalnumberCheckbox progress of the current section — must not be used to infer plan readiness
tasks_execution_scopestringdelta | deploy | code | none
diagnosticstringShort human/driver note on the waiting or blocking state

next_node (on openlogos next only) — the orchestration hint for the node to handle this turn, carrying skill / working_agent / review_agent / pre_script / post_script from the resolved flow. It defaults to the current frontier node, with exceptions:

  • In the slice loop (unconverged, below ceiling) it points to the code work node and carries next_node.slice (= slice_state.current, “only do this slice”).
  • At a slice/plan gate it carries next_node.gate_id alongside id — e.g. ready-to-implement with plan-slices done emits id: "plan-slices" + gate_id: "slice-exit", telling the host not to re-dispatch the skill but to treat it as a human gate. Gate-id mappings: ready-to-delta → plan-exit, ready-to-merge → spec-exit, ready-to-implement → slice-exit, ready-to-deploy → deliver-entry.
  • It is omitted for command-level suggestions (all_done, openlogos change <slug>, openlogos launch) and after a gate is auto-released.

GATE_AUTO_PASSED — an append-only audit ledger (JSONL) in the active proposal directory. Each time next --auto auto-releases a skippable:true gate it appends {gate_id, proposal_step, timestamp}. It is audit only, not a state source — historical lines never authorize a later deploy or gate; default next (no --auto) ignores them. State advances only on the real marker (PLAN_APPROVED for plan, SLICES_APPROVED for slice) or actual delta/slice output. Deployment release is gated on the live gate_auto_passed === true in the current next --auto response.

Terminal window
openlogos verify --format json

Returns test verification results with three-layer validation:

Key fieldDescription
summaryDefined/executed/passed/failed/skipped/uncovered counts and percentages
gateresult (“PASS”/“FAIL”) and reason
failed_cases[]ID and error for each failure
checklistDesign-time coverage validation status
ac_traceAcceptance criteria traceability status
pre_runPre-run execution mode, commands, result paths, diagnostics
sandboxSandbox isolation mode, status, diagnostics
ModeDescription
noneNo pre-run command configured
pre_run_commandSingle verify.pre_run_command executed
two_phaseregression_command + incremental_command with last-write-wins merge
ReasonDescription
failed_casesOne or more test cases failed
incomplete_coverageSome defined cases have no result
checklist_incompleteDesign-time coverage checklist not fully checked
ac_trace_incompleteAcceptance criteria traceability not fully passed
Terminal window
openlogos smoke --format json
openlogos smoke --env staging --format json

Returns post-deployment smoke verification results:

Key fieldDescription
environmentTarget environment (from --env flag, or null)
summarySame structure as verify summary
gateGate 3.8 result and reason
sandboxSandbox execution status
report_pathGenerated smoke report path
result_pathSmoke results JSONL path
Terminal window
openlogos module list --format json

Returns the module registry:

{
"modules": [
{ "id": "core", "name": "核心功能", "lifecycle": "launched" },
{ "id": "payment", "name": "支付模块", "lifecycle": "initial" }
]
}

When a command fails, JSON mode outputs an error envelope to stderr:

{
"command": "<command-name>",
"version": "<cli-version>",
"timestamp": "<ISO-8601>",
"error": {
"code": "PROJECT_NOT_INITIALIZED",
"message": "logos/logos.config.json not found."
}
}
Error codeDescription
PROJECT_NOT_INITIALIZEDNot in an OpenLogos project
NO_TEST_RESULTSTest results JSONL file not found
NO_TEST_CASESNo test case spec files found
NO_SMOKE_RESULTSSmoke results JSONL file not found
NO_SMOKE_CASESNo smoke case spec files found
Terminal window
# Check gate result in scripts
openlogos verify --format json | jq '.data.gate.result'
# Get current phase
openlogos status --format json | jq '.data.current_phase'
# List module lifecycles
openlogos module list --format json | jq '.data.modules[] | {id, lifecycle}'
# Conditional check
if openlogos verify --format json 2>/dev/null | jq -e '.data.gate.result == "PASS"' > /dev/null; then
echo "All tests passed!"
fi