跳转至

Pomodoro

By the end of this page, you will understand a complete self-improvement loop. A Coder changes the candidate, a Critic writes feedback, and the new feedback makes the Coder eligible again. Once the Critic accepts, a person approves that exact Revision and the graph produces the final approved Git artifact.

The live case requires hg, Git, jq, and a working Codex executor.

Pomodoro self-improvement loop

Complete graph definition

This is the exact configuration used by the case. It is part of the public documentation, so you can read and copy it here or download the raw YAML.

version: 1
project:
  name: pomodoro-self-improvement
  default_targets: [approved]
slots:
  brief: { kind: file, path: request/brief.md }
  candidate: { kind: git, path: artifacts/candidate }
  critique: { kind: file, path: artifacts/critique.json }
  approval: { kind: file, path: artifacts/approval.json }
  approved: { kind: git, path: artifacts/approved }
rules:
  - id: coder
    in: [brief, candidate, critique]
    out: [candidate]
    when: >-
      test "$(jq -r '.decision // "revise"' critique)" = revise ||
      test "$(jq -r '.brief_checksum // ""' critique)" != "$(cksum brief | cut -d' ' -f1)"
    session: { policy: reuse, scope: project }
    permissions: { network: none, secrets: [] }
    run:
      using: codex
      model: gpt-5.6-luna
      reasoning_effort: none
      command: >-
        Read in/brief, inspect the Git repository in in/candidate, and read the
        latest structured feedback from in/critique. Clone in/candidate to
        out/candidate, implement the smallest Pomodoro improvement requested by
        the brief and critique, verify the result, and create one Git commit in
        out/candidate. Do not modify inputs or write anywhere else.
  - id: critique
    in: [brief, candidate, critique]
    out: [critique]
    when: >-
      test "$(jq -r '.candidate_commit // ""' critique)" != "$(git -C candidate rev-parse HEAD)" ||
      test "$(jq -r '.brief_checksum // ""' critique)" != "$(cksum brief | cut -d' ' -f1)"
    session: { policy: reuse, scope: project }
    permissions: { network: none, secrets: [] }
    run:
      using: codex
      model: gpt-5.6-luna
      reasoning_effort: none
      command: >-
        Review in/candidate against in/brief and the previous in/critique. Run
        focused checks. Write only out/critique as JSON with decision equal to
        revise or accept, actionable feedback, a checks array, candidate_commit
        equal to `git -C in/candidate rev-parse HEAD`, brief_checksum equal to
        `cksum in/brief | cut -d' ' -f1`, and an integer round one greater than
        the previous round. Accept only a usable and accessible timer.
  - id: request_approval
    in: [brief, candidate, critique]
    out: [approval]
    when: >-
      test "$(jq -r '.decision' critique)" = accept &&
      test "$(jq -r '.candidate_commit' critique)" = "$(git -C candidate rev-parse HEAD)" &&
      test "$(jq -r '.brief_checksum' critique)" = "$(cksum brief | cut -d' ' -f1)"
    run: { using: human, command: "Approve the reviewed Pomodoro candidate" }
  - id: package_approved
    in: [brief, candidate, critique, approval]
    out: [approved]
    when: >-
      test "$(jq -r '.decision' critique)" = accept &&
      test "$(jq -r '.decision' approval)" = approve &&
      test "$(jq -r '.candidate_commit' critique)" = "$(git -C candidate rev-parse HEAD)"
    run: "git clone -q in/candidate out/approved"

What each Slot does

Slot Kind Role in the graph
brief file The requested change. A new brief invalidates a critique whose checksum no longer matches.
candidate git The Pomodoro repository under revision. The Coder reads its current Revision and writes the next commit back to it.
critique file Structured feedback containing the decision, checks, candidate commit, brief checksum, and round.
approval file A Human Rule decision bound to one exact input frontier.
approved git The final Git artifact copied only after critique and human approval both pass.

Both candidate and critique participate in read and write relationships. Their Revisions alternate, which produces the loop.

What each Rule does

Rule Reads Writes Eligibility and work
coder brief, candidate, critique candidate Runs when critique says revise or its brief checksum is stale. It clones the candidate, makes the smallest change, verifies it, and creates one commit.
critique brief, candidate, critique critique Runs when the candidate commit or brief checksum differs from the old critique. It writes revise or accept.
request_approval brief, candidate, critique approval Runs only when the accepted critique still matches the current candidate and brief.
package_approved brief, candidate, critique, approval approved Runs when critique remains valid and the human decision is approve.

There is no Loop node. A revise critique changes the Coder's input frontier. A new candidate then changes the Critic's frontier. When the Critic writes accept, the Coder's when expression becomes false and the loop stops.

Verify scheduler semantics first

Run the deterministic test from the companion case workspace root.

cargo test -p hg-cli --test m18_pomodoro_loop -- --nocapture

It produces the same causal order at two concurrency limits.

coder → critique → coder → critique

This path does not call an agent. It checks that feedback triggers another round, acceptance stops the loop, and worker capacity does not change dependency semantics.

Run the live case

After initializing the case and importing its inputs, run the default target. When the Human Rule becomes pending, retrieve the current Activation and decide it.

hg run approved --jobs 2 --project .
hg human pending --project . --output json
hg human decide --activation <CURRENT_KEY> --decision approve --project .
hg run approved --jobs 2 --project .
hg materialize approved --project .

The decision is bound to the input Revisions visible at that moment. If candidate changes after approval, the old decision cannot approve the new candidate.