Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
e57af31
Feat: make overnight qa/simplifier/security_review loop-safe
dzikowski Jul 30, 2026
31c79af
Test: fill QA coverage gaps for CLI, compiler, e2e
dzikowski Jul 30, 2026
541203f
Refactor: apply safe simplifier-pass cleanups across src
dzikowski Jul 30, 2026
61ccb30
Test: fill QA gap-report coverage for CLI, e2e, compiler
dzikowski Jul 30, 2026
369c7b1
Refactor: apply safe simplifier-pass cleanups across src
dzikowski Jul 30, 2026
4db1b62
Test: fill QA gap-report coverage for CLI init and compiler
dzikowski Jul 30, 2026
66cbb30
Refactor: extract shared SINGLE_QUOTE_MESSAGE parse constant
dzikowski Jul 30, 2026
0ae6795
Refactor: extract shared errText and run-meta helpers
dzikowski Jul 30, 2026
0886be9
Docs: queue security-review HIGH/MEDIUM findings as dev-ready tasks
dzikowski Jul 30, 2026
071bb5c
Docs: queue security-review LOW findings as #dev-ready tasks
dzikowski Jul 31, 2026
2eb3951
Fix: shell-quote values interpolated into workflow shell steps
dzikowski Jul 31, 2026
ffc0bbc
Fix: exclude host-only JAIPH_SERVE_* keys from sandbox env forward
dzikowski Jul 31, 2026
b2378bb
Fix: key and verify the run audit journal to resist tampering
dzikowski Jul 31, 2026
e870111
Refactor: split engineer into queue and task-parameter entries
dzikowski Jul 31, 2026
652c29f
Feat: pin and signature-verify jaiph install registry entries
dzikowski Jul 31, 2026
1c1c234
Docs: document registry scheme allowlist and install integrity checks
dzikowski Jul 31, 2026
16f153a
Docs: finalize install/registry integrity docs and e2e coverage
dzikowski Jul 31, 2026
41ee7aa
Feat: treat docker_image/docker_network as host-controlled
dzikowski Jul 31, 2026
4a11d6c
Feat: gate entry-file trusted_envs behind operator opt-in
dzikowski Jul 31, 2026
ef1cfb1
Feat: harden image jaiph-presence probe and drop login shell
dzikowski Jul 31, 2026
0656c14
Feat: reject or distinctly identify sub-less OIDC tokens
dzikowski Jul 31, 2026
ccbfaf6
Feat: gate project-local hooks behind workspace-trust opt-in
dzikowski Jul 31, 2026
7142be8
Feat: fail-closed release install and runtime toolchain verification
dzikowski Jul 31, 2026
2da46ad
Feat: broaden and canonicalise credential redaction
dzikowski Jul 31, 2026
2d4346f
Feat: self-host Swagger UI assets for jaiph serve /docs
dzikowski Jul 31, 2026
15d6571
Chore: run security_review on Claude fable
dzikowski Jul 31, 2026
1123ec0
Feat: redact credentials in durable log/logwarn/logerr journal lines
dzikowski Jul 31, 2026
611c214
Feat: add host-mode run timeout and optional max-step circuit breaker
dzikowski Jul 31, 2026
6a859fb
Feat: pin explicit OIDC JWT algorithms allowlist in jwtVerify
dzikowski Jul 31, 2026
21b5641
Fix: skip empty JAIPH_MINISIGN_PUBLIC_KEY in installer bad-checksum e…
dzikowski Jul 31, 2026
6f2348a
Fix: leave JAIPH_MINISIGN_PUBLIC_KEY unset in e2e setup-action test w…
dzikowski Jul 31, 2026
4cf2835
Fix: re-export CI env inside WSL install step and pin Docker e2e test…
dzikowski Jul 31, 2026
74e2195
Fix: use npm ci and exact-pin jose in local builds
dzikowski Jul 31, 2026
17bfd77
Docs: queue #dev-ready tasks for security review MEDIUM findings
dzikowski Jul 31, 2026
d53b2f6
Docs: queue security-review LOW findings except L-1
dzikowski Jul 31, 2026
4eb8f73
Fix: require explicit unsafe consent for mcp/serve host-only mode
dzikowski Jul 31, 2026
4db0d1d
Fix: stop otlp/sentry export integration tests from hanging test:ci
dzikowski Aug 1, 2026
0ab3313
Feat: kill a leaf script step after an idle-output timeout
dzikowski Aug 1, 2026
871ee55
Feat: pin registry entries to a commit and enforce on install
dzikowski Aug 1, 2026
969c45f
Feat: require signature verification in CI installer and action
dzikowski Aug 1, 2026
c5fc832
Feat: pin runtime image by digest and verify on every run
dzikowski Aug 1, 2026
bcd1442
Fix: redact credentials in generic step params in run journal
dzikowski Aug 1, 2026
34071b4
Feat: reject truncated audit journals via WORKFLOW_END terminal marker
dzikowski Aug 1, 2026
b0b5d75
Feat: pin runtime Dockerfile base images and npm installs
dzikowski Aug 1, 2026
9a6c2e9
Fix: require explicit --allow-anonymous opt-in for serve's open loopb…
dzikowski Aug 1, 2026
bc31cac
Fix: refresh pinned SHA-256 for the rolling uv installer URL
dzikowski Aug 1, 2026
e49f5db
Fix: refresh pinned SHA-256 for AWS CLI v2 downloads
dzikowski Aug 1, 2026
8a88d46
Fix: disambiguate same-second run-directory collisions
dzikowski Aug 1, 2026
7023d77
Docs: accept agent-analyzability ADR and queue enforcement tasks
dzikowski Aug 2, 2026
f97fc49
Fix: verify per-library registry signatures against the embedded key …
dzikowski Aug 2, 2026
76e956a
Chore: enforce agent-analyzability import graph in CI
dzikowski Aug 2, 2026
efa7f15
Feat: enforce agent-analyzability fan-out and size caps via ESLint
dzikowski Aug 2, 2026
463307e
Feat: make src/parser.ts the public parse entry, ban deep imports
dzikowski Aug 2, 2026
bf14d53
Feat: make src/transpiler.ts the public transpile entry, ban deep imp…
dzikowski Aug 2, 2026
24797ef
Feat: add runtime public entry, stop runtime importing CLI
dzikowski Aug 2, 2026
fa2686c
Feat: add format public entry, ban deep imports into format
dzikowski Aug 2, 2026
37d3c27
Feat: enforce CLI slice isolation in dependency-cruiser
dzikowski Aug 2, 2026
be2d71e
Refactor: clear parse/config layer-violation baselines
dzikowski Aug 2, 2026
7bcf561
Fix: hard-kill wedged Docker presence probes so test:ci cannot hang
dzikowski Aug 2, 2026
880869e
Feat: enforce docs summary-first lead and 500-line body cap
dzikowski Aug 2, 2026
6fdc8fd
Feat: sync engineer code_philosophy with agent-analyzability ADR
dzikowski Aug 2, 2026
2f6bd4f
Fix: pin dependency-cruiser to 17.4.3 to unbreak CI
dzikowski Aug 2, 2026
e12642f
Feat: render TTY log lines in blue
dzikowski Aug 3, 2026
e26e44d
Docs: queue operator logging for mcp/serve and analyzability follow-ups
dzikowski Aug 3, 2026
43e1ab7
Fix: skip flaky Docker e2e in engineer CI; land cycle-break
dzikowski Aug 3, 2026
cc18b02
Feat: commands as composition root; queue Docker e2e harden
dzikowski Aug 3, 2026
f743404
Docs: orchestration owns QUEUE removal; harden Docker e2e helpers
dzikowski Aug 3, 2026
0eec1a7
Fix: drop overnight Docker e2e skip; run hardened suite
dzikowski Aug 3, 2026
d8c7100
Docs: mark Docker e2e hardening done; remove queue task
dzikowski Aug 3, 2026
de7bfbf
Fix: restore overnight Docker e2e skip; require full-suite evidence
dzikowski Aug 4, 2026
d9ce9cd
Fix: Docker e2e flakes from probe misclassify and 74d leftover race
dzikowski Aug 4, 2026
92bcec0
Fix: drop overnight Docker e2e skip after full suite ×3 green
dzikowski Aug 4, 2026
87997c8
Refactor: move MCP + workflow-call into cli/shared; clear peer-slice …
dzikowski Aug 4, 2026
64fd72b
Fix: avoid false positive on overnight Docker skip guard
dzikowski Aug 4, 2026
ef1ba69
Docs: record cleared peer CLI slice baseline
dzikowski Aug 4, 2026
88389c7
Refactor: expose runtime test seams via src/runtime/testing.ts
dzikowski Aug 4, 2026
2ca546f
Refactor: collapse transpile to one public entry (src/transpiler.ts)
dzikowski Aug 4, 2026
adfcba6
Refactor: split hotspot files, drop 12 ESLint grandfather overrides
dzikowski Aug 4, 2026
7a291aa
Docs: refresh agent-analyzability ADR to landed enforcement
dzikowski Aug 4, 2026
b4a8c8f
Feat: add operator log to jaiph mcp and serve
dzikowski Aug 4, 2026
e8ee59c
Fix: refresh pinned SHA-256 for AWS CLI v2 downloads
dzikowski Aug 4, 2026
0afecc7
Docs: call out isolating sensitive data in Why Jaiph
dzikowski Aug 5, 2026
1875ee5
Release: stamp v0.13.0 and clarify factory-deploy unsafe consent
dzikowski Aug 6, 2026
d32b564
Fix: refresh pinned SHA-256 for install script and uv installer
dzikowski Aug 6, 2026
b191300
Fix: refresh pinned SHA-256 for AWS CLI v2 downloads
dzikowski Aug 6, 2026
b8c7a7e
Fix: refresh pinned SHA-256 for Cursor installer
dzikowski Aug 6, 2026
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
1 change: 1 addition & 0 deletions .dependency-cruiser-known-violations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
145 changes: 145 additions & 0 deletions .dependency-cruiser.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// Enforces the agent-analyzability import graph: the layer DAG and no-cycles
// invariant from docs/agent-analyzability.md. `npm run arch:check` runs this.
// Layer paths (downward-only imports):
// 4 CLI src/cli/**, src/cli.ts
// 3 Runtime src/runtime/** (may reuse compile only through the
// single public entry src/transpiler.ts)
// 2 Compile src/transpile/**, src/transpiler.ts
// 1 Parse/fmt src/parse/**, src/parser.ts, src/format/**
// 0 Shared src/types.ts, src/errors.ts, src/diagnostics.ts, src/version.ts,
// src/env-reserved.ts, src/inline-script-name.ts
// The table in docs/agent-analyzability.md is authoritative; keep these in sync.

const LAYER0 =
"^src/(types|errors|diagnostics|version|env-reserved|inline-script-name)\\.ts$";
const LAYER1 = "^src/(parse/|parser\\.ts$|format/)";
const LAYER2 = "^src/(transpile/|transpiler\\.ts$)";
const LAYER3 = "^src/runtime/";
const LAYER4 = "^src/(cli/|cli\\.ts$)";

// CLI slice isolation: these vertical slices must not import each other's
// private files. Cross-slice reuse goes through src/cli/shared/** or lower-layer
// public entries. See docs/agent-analyzability.md "CLI slice isolation".
// `commands` is the composition root: it wires the other slices together, so it
// is allowed to import them. CLI_PEER_SLICE (commands excluded) is the set of
// slices that must NOT import each other — peer coupling is the real
// analyzability problem the rule targets.
const CLI_SLICE = "^src/cli/(commands|run|serve|mcp|exec|telemetry)/";
const CLI_PEER_SLICE = "^src/cli/(run|serve|mcp|exec|telemetry)/";

module.exports = {
forbidden: [
{
name: "no-circular",
comment:
"Cycles break the 'direct deps' interfaces suffice' analyzability story: each side needs the other's body.",
severity: "error",
from: {},
to: { circular: true },
},
{
name: "layer0-shared-leaf-no-upward",
comment:
"Shared leaf (layer 0) may import only other layer-0 files, never parse/format/transpile/runtime/cli.",
severity: "error",
from: { path: LAYER0 },
to: { path: `${LAYER1}|${LAYER2}|${LAYER3}|${LAYER4}` },
},
{
name: "layer1-parse-format-no-upward",
comment:
"Parse/format (layer 1) may import only layer 0, never transpile/runtime/cli.",
severity: "error",
from: { path: LAYER1 },
to: { path: `${LAYER2}|${LAYER3}|${LAYER4}` },
},
{
name: "layer2-transpile-no-upward",
comment:
"Compile (layer 2) must not import runtime or cli (generalizes no-runtime-imports.test.ts).",
severity: "error",
from: { path: LAYER2 },
to: { path: `${LAYER3}|${LAYER4}` },
},
{
name: "layer3-runtime-no-cli",
comment: "Runtime (layer 3) must not import cli (layer 4).",
severity: "error",
from: { path: LAYER3 },
to: { path: LAYER4 },
},
{
name: "layer3-runtime-only-transpile-public-graph",
comment:
"Runtime may reuse the transpile package only through its single public entry (src/transpiler.ts, which re-exports the module-graph API), never src/transpile/** internals (validators, emit, module-graph.ts, etc.).",
severity: "error",
from: { path: LAYER3 },
to: { path: "^src/transpile/" },
},
{
name: "no-deep-imports-into-parse",
comment:
"Parse is a deep module: code OUTSIDE the parse package imports only its public entry (src/parser.ts), never src/parse/** internals. Add a named re-export to src/parser.ts instead of reaching in.",
severity: "error",
from: { pathNot: "^src/(parse/|parser\\.ts$)" },
to: { path: "^src/parse/" },
},
{
name: "no-deep-imports-into-transpile",
comment:
"Transpile is a deep module: code OUTSIDE the transpile package imports only its single public entry (src/transpiler.ts, which re-exports the module-graph API), never module-graph/validator/emit/build internals. Add a named re-export to src/transpiler.ts instead of reaching in.",
severity: "error",
from: { pathNot: "^src/(transpile/|transpiler\\.ts$)" },
to: { path: "^src/transpile/" },
},
{
name: "no-deep-imports-into-runtime",
comment:
"Runtime is a deep module: code OUTSIDE the runtime package imports only its public entries — src/runtime/index.ts (production surface) or src/runtime/testing.ts (named test seams for cross-package *.test.ts) — never src/runtime/** internals (docker, docker-inplace, embedded-assets, kernel/*). Add a named re-export to src/runtime/index.ts (production) or src/runtime/testing.ts (test-only seams) instead of reaching in.",
severity: "error",
from: { pathNot: "^src/runtime/" },
to: { path: "^src/runtime/", pathNot: "^src/runtime/(index|testing)\\.ts$" },
},
{
name: "no-deep-imports-into-format",
comment:
"Format is a deep module: code OUTSIDE the format package imports only its public entry (src/format/index.ts), never src/format/** internals (emit.ts). Add a named re-export to src/format/index.ts instead of reaching in.",
severity: "error",
from: { pathNot: "^src/format/" },
to: { path: "^src/format/", pathNot: "^src/format/index\\.ts$" },
},
{
name: "no-cross-cli-slice-imports",
comment:
"Peer CLI slices (run/serve/mcp/exec/telemetry) are vertical features that must not import each other's private files. Cross-slice reuse goes through src/cli/shared/** or a lower-layer public entry. `commands` is the composition root and is deliberately absent from `from` (CLI_PEER_SLICE): it may import any slice to wire them together. The $1 backreference lets same-slice imports through: to.pathNot excludes the slice captured in from.path.",
severity: "error",
from: { path: CLI_PEER_SLICE },
to: { path: CLI_SLICE, pathNot: "^src/cli/$1/" },
},
{
name: "no-orphans",
comment:
"Orphan modules (no incoming or outgoing deps) are usually dead code or a missing wiring.",
severity: "warn",
from: {
orphan: true,
pathNot: [
"\\.d\\.ts$",
"(^|/)tsconfig\\.json$",
"\\.test\\.ts$",
"\\.acceptance\\.test\\.ts$",
],
},
to: {},
},
],
options: {
doNotFollow: { path: "node_modules" },
tsConfig: { fileName: "tsconfig.json" },
tsPreCompilationDeps: true,
enhancedResolveOptions: {
exportsFields: ["exports"],
conditionNames: ["import", "require", "node", "default", "types"],
},
},
};
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Enforce agent-analyzability import graph (layer DAG, no cycles)
run: npm run arch:check

- name: Enforce agent-analyzability caps (max-dependencies, max-lines)
run: npm run lint

- name: Run core test suite (unit and acceptance)
run: npm test

Expand Down Expand Up @@ -268,6 +274,11 @@ jobs:
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
export JAIPH_UNSAFE=true
# wsl.exe does not forward the parent runner's env into this Linux
# session, so CI (which docs/install treats as "trusted toolchain,
# checksum-only OK when minisign is absent") must be re-set here —
# this WSL shell IS the CI runner, just one hop removed.
export CI=true
SUDO=
if [ "$(id -u)" -ne 0 ]; then
SUDO=sudo
Expand Down
24 changes: 4 additions & 20 deletions .github/workflows/nightly-engineer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,6 @@ name: Nightly Engineer Run

on:
workflow_dispatch:
inputs:
engineer_type:
description: "Engineer role (auto uses task classification)"
required: false
default: "auto"
type: choice
options:
- auto
- surgical
- reductionist
- optimizer
- stabilizer

permissions:
contents: write
Expand Down Expand Up @@ -83,13 +71,9 @@ jobs:
shell: bash
run: |
set -euo pipefail

engineer_type="${{ inputs.engineer_type }}"
if [ "${engineer_type}" = "auto" ]; then
./.jaiph/engineer.jh
else
./.jaiph/engineer.jh -- "${engineer_type}"
fi
# Queue-driven entry: picks first #dev-ready QUEUE.md task and
# auto-classifies the engineer role (no role CLI arg).
./.jaiph/engineer.jh

- name: Create worktree patch artifact
if: always()
Expand Down Expand Up @@ -190,6 +174,6 @@ jobs:
Automated engineer run from workflow dispatch.

- Base branch: `nightly`
- Engineer type: `${{ inputs.engineer_type }}`
- Entry: queue-driven `.jaiph/engineer.jh` (auto-classified role)
EOF
)" --head "${branch_name}" --base nightly
9 changes: 5 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,11 @@ jobs:
set -euo pipefail
rm -f SHA256SUMS.minisig
if [ -z "${MINISIGN_SECRET_KEY}" ]; then
echo "MINISIGN_SECRET_KEY secret is not set — skipping detached signature." >&2
echo "Set the secret to enable signed releases (see docs/contributing.md)." >&2
echo "Installers fail closed without SHA256SUMS.minisig; do not upload an empty stub" >&2
echo "(GitHub rejects 0-byte release assets with HTTP 400 Bad Content-Length)." >&2
echo "MINISIGN_SECRET_KEY secret is not set — refusing to publish an unsigned release." >&2
echo "Installers fail closed without SHA256SUMS.minisig (finding M-5): publishing" >&2
echo "unsigned would strip the only out-of-band integrity check for every consumer." >&2
echo "Set the MINISIGN_SECRET_KEY secret to enable signed releases (docs/contributing.md)." >&2
exit 1
else
command -v minisign >/dev/null
key_file="$(mktemp)"
Expand Down
94 changes: 73 additions & 21 deletions .jaiph/engineer.jh
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
#!/usr/bin/env jaiph

#
# Picks the first pending task from QUEUE.md, implements it, verifies CI,
# updates docs, removes from queue, and publishes a workspace patch artifact.
# Implement a task: code, CI, docs, commit patch.
#
# CLI / overnight (queue-driven):
# jaiph run .jaiph/engineer.jh
# → default → implement_from_queue (first #dev-ready QUEUE.md task).
#
# Hub / serve / mcp (task parameter, no QUEUE.md):
# export workflow implement_from_task(task) — used by .jaiph/main.jh engineer(task)
#
import "jaiphlang/artifacts" as artifacts
import "jaiphlang/claude" as claude
Expand Down Expand Up @@ -33,15 +39,20 @@ const safety_constraints = """
Nested sessions share runtime resources and can crash active sessions.
- Do not attempt to bypass nested-session guards (for example by unsetting
environment variables such as CLAUDECODE).
- Do not modify QUEUE.md in any way (no deleting the current task, no
rewriting headers/bodies, no reordering). QUEUE.md process rule 4 is
for orchestration only: after a successful implement, the workflow calls
queue.remove_completed_task. If you believe a task is done, finish
acceptance work and stop — do not edit the queue file yourself.
- Any violation of these constraints is an immediate task failure; stop and report.
"""

const definition_of_done = """
Definition of done (QUEUE.md rule 7, verbatim):
"Acceptance criteria are non-negotiable. A task is not done until every
Definition of done:
Acceptance criteria are non-negotiable. A task is not done until every
acceptance bullet is verified by a test that fails when the contract is
violated. 'It works on my machine' or 'the existing tests pass' is not
acceptance."
violated. "It works on my machine" or "the existing tests pass" is not
acceptance.
"""

const code_philosophy = """
Expand Down Expand Up @@ -71,6 +82,17 @@ const code_philosophy = """
logs, or platform-dependent text) and add an inline comment explaining why.
9. Source code and docs/architecture.md are the single source of truth. Don't trust
documentation blindly.
10. Agent analyzability (import graph). Before changing any src/ import
structure, read docs/agent-analyzability.md. Import a package only through
its public entry point (e.g. src/parser.ts, src/format/index.ts,
src/transpiler.ts, src/runtime/index.ts, src/cli/index.ts) — never reach
into another package's private files. Respect the layer DAG: imports point
only downward (CLI → Runtime → Compile → Parse/format → Shared leaf); lower
layers never import higher ones. Keep files ≤ ~400 lines and low fan-out
(≤ 8 runtime imports per file); prefer splitting into sibling files over
raising a cap. When package.json defines them, run npm run arch:check and
npm run lint in addition to npm run build and npm test; fix any new
violations before continuing.
"""

const output_criteria = """
Expand Down Expand Up @@ -207,7 +229,6 @@ workflow classify_role(task) {
config {
agent.model = "sonnet"
}

const result = prompt """
${classification_prompt}

Expand Down Expand Up @@ -236,7 +257,6 @@ workflow implement(task, role_name) {
config {
agent.model = "opus"
}

run task_text_has_header(task) catch (err) {
fail "Provided task does not contain a '## [text]' header"
}
Expand All @@ -262,8 +282,9 @@ workflow implement(task, role_name) {
- Following the codebase's existing style and conventions precisely.
- Following the code philosophy above for all new and modified code.
- Adding or updating tests as needed for acceptance criteria.
- Running npm run build, npm test, and npm run test:e2e; fix any failures
before continuing.
- Running npm run build, npm test, and npm run test:e2e; and, when
package.json defines them, npm run arch:check and npm run lint; fix any
failures before continuing.
- Ensuring all acceptance criteria in the task are met.

${definition_of_done}
Expand Down Expand Up @@ -300,27 +321,58 @@ workflow implement(task, role_name) {
"""
}

workflow default(name) {
# ensure git.is_clean
# Shared post-implement path: CI, docs parity from the task text, commit, artifact.
# Callers that touch QUEUE.md must do so before this (so the commit includes it).
workflow verify_docs_and_commit(task) {
run ci.ensure_ci_passes()
run docs.update_from_task(task)
const patch_file = run git.commit(task)
run artifacts.save(patch_file)
return patch_file
}

# Task-parameter entry for serve/mcp hub. Does not read or write QUEUE.md.
export workflow implement_from_task(task) {
run common.arg_nonempty(task) catch (err) {
fail "engineer.implement_from_task requires a non-empty task parameter (markdown with a ## header)"
}

run claude.ensure_usage()
const task = run queue.get_first_task()

const task_header = run first_line_task(task)
log "Implementing task: ${task_header}"

const role_name = run classify_role(task)
log "Role: ${role_name}"

run implement(task, role_name)

const patch_file = run verify_docs_and_commit(task)
log "Patch file: ${patch_file}"
return patch_file
}

# Queue-driven entry for CLI / overnight loops. Always auto-classifies the role.
export workflow implement_from_queue() {
run claude.ensure_usage()

const task = run queue.get_first_task()
ensure queue.task_is_dev_ready(task)
const task_header = run first_line_task(task)
log "Implementing task: ${task_header}"

const role_name = match name {
"" => run classify_role(task)
_ => name
}
const role_name = run classify_role(task)
log "Role: ${role_name}"

run implement(task, role_name)

run ci.ensure_ci_passes()
run docs.update_from_task(task)
run queue.remove_completed_task(task_header)

const patch_file = run git.commit(task)
run artifacts.save(patch_file)
const patch_file = run verify_docs_and_commit(task)
log "Patch file: ${patch_file}"
return patch_file
}

workflow default() {
return run implement_from_queue()
}
Loading
Loading