Beta Smoke Tests
Use these smoke tests before cutting a beta release. They verify the local V1 loop without a hosted service or webhook receiver.
Prerequisites
Run from each repository checkout that will be watched:
git status --short
git remote -v
gh auth status
gitmoot doctor --repo .
Use a test repository or a disposable branch. Keep generated logs, cloned helper repos, session archives, and large outputs untracked.
Plugin Package Smoke Test
Goal: prove Gitmoot can build runtime plugin packages, register local marketplaces in isolated homes, and diagnose the generated packages without writing into the real user runtime state.
For the scripted version, run:
GO_BIN=/path/to/go1.26 scripts/plugin-smoke.sh
-
Build a local test binary and use an isolated Gitmoot home.
GOTOOLCHAIN=go1.26.0 go build -o /tmp/gitmoot-current ./cmd/gitmootexport GITMOOT_SMOKE_HOME=/tmp/gitmoot-plugin-smokeexport GITMOOT_RUNTIME_HOME=/tmp/gitmoot-plugin-runtime-smokerm -rf "$GITMOOT_SMOKE_HOME"rm -rf "$GITMOOT_RUNTIME_HOME"mkdir -p "$GITMOOT_RUNTIME_HOME"/tmp/gitmoot-current init --home "$GITMOOT_SMOKE_HOME" -
Build both plugin packages.
/tmp/gitmoot-current plugin build codex --home "$GITMOOT_SMOKE_HOME"/tmp/gitmoot-current plugin build claude --home "$GITMOOT_SMOKE_HOME"/tmp/gitmoot-current plugin path codex --home "$GITMOOT_SMOKE_HOME"/tmp/gitmoot-current plugin path claude --home "$GITMOOT_SMOKE_HOME"Plugin packages are built for the runtime CLIs that support them (
codexandclaude). Kimi Code is a supported agent runtime (gitmoot agent start --runtime kimi) but is not a plugin build target. -
Diagnose the built packages.
/tmp/gitmoot-current plugin doctor --home "$GITMOOT_SMOKE_HOME" || true/tmp/gitmoot-current plugin doctor codex --home "$GITMOOT_SMOKE_HOME" || true/tmp/gitmoot-current plugin doctor claude --home "$GITMOOT_SMOKE_HOME" || trueMissing runtime CLIs are valid in this smoke path. Continue when doctor reports
runtime-clifailures for missingcodexorclaude. -
Install with an isolated runtime home.
HOME="$GITMOOT_RUNTIME_HOME" /tmp/gitmoot-current plugin install codex --home "$GITMOOT_SMOKE_HOME" --forceHOME="$GITMOOT_RUNTIME_HOME" /tmp/gitmoot-current plugin install claude --home "$GITMOOT_SMOKE_HOME" --scope user --forceIf
codexorclaudeis not installed, the command should keep generated files and print manual install commands instead of failing after partial destructive work. -
Validate diagnostics again after install.
/tmp/gitmoot-current plugin doctor --home "$GITMOOT_SMOKE_HOME" || true/tmp/gitmoot-current plugin doctor codex --home "$GITMOOT_SMOKE_HOME" || true/tmp/gitmoot-current plugin doctor claude --home "$GITMOOT_SMOKE_HOME" || true
Expected signals:
plugin path codexandplugin path claudepoint under$GITMOOT_SMOKE_HOME/.gitmoot/plugins/build.- Each generated package contains
skills/gitmoot/SKILL.md. - Doctor reports readable manifests and copied skill files.
- Runtime marketplace or install state is written under
$GITMOOT_RUNTIME_HOME, not the real user home. - Missing runtime CLIs are reported as diagnostics with next steps, not as corrupt generated packages.
One-Repo Smoke Test
Goal: PR comment -> queued ask job -> adapter result -> attributed PR comment
-> local job status update. This intentionally uses ask, not review, so
the smoke test cannot approve or merge the PR.
-
Register the repo and a shell smoke agent.
gitmoot setup --repo owner/project --path . --agent shell-smoke --runtime shell --session "printf '%s\n' '{\"gitmoot_result\":{\"decision\":\"approved\",\"summary\":\"shell ask smoke passed\",\"findings\":[],\"changes_made\":[],\"tests_run\":[\"shell smoke\"],\"needs\":[],\"delegations\":[]}}'"gitmoot agent repos shell-smoke -
Start the background daemon.
gitmoot daemon start --repo owner/project --poll 30sgitmoot daemon status -
Open a small test PR in
owner/project, then comment:/gitmoot help/gitmoot shell-smoke ask smoke test routing -
Confirm the job was queued and completed.
gitmoot job list --repo owner/projectgitmoot events --repo owner/projectgh pr view <number> --repo owner/project --comments
Expected signals:
-
The PR receives a Gitmoot queued-job acknowledgement.
-
gitmoot job list --repo owner/projectshows the job as succeeded. -
The PR receives a result comment with:
> Agent: `shell-smoke`> Runtime: `shell`> Job: `...` -
gitmoot events --repo owner/projectshows the queued/running/succeeded job events.
-
Stop the daemon when finished.
gitmoot daemon stopgitmoot daemon status
Delegation (Orchestra) Smoke Test
Orchestra is Gitmoot's name for structured multi-agent delegation: a conductor
(coordinator) returns a delegations[] score, the players (child agents) run in
parallel or in dependency order, and a finale (continuation) reconvenes and
synthesizes the results.
Goal: background coordinator job -> delegations in the coordinator result ->
two child jobs fanned out to worker agents -> both children succeed -> coordinator
continuation job enqueued. This exercises the structured delegation path end to
end with local shell agents, so it needs no external runtime CLIs.
The coordinator must run as background work so the daemon executes it through the
engine and dispatches the delegations. A synchronous gitmoot agent ask without
--background only returns the coordinator's own result and does not fan out, so
the test would silently pass with zero child jobs.
-
Register a coordinator shell agent whose result returns two delegations, and two worker shell agents whose results return empty
delegations(so the fan-out terminates and does not recurse).gitmoot setup --repo owner/project --path . --agent coordinator --runtime shell --session "printf '%s\n' '{\"gitmoot_result\":{\"decision\":\"approved\",\"summary\":\"coordinator delegating ui and api\",\"findings\":[],\"changes_made\":[],\"tests_run\":[],\"needs\":[],\"delegations\":[{\"id\":\"ui\",\"agent\":\"ui-worker\",\"action\":\"ask\",\"prompt\":\"propose the ui changes\"},{\"id\":\"api\",\"agent\":\"api-worker\",\"action\":\"ask\",\"prompt\":\"review the api contract\"}]}}'"gitmoot agent subscribe ui-worker --runtime shell --session "printf '%s\n' '{\"gitmoot_result\":{\"decision\":\"approved\",\"summary\":\"ui worker done\",\"findings\":[],\"changes_made\":[],\"tests_run\":[\"shell smoke\"],\"needs\":[],\"delegations\":[]}}'" --role reviewer --repo owner/project --capability ask --capability reviewgitmoot agent subscribe api-worker --runtime shell --session "printf '%s\n' '{\"gitmoot_result\":{\"decision\":\"approved\",\"summary\":\"api worker done\",\"findings\":[],\"changes_made\":[],\"tests_run\":[\"shell smoke\"],\"needs\":[],\"delegations\":[]}}'" --role reviewer --repo owner/project --capability ask --capability reviewgitmoot agent repos coordinator -
Start the background daemon so it executes the queued coordinator job and fans out the delegations.
gitmoot daemon start --repo owner/project --poll 30sgitmoot daemon status -
Queue the coordinator as background work.
gitmoot agent ask coordinator --repo owner/project --background "coordinate the ui and api work"gitmoot orchestrate coordinator "coordinate the ui and api work" --repo owner/projectis equivalent sugar for this background coordinator run. -
Confirm the coordinator job, the two child jobs, and the continuation job.
gitmoot job list --repo owner/projectgitmoot events --repo owner/project
Expected signals:
gitmoot events --repo owner/projectshows twodelegation_enqueuedevents on the coordinator job, one for theuidelegation and one for theapidelegation.gitmoot job list --repo owner/projectshows two child jobs with composite ids of the form<coordinator-job-id>/delegation/uiand<coordinator-job-id>/delegation/api, each reachingsucceeded.- After both children succeed,
gitmoot events --repo owner/projectshows adelegation_continuation_enqueuedevent andgitmoot job listshows a coordinator continuation job<coordinator-job-id>/continuationqueued forcoordinator.
Note: the continuation job runs the same coordinator agent. A real LLM coordinator ends the loop by returning no
delegationson the continuation, but a static shell agent returns the same delegations every time, so the continuation re-delegates each generation. This is bounded byMaxDelegationDepth(8): once a coordinator/continuation at that depth would dispatch, Gitmoot refuses and records adelegation_depth_exceededevent instead of spawning jobs forever. To keep this smoke test fast, rungitmoot daemon stoponce you have observed the first continuation rather than waiting for the depth cap to halt the chain. Also note delegatedaction: reviewrequires a pull request / head SHA; useaction: askfor PR-less smoke agents (a no-PR review fails withjob for <branch> has no head SHA).
-
(Optional) Verify dependency gating. Re-run with a coordinator whose result adds a third delegation that depends on the first two; it must stay queued until both deps succeed, then run.
{"id": "integrate","agent": "api-worker","action": "ask","prompt": "integrate the ui and api work","deps": ["ui", "api"]}Expected:
gitmoot events --repo owner/projectshows the<coordinator-job-id>/delegation/integratejob enqueued only after theuiandapichildren reachsucceeded, and the continuation job is enqueued onceintegratealso succeeds. -
(Optional) Verify an ephemeral delegation worker. A delegation can carry an inline
ephemeralworker spec (runtimeis required and must be one of codex/claude/kimi, plus optionalmodel,template,role,capabilities, andautonomy_policywhich defaults to read-only) that Gitmoot provisions on the fly and auto-disposes when the child job finishes. Ephemeral workers are leaf-only: an ephemeral child cannot itself delegate.{"id": "review","action": "ask","prompt": "review the api contract","ephemeral": {"runtime": "kimi","model": "kimi-k2","role": "reviewer","capabilities": ["ask"],"autonomy_policy": "read-only"}}Expected: Gitmoot materializes a temporary worker agent for the child job, removes it once the child completes, and any
delegationsreturned by an ephemeral child are ignored (leaf-only). This needs a real runtime CLI (codex/claude/kimi) on PATH, since an ephemeral worker is never a raw shell. -
Stop the daemon when finished.
gitmoot daemon stopgitmoot daemon status
Thermo Template Smoke Test
Goal: PR comment -> queued review job -> Codex resume with cached thermo template
instructions -> attributed PR result comment. Run this with a Gitmoot build that
includes gitmoot agent template commands.
-
Confirm the template row is installed (seed the
agent_templatesrow directly ifagent template listreports it as not installed), then start a Gitmoot-managed Codex review agent.gitmoot agent template show thermo-nuclear-code-quality-reviewgitmoot agent start thermo-review \--runtime codex \--repo owner/project \--path . \--template thermo-nuclear-code-quality-reviewgitmoot agent doctor thermo-reviewUse
--runtime claudeor--runtime kimito run the same template through Claude Code or Kimi Code, and add--model <model-id>to pin a specific model for the agent.Gitmoot prints the created session id. To inspect that Codex thread later:
codex resume <session-id>If you prefer registering an already-open Codex session, use
gitmoot agent subscribe ... --session <session-id-or-last>instead. -
Start the daemon for the test repo, or pass
--start-daemontoagent start.gitmoot daemon start --repo owner/project --poll 10sgitmoot daemon status -
Open a disposable PR, then comment:
/gitmoot thermo-review review -
Verify the queued job and PR result.
gitmoot job list --repo owner/projectgh pr view <number> --repo owner/project --comments
Expected signals:
-
The PR receives a queued-job acknowledgement for
thermo-review. -
gitmoot job list --repo owner/projectshows the review job. -
The result comment includes template attribution:
> Agent: `thermo-review`> Runtime: `codex`> Template: `thermo-nuclear-code-quality-review`> Job: `...`
Planner Template Smoke Test
Goal: cached planner template -> Gitmoot-managed Codex planner agent -> the first plan item dispatched as implementation work. This verifies the planning workflow is discoverable before using it on a real PR.
-
Build a local test binary and use an isolated Gitmoot home.
GOTOOLCHAIN=go1.26.0 go build -o /tmp/gitmoot-current ./cmd/gitmootexport GITMOOT_SMOKE_HOME=/tmp/gitmoot-planner-template-smokerm -rf "$GITMOOT_SMOKE_HOME"/tmp/gitmoot-current init --home "$GITMOOT_SMOKE_HOME" -
Confirm the planner template is available.
/tmp/gitmoot-current agent template list --home "$GITMOOT_SMOKE_HOME" | grep planner/tmp/gitmoot-current agent template show --home "$GITMOOT_SMOKE_HOME" planner -
From the test repo checkout, start the planner agent.
cd /path/to/project/tmp/gitmoot-current agent start project-planner-smoke \--home "$GITMOOT_SMOKE_HOME" \--runtime codex \--repo owner/project \--path . \--template planner \--start-daemon/tmp/gitmoot-current agent doctor project-planner-smoke --home "$GITMOOT_SMOKE_HOME"/tmp/gitmoot-current daemon status --home "$GITMOOT_SMOKE_HOME" -
Ask the planner directly through the local agent path.
/tmp/gitmoot-current agent ask project-planner-smoke \--home "$GITMOOT_SMOKE_HOME" \--repo owner/project \"Write a task-by-task implementation plan for this feature."/tmp/gitmoot-current job list --home "$GITMOOT_SMOKE_HOME" --repo owner/project/tmp/gitmoot-current job show <local-ask-job-id> --home "$GITMOOT_SMOKE_HOME" -
Hand the first plan item to an implement-capable agent and inspect the task Gitmoot records for it.
/tmp/gitmoot-current agent start project-implementer-smoke \--home "$GITMOOT_SMOKE_HOME" \--runtime codex \--repo owner/project \--path . \--role implementer \--capability implement \--policy danger-full-access/tmp/gitmoot-current agent implement project-implementer-smoke \--home "$GITMOOT_SMOKE_HOME" \--repo owner/project \"Implement the first task from the planner's plan."/tmp/gitmoot-current task list --home "$GITMOOT_SMOKE_HOME" --repo owner/project --json/tmp/gitmoot-current task events <task-id> --home "$GITMOOT_SMOKE_HOME" --jsonagent implementmints the task itself unless--task <task-id>names an existing one, so read the recorded id out oftask list --jsonbefore callingtask events. -
Open a disposable PR, then comment:
/gitmoot project-planner-smoke ask Write a task-by-task implementation plan for this feature. -
Verify the queued PR job and PR result.
/tmp/gitmoot-current job list --home "$GITMOOT_SMOKE_HOME" --repo owner/project/tmp/gitmoot-current job show <pr-ask-job-id> --home "$GITMOOT_SMOKE_HOME"/tmp/gitmoot-current events --home "$GITMOOT_SMOKE_HOME" --repo owner/projectgh pr view <number> --repo owner/project --comments
Expected signals:
agent template showdisplaysdefault role: planner,default capabilities: ask, andmutation: true.agent doctor project-planner-smokesucceeds.agent ask project-planner-smokeprintsstate: succeeded,agent: project-planner-smoke,action: ask, and a planner summary.job show <local-ask-job-id>includes"sender": "local", the cachedplannertemplate metadata, and the planner result.agent implement project-implementer-smokereports its implement job, andtask listshows the recorded task with its branch and state.task events <task-id>prints that task's append-only event trail.- The PR result comment includes
Template: planner. - The planner returns a structured task-by-task plan.
-
Stop the isolated daemon.
/tmp/gitmoot-current daemon stop --home "$GITMOOT_SMOKE_HOME"/tmp/gitmoot-current daemon status --home "$GITMOOT_SMOKE_HOME"
Agent Start Smoke Test
Goal: prove gitmoot agent start can create a Codex session, store the session
reference, start the daemon, and route a PR comment job through that new
session.
-
Build a local test binary and use an isolated Gitmoot home.
GOTOOLCHAIN=go1.26.0 go build -o /tmp/gitmoot-current ./cmd/gitmootexport GITMOOT_SMOKE_HOME=/tmp/gitmoot-agent-start-smokerm -rf "$GITMOOT_SMOKE_HOME"/tmp/gitmoot-current init --home "$GITMOOT_SMOKE_HOME" -
From the test repo checkout, confirm the installed template and start the agent.
cd /path/to/project/tmp/gitmoot-current agent template show --home "$GITMOOT_SMOKE_HOME" thermo-nuclear-code-quality-review/tmp/gitmoot-current agent start thermo-start-smoke \--home "$GITMOOT_SMOKE_HOME" \--runtime codex \--repo owner/project \--path . \--template thermo-nuclear-code-quality-review \--start-daemon/tmp/gitmoot-current agent list --home "$GITMOOT_SMOKE_HOME"/tmp/gitmoot-current daemon status --home "$GITMOOT_SMOKE_HOME" -
Open a disposable PR, then comment:
/gitmoot thermo-start-smoke review -
Verify the job and PR comments.
/tmp/gitmoot-current job list --home "$GITMOOT_SMOKE_HOME" --repo owner/project/tmp/gitmoot-current events --home "$GITMOOT_SMOKE_HOME" --repo owner/projectgh pr view <number> --repo owner/project --comments
Expected signals:
agent listshowsthermo-start-smokewith a generated Codex session id.- The PR receives a queued-job acknowledgement.
- The job succeeds and the result comment includes agent, runtime, template, and job metadata.
codex resume <session-id>opens the created session if manual inspection is needed.
-
Stop the isolated daemon.
/tmp/gitmoot-current daemon stop --home "$GITMOOT_SMOKE_HOME"/tmp/gitmoot-current daemon status --home "$GITMOOT_SMOKE_HOME"
Two-Repo Smoke Test
Goal: one daemon -> two registered repos -> same allowed agent -> ask jobs in each repo -> no cross-routing. This intentionally avoids approving reviews.
-
Register both repos with the same agent identity.
cd /path/to/project-agitmoot setup --repo owner/project-a --path . --agent shell-smoke --runtime shell --session "printf '%s\n' '{\"gitmoot_result\":{\"decision\":\"approved\",\"summary\":\"repo ask smoke passed\",\"findings\":[],\"changes_made\":[],\"tests_run\":[\"shell smoke\"],\"needs\":[],\"delegations\":[]}}'"cd /path/to/project-bgitmoot setup --repo owner/project-b --path . --agent shell-smoke --runtime shell --session "printf '%s\n' '{\"gitmoot_result\":{\"decision\":\"approved\",\"summary\":\"repo ask smoke passed\",\"findings\":[],\"changes_made\":[],\"tests_run\":[\"shell smoke\"],\"needs\":[],\"delegations\":[]}}'"gitmoot agent repos shell-smoke -
Start one daemon for all enabled repos.
gitmoot daemon startgitmoot daemon statusgitmoot status -
Open one test PR in each repo. Comment in each PR:
/gitmoot shell-smoke ask repo routing smoke -
Verify each repo saw only its own job.
gitmoot job list --repo owner/project-agitmoot job list --repo owner/project-bgitmoot events --repo owner/project-agitmoot events --repo owner/project-bgh pr view <project-a-pr> --repo owner/project-a --commentsgh pr view <project-b-pr> --repo owner/project-b --comments
Expected signals:
-
Each PR receives exactly the acknowledgement and result for its own comment.
-
gitmoot job list --repo owner/project-adoes not show project B jobs. -
gitmoot job list --repo owner/project-bdoes not show project A jobs. -
The same agent name is allowed on both repos:
gitmoot agent repos shell-smoke
Execution Model Smoke Test
Goal: verify the final here versus background execution model and the
resource scheduling rules.
-
Confirm fast planner guidance does not start a background runtime job.
In a Codex, Claude Code, or Kimi Code chat with the Gitmoot skill installed, ask:
Use the Gitmoot planner here. Write a task-by-task implementation plan for a README wording update.Expected signal: the answer appears directly in the current chat, and
gitmoot job list --repo owner/projectdoes not gain a new planner job. -
Queue two background asks to the same registered Codex or Claude agent.
gitmoot agent ask project-planner --repo owner/project --background "Say first OK."gitmoot agent ask project-planner --repo owner/project --background "Say second OK."gitmoot job watch <first-job-id>gitmoot job watch <second-job-id>Expected signal: both jobs finish, but their
job eventsdo not show overlapping runtime delivery for the sameruntime:<runtime>:<runtime_ref>. If the session is already busy, the later job recordsruntime_lock_waitand remains queued until a worker can retry it. -
Queue background asks that can use independent managed instances.
gitmoot agent type set project-planner --runtime codex --template planner --max-background 2 --idle-timeout 20mgitmoot daemon start --repo owner/project --workers 2gitmoot agent ask project-planner --repo owner/project --background "Say planner A OK."gitmoot agent ask project-planner --repo owner/project --background "Say planner B OK."gitmoot job list --repo owner/projectExpected signal: Gitmoot may create or reuse up to two managed planner instances, different runtime references can run concurrently, and
gitmoot agent gclater removes expired idle instances.
Recovery Checks
Run these against one smoke job if you need to verify recovery UX:
gitmoot job show <job-id>
gitmoot job events <job-id>
gitmoot job retry <job-id>
gitmoot job cancel <job-id>
gitmoot lock list --repo owner/project
gitmoot lock show owner/project <branch>
Only retry failed, blocked, or cancelled jobs. Only cancel queued, running, or
blocked jobs. Use gitmoot lock release owner/project <branch> --owner <agent>
for an exact-owner stale lock; use --force only when the stored owner is stale.
Known V1 Limits
- Local-only: the machine running the daemon must stay online.
- Polling watches GitHub; there is no webhook receiver.
- GitHub comments are authored by the authenticated
ghuser, not a bot. - Agent identity is shown in the comment body.
- There is no hosted dashboard, GitHub App bot identity, cloud runner, billing, or remote control plane.