Skip to content

Scaffold + engine core: modulex-core and modulex-cli#1

Merged
hartsock merged 5 commits into
mainfrom
pr1/scaffold-engine-core
Jun 5, 2026
Merged

Scaffold + engine core: modulex-core and modulex-cli#1
hartsock merged 5 commits into
mainfrom
pr1/scaffold-engine-core

Conversation

@hartsock

@hartsock hartsock commented Jun 5, 2026

Copy link
Copy Markdown
Owner

Summary

First slice of the modulex routine engine (per the approved plan; origin: gilabot#1892 redirected to a standalone Rust binary):

  • Workspace scaffold: kyln version 0.6.20260605, MIT OR Apache-2.0, justfile (just check gate), .githooks/pre-pushci.yml parity with cross-reference comments, CLAUDE.md hard rules, modulex.toml.example (executable documentation — integration tests parse it).
  • modulex-core:
    • Config model (TOML; $MODULEX_CONFIG./modulex.toml~/.modulex/config.toml; flattened per-step params)
    • CredentialRef {env|file|cmd}Secret (unprintable; unserializable by construction, guarded by a compile_fail doctest); resolved at spawn, scrubbed from output
    • ExecGate — the single subprocess seam; agent-bridle check_exec before spawn
    • GrantedCaveats three-tier sourcing; default = deny-all-exec-except-declared
    • Engine: monotonic generation counter (report identity; never wall-clock), adjacent-parallel batching re-ordered to config order, soft skips, 16-report retention
    • Builtin steps: git-tend / git-status / git-unpushed, deadline-calc / countdown-calc, script, harness (JSON-on-stdout, the pa contract)
  • modulex-cli: modulex run|step|list|steps|doctor (exit 0/1/2 = ok / engine error / step failures)

Fresh-eyes fixes included: {cmd=..} credential programs now part of the declared grant; panicked parallel steps surface as failed steps; hook exec bit.

Test plan

  • just check green locally: fmt, clippy --all-targets --all-features -D warnings, 61 tests (53 unit + 7 integration + 1 compile_fail doctest)
  • Integration: real-subprocess leash test (echo granted runs; sh ungranted denied before spawn; injected secret reaches child env and is scrubbed from output; timeout kills)
  • just demo dry-runs the example morning routine end-to-end
  • CI runs the same gate on this PR

Next slices per plan: PR 2 MCP server crate, PR 3 forge/board steps, PR 4 Python surface.

hartsock and others added 5 commits June 5, 2026 18:15
WHAT: Cargo workspace (kyln version 0.6.20260605, MIT OR Apache-2.0,
Rust 1.85), justfile with the canonical 'just check' gate, pre-push hook
mirroring .github/workflows/ci.yml (hook-parity comments both ways),
CLAUDE.md hard rules (ExecGate-only spawns, unserializable Secret, no
credentials at rest, generation counters not wall-clock, soft failures),
and modulex.toml.example showing the full morning routine with
credential REFERENCES only.

WHY: Establish the governance surface before the code: the example
config is executable documentation (integration tests parse it), and
hook/CI parity is a workspace-wide policy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
WHAT: The engine crate. Config model (TOML; $MODULEX_CONFIG →
./modulex.toml → ~/.modulex/config.toml; flattened per-step params),
CredentialRef {env|file|cmd} resolving to an unprintable, unserializable
Secret (compile_fail doctest guards the no-Serialize invariant),
GrantedCaveats three-tier leash sourcing ($MODULEX_CAVEATS JSON →
[caveats] → declared-default deny-all-exec-except-declared), ExecGate as
the single subprocess seam (agent-bridle check_exec BEFORE spawn, secret
scrubbing after), StepHandler trait + registry, Report/StepResult/
RepoResult mirroring gila-plugin-morning's proven shapes, and the Engine
(monotonic generation counter, adjacent-parallel batching re-ordered to
config order, soft skips for missing tools, 16-report retention).
Builtin steps: git-tend/git-status/git-unpushed, deadline-calc/
countdown-calc (pure ports incl. work_days_between), script, harness
(JSON-on-stdout contract for enclave AI harnesses like pa).

WHY: gilabot#1892 asked for the good-morning routine as a single
deterministic command; this engine is the standalone-Rust answer scoped
so multiple agents can drive it (MCP server lands next). 50 unit tests +
4 gated real-subprocess integration tests + example-config tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
WHAT: clap-based 'modulex' binary: run <routine> [--only/--skip/
--dry-run/--json], step <routine> <step>, list, steps, doctor (config
path, leash provenance banner, per-program availability). Exit codes:
0 success, 1 engine error, 2 ran-with-step-failures.

WHY: The human-facing surface and the smoke-test harness for the engine
('just demo' dry-runs the example morning routine).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
WHAT: (1) Config::declared_programs now includes the argv0 of every
{cmd=..} credential reference (tilde-expanded, matching what resolve()
spawns) — previously the declared-default leash denied all credential
commands and their steps silently soft-skipped. (2) A panicked handler
in a parallel batch now lands in the report as a failed step instead of
being silently dropped (slot-based collection). (3) Report retention
uses a defensive >= bound; removed a duplicate match arm in script's
run_command.

WHY: Fresh-eyes review findings. Regression tests:
declared_programs_include_cmd_credentials,
declared_program_extracts_cmd_argv0_only,
cmd_resolution_is_leash_gated_and_uses_stdout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
WHAT: Set the executable bit on .githooks/pre-push (in the index, so
every clone gets it).

WHY: git silently ignores non-executable hooks — the gate did not run.
Spotted via the hint on the bootstrap push.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hartsock hartsock added the risk:high High-risk change label Jun 5, 2026
@hartsock hartsock merged commit 0a8d083 into main Jun 5, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:high High-risk change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant