Repository navigation
fix(vibe): ship the 1.0.75 fleet lessons release - #336
Merged
Merged
Conversation
- liveness.mjs awaited main() above the constants that classify turn errors, so the watcher printed READFAIL for every failed turn; the entry point is last and a contract test refuses the shape anywhere. - NEEDS-REPLY catches a question or a permission, authorization or approval request on any line of an idle writer's final message. - A notLoaded thread whose turn finished reads IDLE with its message, proven with a test against the same App Server reads. - The watcher flags MODEL(...) drift from CODEX_MODEL and CODEX_EFFORT; a new Codex session needs a model as well as an effort. - watch.sh refuses a second copy per work dir. - board.mjs: standing duties with owners (UNOWNED-DUTY; helpers.mjs refuses to stop an owner) and SLOW Codex writers with unresolved human threads and no push for 30 minutes. - executed-check.mjs --kind prd refuses open PRODUCES children; review-page-check.mjs needs code evidence on decisions; session-questions.mjs refuses permission for in-scope work; lessons-pr.mjs finds the open lessons PR. - Short prose for the usage reset rule, grouped bug fixes and work outside the program; vibe 1.0.75 and its changelog. Testing: node --test on each changed suite; each new check shown failing with its fix removed; full suites run on a second machine. Risks: a new Codex session without CODEX_MODEL now refuses to start.
- The second-copy test starts the refused copy detached and kills its group afterwards, so a regression that lets it run leaves no sleep. Testing: watcher.test.mjs on a second machine, with and without the lock in watch.sh. Risks: None identified.
- A writer skipped two tickets on an uncited Out-of-scope line of a plan vibe had set to APPROVED with no approver, against a direct instruction to build them. - rulings-check.mjs --plan reads a PLN's get-document JSON; with no approverId, each out-of-scope, non-goal, excluded, deferred, descoped, not-covered or GAP item must cite a ticket AC, PRD or operator ruling. - The ticket worker runs it before setting a PLN APPROVED, handoff on every linked PLN, fleet-orchestrator at dispatch and QA prep; the takeover and resume prompts make the incoming writer trace every inherited exclusion to a human source. Testing: rulings-check tests on a fixture shaped like the plan, failing when APPROVED is trusted, when a line-level citation covers every item, and when only labeled lines are read. Risks: vibe plans with uncited exclusions now return NEEDS_CHANGE at the APPROVED transition until each one is cited or brought in scope.
- Every PLN session-plan.mjs renders starts with a Self-approved line, since vibe sets a PLN's status but never its approver; the ticket worker sets APPROVED only with a human approver or that line. - rulings-check.mjs --plan fails an APPROVED or EXECUTED plan with no approver that lacks the line, and reads obsolete calls as exclusions. The fixture is shaped like the plan a writer used to skip two tickets. - fleet-orchestrator principle 1 states the operator's ruling that a scope exclusion, deferral or obsolete call needs a human source. - session-questions lets a question about dropping or narrowing scope through; the change worker waits for that answer. Testing: rulings-check, session-plan and session-questions tests; each check shown failing with its part removed. Risks: the first publish after upgrading versions every open session's PLN once, adding the Self-approved line.
…1022 # Conflicts: # CHANGELOG.md
- snapshot.sh reads each watched PR's unresolved review threads and prints threads=<n>; an open PR with any ends BLOCKED(unresolved threads), apart from its review decision and checks. Two approved PRs with auto-merge armed sat blocked for hours while their writers waited and the block was read as a missing approval. Testing: snapshot.test.mjs with a fake gh, failing with the flag removed. Risks: one more gh call per watched PR per tick.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Ship the open vibe lessons ledger entries from the 2026-10-21 and 2026-10-22 fleet runs as one pull request and one vibe 1.0.75 release, with a mechanical check wherever one fits. While checking the watcher's handling of unloaded threads, this also fixes a watcher bug: run as a command,
liveness.mjsprintedREADFAILfor every failed turn.Release metadata
plugins/vibe/tools/python/test_vibe_1075_lessons_contract.py.Affected files
scripts/liveness.mjs,scripts/classify.sh,scripts/snapshot.sh,scripts/watch.sh, their tests,SKILL.md.scripts/board.mjs,scripts/helpers.mjs,scripts/codex-session.mjs,scripts/review-page-check.mjs, newscripts/lessons-pr.mjs, their tests,SKILL.md,references/templates.md.scripts/executed-check.mjs,scripts/rulings-check.mjsand their tests,SKILL.md; vibe:scripts/session-questions.mjs,scripts/session-plan.mjsand their tests,SKILL.md; agents:vibe-change-worker.md,vibe-ticket-worker.md.Prevention closeouts
Watcher printed READFAIL for every failed turn
Prevention
await main()at the top level above the constants it uses, so the module paused before they were initialized and classifying a failed turn threw, causing usage limits, transient failures and system errors to read asREADFAIL.plugins/vibe/skills/codex-fleet-monitor/scripts/liveness.mjs| none found elsewhere.rg -n "await main\(" plugins, then a scan for top-levelconst,letorclassbelow it.test_no_plugin_script_declares_a_constant_below_its_top_level_await_main(scans every plugin.mjs), plus a rung 3 command-level test inliveness.test.mjsthat reads a usage-limit turn asLIMIT.liveness.mjsrestored the scan namesFailureand the other constants, and moving the entry point back fails the command test.Finished writer unloaded by the App Server (notLoaded)
Prevention
notLoadedas unreadable or dropped its final message.liveness.mjsreads themIDLEwith the tail.rg -n "notLoaded" plugins/vibe; livethread/read,thread/turns/listandthread/items/liston idle and unloaded threads.liveness.test.mjscase that reads the same finished turn asidleand asnotLoadedand requires identicalIDLE ... LASTlines throughclassify.sh.notLoadedthreads fails the case.Writers waited on the orchestrator while the operator was away
Prevention
NEEDS-REPLYonly when an idle writer's final message ended in a question, causing a writer that asked "May I ...?" and ended on a status sentence to wait unread.scripts/liveness.mjsneedsReply| a live idle tail showed the same shape.rg -n "needsReply|NEEDS-REPLY" plugins/vibeliveness.test.mjs: a question or a permission, authorization or approval request on any line isNEEDS-REPLY; plain reports and URLs with query strings are not.Approved PRs blocked by unresolved review threads
Prevention
codex-fleet-monitor/scripts/snapshot.shand the monitorSKILL.mdtable | listed for follow-up: vibeshepherd.mjs(the writer side of polling until merged).rg -n "reviewThreads|isResolved|reviewDecision" plugins/vibe/skillsthreads=<n>unresolved threads, andBLOCKED(unresolved threads)on an open PR with any, apart from the review decision and checks.shepherd.mjsstop on a new unresolved thread so the writer acts on it.A writer waited for authorization it did not need
Prevention
scripts/session-questions.mjs,agents/vibe-change-worker.md,skills/vibe/SKILL.md; the watcher side is theNEEDS-REPLYchange above.rg -n -i "authoriz|permission|NEEDS_PERSON" plugins/vibe/agents plugins/vibe/skills/vibesession-questions.mjs ask, which every question to the person goes through and which refuses a permission request for a test repair, main merge, push, rerun or fix while flags, product calls, destructive actions and credentials still pass; rung 4 line in the change worker.session-questions.test.mjs.Asked product questions the code could answer
Prevention
scripts/review-page-check.mjs,references/templates.md, fleetSKILL.md; vibe's side issession-questions.mjs ask --product --code-evidencefrom 1.0.74.rg -n "code-evidence|checked in code|D###" plugins/vibereview-page-check.mjs: aD###row needschecked in code: <file>:<line>.review-page-check.test.mjs.PRD marked EXECUTED with open children
Prevention
skills/handoff/scripts/executed-check.mjs, fleetSKILL.md,agents/vibe-ticket-worker.md(plans pass--kind plan).rg -n "executed-check|EXECUTED" plugins/vibe/skills plugins/vibe/agents--kind, and--kind prdcannot run without--children, which it refuses while any child is not DONE or CANCELED.executed-check.test.mjs.Codex sessions started without an explicit model
Prevention
scripts/codex-session.mjs(a new session needs a model as well as an effort) andliveness.mjsplusclassify.shplussnapshot.sh(MODEL(...)drift againstCODEX_MODELandCODEX_EFFORT, local and remote).rg -n -- "--model|--effort|CODEX_MODEL|CODEX_EFFORT" plugins/vibe/skillscodex-session.mjsrefusing a new session without a model; rung 3 via the watcher's drift word, which also catches threads started outsidefleet.sh.codex-session.test.mjs; removing the drift or dropping it inclassify.shfailsliveness.test.mjs.Codex usage reset rule
Prevention
SKILL.md(Moving work) and the monitor'sHIGHrow.rg -n "MOVE_AT_PERCENT|resets=" plugins/vibe/skillsSKILL.md; the usage line already carriesresets=<n>.Main's post-merge health went unwatched
Prevention
scripts/board.mjs(duty,UNOWNED-DUTY),scripts/helpers.mjs(refuses to stop an owner), fleetSKILL.md.rg -n "stopped|duty|shepherd" plugins/vibe/skills/fleet-orchestratorhelpers.mjs stoppedrefusing a duty owner; rung 3 viaboard.mjs status.board.test.mjs.Watcher started with & again
Prevention
watch.shwith&in a foreground shell, causing a stray second watcher (a repeat).scripts/watch.sh, monitor and fleetSKILL.md.rg -n "watch.sh" plugins/vibe/skillswatcher.test.mjs(run on a second machine).A struggling Codex writer handed to Claude too late
Prevention
scripts/board.mjs(--runtime, head time,SLOWfrom unresolved human threads viagh api graphqlor--threads), fleetSKILL.md.rg -n "takeover|harness switch|SLOW" plugins/vibe/skills/fleet-orchestratorboard.mjs status.board.test.mjs.An agent-approved plan's exclusion treated as a human ruling
Prevention
skills/vibe/scripts/session-plan.mjs(every rendered PLN starts with aSelf-approvedline),agents/vibe-ticket-worker.md(sets APPROVED only with a human approver or that line, and runs the plan check first),skills/handoff/scripts/rulings-check.mjs(--plan),skills/handoff/SKILL.md(every linked PLN), fleetSKILL.md(the operator's scope-source ruling in principle 1; the check at dispatch and QA prep),references/templates.md(takeover and resume prompts trace inherited exclusions),scripts/session-questions.mjs(a question about dropping or narrowing scope goes through). Vibe already said session-written text is never a source, so this moves that rule up a rung.rg -n -i "out-of-scope|approverId|APPROVED|obsolete" plugins/vibe/agents plugins/vibe/skills plugins/closedloop-core/skills/plan-structuresession-plan.mjs, which renders the self-approved line on every plan vibe publishes; rung 3 viarulings-check.mjs --plan: an APPROVED or EXECUTED plan with no approver fails without that line, and any plan with no approver fails on each out-of-scope, non-goal, excluded, deferred, descoped, obsolete, not-covered or GAP item (labeled lines, bullets under such headings, and such clauses in tables or notes) that cites no ticket AC, PRD or operator ruling; rung 4 lines in fleetSKILL.mdand the takeover and resume prompts.approverIdnull, an uncitedOut-of-scope: ISS-9381 ...line) the check reports 7 problems; trusting the APPROVED status, accepting one citation for a whole line, reading labeled lines only, dropping the marker requirement, or rendering without the marker each fails its test.Stacked lessons PRs
Prevention
SKILL.mdLessons loop and newscripts/lessons-pr.mjs.rg -n "lessons PR|Batch lesson" plugins/vibelessons-pr.mjs, required before opening one; it names the open PR to push onto and fails when gh cannot answer.lessons-pr.test.mjs.Bug fixes grouped into few tickets and PRs
Prevention
SKILL.md(QA finding filing).rg -n "file a ticket|follow-up" plugins/vibe/skills/fleet-orchestratorSKILL.md.Work outside the program goes to its owner
Prevention
SKILL.mdPushback.rg -n "other teams|scope" plugins/vibe/skills/fleet-orchestrator/SKILL.mdSKILL.md.Testing
Run on a second machine in this branch's own worktree:
uv run ruff check .,uv run pyright,uv run pytest plugins/,node --testover every plugin test file (80 files),npm ci && npm run typecheck && npm testin eachtools/*package, andnpm run buildin each bundling tool with no change to the committeddistbundles. Each new check was shown failing with its fix removed; the watcher lock proof ran on the second machine.Risks
A new Codex session started through
fleet.shwithoutCODEX_MODELnow refuses to start, andexecuted-check.mjsnow requires--kind; the only shipped caller passes it. The first publish after upgrading versions each open session's PLN once to add the self-approved line, and a vibe plan with an uncited exclusion goes back to its writer before it is set APPROVED.