Skip to content

orchestrate: lint the state file from the hooks, script the Now/Done edits and the updated= marker - #115

Merged
gilesknap merged 1 commit into
fix/orchestrate-hook-scopefrom
fix/orchestrate-state-quality
Oct 14, 2026
Merged

gilesknap merged 1 commit into
fix/orchestrate-hook-scopefrom
fix/orchestrate-state-quality

Conversation

@gilesknap

Copy link
Copy Markdown
Contributor

In a long goal, state.md drifted even though it was edited every turn. Now had stray blank lines and no (nothing running). Done grew one line per agent return and ended up out of order. Decided collected events. Next and Queue still named merged items. updated= was typed by hand and was wrong. Nothing in the plugin checked the file's content. This PR adds that check and moves the most error-prone edits into goal.sh. Plugin version 0.3.0 -> 0.4.0.

Stacked on #114 (hook session ownership and the narrower Stop check): this branch is based on #114's branch and should merge after it.

Closes #108
Closes #110
Closes #111
Closes #112

Changes

  • scripts/state-lint.sh <state> [<log>] [<sidecar>] (orchestrate: add a state.md lint run by the Stop and SessionStart hooks #108). Prints lint: <code>: <text> and always exits 0. Codes: now-blank, now-empty, now-finished, pending-but-done, decided-events, decided-unattributed, done-order, size, done-long, head-long, marker-stale, section-stale.
    • done-order compares the YYYY-MM-DD HH:MMZ stamps, date and time, so a goal can run over several days. Unstamped entries are placed by their label's time in log.md.
    • section-stale skips empty or placeholder-only sections, and after it reports a section it counts again from zero.
    • section-stale keeps section hashes in the goal's .lint sidecar, so the orchestrator is still the only writer of state.md.
    • Thresholds can be overridden with STATE_LINT_* environment variables.
  • Hooks (orchestrate: add a state.md lint run by the Stop and SessionStart hooks #108).
  • Size is measured in bytes (orchestrate: skill wording makes state.md grow one row per event and insert out of order #110). size flags a file over 10 KB; the pre-trim file was 98 lines but 14.7 KB. head-long flags a head over the injection cap (40 lines / 4000 bytes). The "under 150 lines" rule is gone.
  • goal.sh touch (orchestrate: the model types the state.md updated= marker and gets it wrong #111). Sets updated=, and so do now and land. The skill and the Stop nudge no longer ask the model to type a time.
  • goal.sh now '<entry>' and goal.sh land <label> ['<done line>'] (orchestrate: optional goal.sh helpers for the Now/Done moves (now, land) #112).
    • now adds a Now entry in place of (nothing running).
    • land drops the entry whose text contains -> <label> -> and restores (nothing running) when Now empties. Given a done line, it appends - YYYY-MM-DD HH:MMZ <text> after the last Done entry. land - '<text>' is for an item no agent ran. land also drops an entry that starts with the label, so now 'foreground: <item>' pairs with land foreground. Both keep the file's mode and fold newlines in their arguments into spaces.
    • Both rewrite Now with no blank lines and print the new Now.
    • Added because launches and returns are the most frequent state edits, and the free-form Edits caused the blank lines, the lost placeholder and the out-of-order Done. Each helper is one awk pass in goal.sh, which is already the orchestrator's own tool, so the single-writer rule holds.
  • Docs: docs/how-to/use-orchestrate-mode.md gains a "The state file" section covering the format, goal.sh touch/now/land and the lint.
  • SKILL.md and the template (orchestrate: skill wording makes state.md grow one row per event and insert out of order #110).
    • Now is edited only through now/land.
    • Done is the last section: one stamped line per finished item, not one per agent return. Agent returns and review rounds stay in the log.
    • Decided holds rulings only, each ending (<who>, <date>).
    • After every return or ruling, re-read the file down to ## Decided and fix what it contradicts.
    • When an item finishes, collapse its lines into its Done line.
    • The template's Done example carries the <YYYY-MM-DD HH:MMZ> prefix, and Decided's example ends (<who>, <YYYY-MM-DD>).

The lint, the skill and the helpers use one format: Now holds one line per entry or - (nothing running); Done is last, - YYYY-MM-DD HH:MMZ <text>; Decided entries end with (<who>, YYYY-MM-DD).

Testing

Merge order: stacked on #114; merge it first.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AJKFfYT7qdSfhkZGj6syCo

…edits and the updated= marker

Adds a state.md lint run from the hooks (#108), rewrites the skill's
state-file rules to one row per item with dated Done lines (#110), has
goal.sh write the updated= marker (#111) and adds goal.sh now/land
helpers (#112). Stacked on #114.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AJKFfYT7qdSfhkZGj6syCo
@gilesknap
gilesknap merged commit b26f0ad into fix/orchestrate-hook-scope Oct 14, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants