Skip to content

feat(work-items): loud binding-presence entry invariant + role-default warning (#449) - #690

Merged
kyle-sexton merged 3 commits into
mainfrom
feat/449-work-items-no-checkout-entry-invariant
Jul 20, 2026
Merged

feat(work-items): loud binding-presence entry invariant + role-default warning (#449)#690
kyle-sexton merged 3 commits into
mainfrom
feat/449-work-items-no-checkout-entry-invariant

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Summary

The work-items triage/work lanes assumed a resolvable, bound project context. When
.work-item-tracker.json was absent, canonical role labels fell to their defaults silently (a
correctness risk for any repo that remapped config.role_labels) and seam coordination verbs
surfaced a raw mid-flow exit 3 instead of an actionable message. This ships the operator-ratified
fix — binding presence as a third loud entry invariant, and the silent role-default fallback as a
loud warning — reconciled so it does not regress this repo's own deliberately gh-native
/work-items:work lane.

Fix

  • Binding presence is a third loud entry invariant (reference/tracker-seam.md "Shared tracker
    context"). It sits alongside the existing jq and seam-script checks but is discharged
    distinctly: the first two have no recovery path and stop; a missing binding is loud and
    routable, never a silent default and never a raw exit 3, without halting unconditionally —
    • Seam coordination verbs (claim, reclaim, renew-lease, create-item, list-frontier,
      capabilities) cannot run unbound (the seam hard-errors exit 3, CONTRACT.md "Exit codes"), so
      before the first one the skill surfaces a message distinguishing (1) setup was never run
      run /work-items:setup, from (2) a deliberate gh-native operating mode → proceed for
      provider-mechanic operations only, accepting no race-safe claim/lease.
    • Provider-mechanic operations (list/search/close, label/assignee/comment edits) run as raw
      gh per the bound adapter reference, never read the binding, and proceed unbound.
    • Caveat recorded: the gh-native path presumes a gh-backed provider — a local-markdown
      target with no binding has no config.storage_dir and stays a hard stop.
  • Silent role-label default becomes a loud warning. When a canonical role resolves to its default
    because the binding or its config.role_labels entry is absent, the skills now warn loudly instead
    of substituting silently. Applied at every action-entry resolution site that inlines it
    (skills/work/SKILL.md, skills/track/actions/{due,recheck,audit}.md, skills/decompose/SKILL.md)
    and in the shared invariants (reference/tracker-seam.md, reference/label-taxonomy.md). A
    present-but-malformed / empty / non-string value remains a hard stop, unchanged.
  • skills/work/evals/evals.json gains eval 4 asserting the unbound-binding behavior (loud,
    routable, distinguishes setup-vs-gh-native, warns on role default, never forges a binding).
  • Version bump 0.14.40.15.0 + CHANGELOG.md entry.

The reconciliation (why not an unconditional hard stop)

The ratified decision reads "stop-and-remediate," but the last comment on #449 (filed after
ratification) reports that this very repo runs /work-items:work deliberately gh-native (plain
gh issue/gh pr, status: ready, no seam claim/reclaim) because it has no binding and never ran
/work-items:setup — so a literal hard stop would regress a working, intentional mode every cycle
(session-start reclaim already hits exit 3 here today). The coordination-vs-provider-mechanic split
is not invented for this fix — it is the pre-existing "Operation routing" seam (coordination verbs go
through the dispatcher and need the binding; provider mechanics run as raw gh and never read it).
Scoping the halt to coordination verbs, and making everything else warn-and-proceed, satisfies the
ratified loud-surfacing intent (#455) and keeps the gh-native read/comment/label path working.

Parked (see PR comment)

One residual judgment call is parked with status: needs-decision, not silently resolved:
whether to formally document a first-class gh-native no-lease claim path for
coordination-dependent lanes (/work-items:work) so they too run unbound, versus keeping them
stopped at the coordination check. RECOMMENDED: defer with the same trigger as the full remote mode.
It does not block this PR — the loud invariant and role-default warning ship regardless.

Verification

  • bash scripts/check-changed-skills.sh origin/mainwork, track, decompose all
    PASS — 0 errors (the lone per-skill "no Gotchas surface" WARN is pre-existing).
  • bash scripts/check-skill-portability.sh origin/mainNo unexcused coupling tokens in 5 skill
    files.
  • check-jsonschema against plugins/skill-quality/reference/evals.schema.jsonwork/evals.json
    validation done (ok).
  • markdownlint-cli2 over all 14 changed/sibling markdown files — 0 errors.
  • jq empty on plugin.json and work/evals.json — valid JSON. git diff --check — no trailing
    whitespace.

Related

Closes #449

🤖 Generated with a Claude Code implementation subagent (issue #449)


Co-authored-by: Claude Opus 4.8 noreply@anthropic.com

…t warning (#449)

Add binding presence (.work-item-tracker.json) as a third loud entry
invariant alongside jq / dispatcher-script, and convert the silent
role-label-default fallback into a loud warning.

Reconciles the ratified "stop-and-remediate" decision with this repo's own
deliberately gh-native /work-items:work lane: a missing binding is discharged
distinctly from jq/seam (which have no recovery path). Seam coordination verbs
(claim, reclaim, renew-lease, create-item, list-frontier, capabilities) cannot
run unbound, so before the first one the skill surfaces an actionable message
distinguishing "setup never run" (run /work-items:setup) from a "deliberate
gh-native operating mode" (proceed provider-mechanic-only, no race-safe
claim/lease) instead of a raw mid-flow exit 3. Provider-mechanic operations
(list/search/close, label/comment edits) run as raw gh and proceed unbound;
their only degradation is role resolution, now a loud warning. local-markdown
with no binding stays a hard stop.

Full remote/no-checkout mode stays deferred. A first-class gh-native no-lease
claim path for coordination-dependent lanes is parked for operator decision.

Closes #449

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@kyle-sexton kyle-sexton added the automated Opened by automation. label Jul 20, 2026
@claude

claude Bot commented Jul 20, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 4m 52s —— View job


PR Review — feat(work-items): loud binding-presence entry invariant + role-default warning (#449)

  • Gather context and understand the request
  • Read changed files
  • Review core invariant logic (reference/tracker-seam.md)
  • Review skill entry points for role-default warnings
  • Review eval additions (evals.json)
  • Review changelog and version bump
  • Compile and post findings

Summary

This PR correctly identifies and closes a real correctness gap: a missing .work-item-tracker.json previously produced either a silent wrong-label query (role-label default) or a raw exit 3 mid-flow (seam coordination verb). The design is well-reasoned — the coordination-vs-provider-mechanic split is pre-existing and the invariant discharge is appropriately asymmetric (coordination = stop+route, provider-mechanic = warn+proceed). Changelog, version bump (0.14.4 → 0.15.0), and eval coverage are all solid. Three findings follow.


Finding 1 — Medium | work/SKILL.md: Step 0 runs a coordination verb before the binding is checked

The binding-presence invariant in tracker-seam.md says:

"Before the first coordination verb, if no binding resolves, surface a message…"

In work/SKILL.md, Step 0 (reclaim) is the first coordination verb, and it is placed before the ## Workflow → Role-label preflight section (the first place the skill file reads .work-item-tracker.json). A model following the skill file top-to-bottom executes Step 0 before it ever reads the binding — at which point the seam hard-errors exit 3 before the invariant fires.

The binding check lives only in the reference doc (tracker-seam.md), not as an explicit inline step in work/SKILL.md before Step 0. Eval 4 asserts the desired behavior ("detects the missing binding before the first coordination verb"), but the skill file's structural ordering works against reliably producing it.

Relevant lines:

Suggested fix: Add an explicit binding-presence check note before Step 0 in work/SKILL.md — matching the pattern of jq and seam-script checks that are applied before the workflow begins. Alternatively, move the role-label preflight to before Step 0 so that the binding read happens earlier, and note that an absent binding at that point triggers the coordination-verb routing decision before reclaim is attempted.

Fix this →


Finding 2 — Low | triage/SKILL.md: canonical role labels applied without binding resolution or loud-warning (inconsistent with decompose)

The PR updates decompose/SKILL.md to "warn loudly when a role defaults because the binding or its config.role_labels entry is absent." The triage/SKILL.md applies the same canonical role labels (autonomous-eligible → default agent-ready, human-gated → default needs-human) in its outcome table without a corresponding resolution step or loud-warning note — the PR description claims to update "every action-entry resolution site that inlines it," but triage inlines these defaults at four points in the outcome table.

If a consuming repo remaps autonomous-eligible or human-gated in config.role_labels, triage would silently apply the wrong default string to every briefed item — the same correctness risk the PR fixes elsewhere.

Relevant lines:

The updated label-taxonomy.md and tracker-seam.md do cover this by reference (triage defers to label-taxonomy.md "Canonical roles"), so the reference-layer protection exists. The gap is that triage lacks the inline reminder that decompose gained, making it inconsistent within the plugin's explicit-resolution sites.


Finding 3 — Low | track/SKILL.md: role-invariant summary doesn't mention loud warning

track/SKILL.md has an action-entry invariant note (not changed in this PR) that still says "resolve each role from config.role_labels at action entry and use the resolved strings in every query" without mentioning "warn loudly when absent." The individual action files (due, recheck, audit) all received the loud-warning clause — the parent router's summary is now inconsistent with its children.

Relevant lines:


What's done well

  • Invariant design is correct. The three-level discharge (jq/seam = hard stop; binding = warn+route) maps to the actual failure-mode taxonomy: the first two have no recovery path, the binding does.
  • Coordination-vs-mechanic split is clean. The pre-existing routing table in tracker-seam.md makes the scoping principled rather than ad hoc. Provider-mechanic operations genuinely never read the binding.
  • local-markdown caveat is recorded — not silently elided.
  • Eval 4 is well-formed. Five expectations, each testing a distinct aspect of the invariant (detection timing, message content, tradeoff naming, role-default warning, no binding forgery).
  • Version bump and CHANGELOG are appropriate and accurate (0.15.0, behavioral change surfaced to operators).
  • The deferred claim-path decision is properly parked, not silently resolved.

@kyle-sexton

Copy link
Copy Markdown
Contributor Author

Parked decision — gh-native no-lease claim path for coordination-dependent lanes

Context. This PR ships the ratified fix (binding presence as a third loud entry invariant; silent
role-default → loud warning) and scopes the halt to seam coordination verbs so provider-mechanic
(read/comment/label) work still runs unbound — which keeps this repo's deliberately gh-native
/work-items:work lane working. One residual, contract-shaped question is not decided here,
because it was raised in the last #449 comment after the operator ratified the brief:

Question. Should coordination-dependent lanes (/work-items:work — whose purpose is
claim-and-execute) get a documented first-class gh-native no-lease claim path so they run unbound,
or stay stopped at the coordination check when unbound?

RECOMMENDED — (1) Defer with a recorded trigger (mirrors how full remote mode was deferred).
Ship this PR's loud invariant now; document the gh-native no-lease claim mode only when someone needs
unattended coordination-dependent work at scale. Lowest risk — builds no new claim-safety surface,
and the loud message already tells a gh-native operator what they lose (no race-safe lease).

  • (2) Build the gh-native no-lease claim mode now. Bless assignee-only claim (no lease; races are
    the operator's problem) as a supported /work-items:work mode for unbound repos. Matches what this
    repo already does live — but it is new claim-safety contract surface (cousin to the deferred remote
    mode) and invites silent double-claims across concurrent lanes.
  • (3) Hard-stop /work-items:work when unbound. Strictest reading of "stop-and-remediate," but
    regresses this repo's own working gh-native lane every cycle — rejected as the reconciliation shows.

Labeling #449 status: needs-decision for this residual only; the rest of the fix is not blocked.

…e/track role-warning parity (#449)

Review findings (PR #690):
- F1 (medium): work Step 0 reclaim is the lane's first coordination verb but
  ran structurally before the binding was read, so the invariant surfaced as a
  raw exit 3. Add an explicit binding preflight before Step 0 that discharges the
  setup-vs-gh-native routing (and stops rather than dispatching claimless, since
  the gh-native no-lease claim path for this coordination-dependent lane is parked).
- F2 (low): triage applied canonical role labels without an inline resolution/
  loud-warning reminder; add one mirroring decompose (reference layer already
  covered it — this restores site-level consistency).
- F3 (low): track/SKILL.md parent role-invariant summary now carries the
  loud-warning clause its children (due/recheck/audit) already gained.

CHANGELOG updated to reflect the added sites.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@claude

claude Bot commented Jul 20, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 4m 3s —— View job


PR Review — feat(work-items): loud binding-presence entry invariant + role-default warning (#449)

  • Gather context and understand the request
  • Read changed files (tracker-seam.md, work/SKILL.md, triage/SKILL.md, track/SKILL.md, action files)
  • Check whether Finding 1 (preflight ordering) was addressed
  • Check whether Finding 2 (triage loud-warning gap) was addressed
  • Check whether Finding 3 (track/SKILL.md parent-router inconsistency) was addressed
  • Review eval additions and version bump
  • Compile and post findings

Previous findings — status after second commit (31a4a7b)

All three findings from the first review pass are addressed.

Finding 1 (Medium) — binding check before Step 0: ✅ Resolved. The new ## Binding preflight (before Step 0) section (lines 37–49) correctly names Step 0's reclaim as the first coordination verb, discharges the invariant explicitly before that step runs, distinguishes both paths (setup-never-run vs. gh-native), stops the lane when unbound (correct for a coordination-dependent lane), and flags the local-markdown hard-stop caveat. The binding reference to tracker-seam.md "Shared tracker context" keeps the two in sync by citation rather than duplication.

Finding 2 (Low) — triage loud-warning gap: ✅ Resolved. The paragraph added at the end of the "Apply outcome" section (line 138) now explicitly requires resolution from config.role_labels at action entry, warns loudly on absent binding/entry, and stops on malformed values — matching the protection already in decompose.

Finding 3 (Low) — track/SKILL.md parent-router summary: ✅ Resolved. The role-resolution bullet (lines 25–29) now matches its children: "warn loudly rather than substituting silently; a present malformed/empty/non-string value is a hard stop."


Fresh review of the full changeset

Design — correct. The three-tier invariant discharge in tracker-seam.md maps cleanly to the actual failure-mode taxonomy:

Invariant Recovery path Discharge
jq missing None Hard stop + install remediation
Seam script missing None Hard stop + reinstall remediation
Binding missing Exists (setup or gh-native) Loud + routable; blocks coordination only, not provider-mechanic

The coordination-vs-provider-mechanic split is principled (pre-existing routing table in tracker-seam.md, not invented here), and the work-lane override (coordination-dependent → stop both paths, not just coordination) is the correct application of that split for a lane whose entire purpose is claim-and-execute.

Coverage — complete. The CHANGELOG claims the loud-warning was "applied at every action-entry resolution site that inlines it." Verified across all 9 sites:

  • reference/tracker-seam.md "Role-label resolution" — ✅
  • reference/label-taxonomy.md "Canonical roles" — ✅
  • skills/work/SKILL.md "Role-label preflight" — ✅
  • skills/triage/SKILL.md "Apply outcome" close — ✅
  • skills/track/SKILL.md summary — ✅
  • skills/track/actions/due.md Step 1 — ✅
  • skills/track/actions/recheck.md Step 1 — ✅
  • skills/track/actions/audit.md "Before any tracker read" — ✅
  • skills/decompose/SKILL.md classification table note — ✅

Eval 4 — well-formed. Five expectations, each testing a distinct behavioral dimension:

  1. Detection before the first coordination verb (not mid-flow)
  2. Actionable message distinguishing the two arrival paths
  3. Naming the gh-native tradeoff (coordination unavailable; provider-mechanic proceeds)
  4. Loud role-default warning when binding absent
  5. No forged binding

Expectation 3 says the model should name the gh-native tradeoff, not that it should proceed for provider-mechanic operations within work — consistent with the skill file's "stop for the remediation" instruction for this coordination-dependent lane. The wording is precise.

CHANGELOG and version bump — appropriate. The 0.14.4 → 0.15.0 bump is warranted (behavioral change surfaced to operators). The CHANGELOG correctly flags the deferred gh-native no-lease claim path in a separate "Deferred" subsection rather than burying it.


One minor observation (informational, not blocking)

In triage/SKILL.md, the canonical-role resolution note lands at the end of Step 5 ("Apply outcome"), after the outcome table has already inlined (default agent-ready) and (default needs-human) four times in lines 124–127. A model reading linearly could apply those defaults before reaching the loud-warning instruction.

The mitigation is already in place: triage/SKILL.md instructs reading tracker-seam.md at invocation start, and tracker-seam.md's "Role-label resolution is an action-entry invariant" section fires before any step. The reference-layer coverage is real. This is an observation about asymmetry relative to how work structures the same guidance (inline, before the step that needs it), not a gap in the protection.

If triage gains evals in a future pass, eval coverage would validate this path independently of the reference-layer reliance.


Summary

The second commit (31a4a7b) cleanly closes the three findings from the first pass. The invariant design is correct, the coordination-vs-provider-mechanic split is principled, the coverage is verified complete across all 9 inlining sites, and eval 4 is well-specified. The deferred gh-native no-lease claim decision is properly parked, not silently resolved. Ready to merge.

@kyle-sexton

Copy link
Copy Markdown
Contributor Author

Thanks — all three findings addressed in 31a4a7ba (branch-owned, fixed):

  • Finding 1 (Medium) — binding read after Step 0's coordination verb. Correct and the important
    one. Added an explicit ## Binding preflight (before Step 0) section to work/SKILL.md that
    discharges the binding-presence invariant before reclaim runs: surfaces the setup-vs-gh-native
    choice, and — because /work-items:work is coordination-dependent and its gh-native no-lease
    claim path is the parked decision, not yet a supported mode — stops for remediation rather than
    dispatching claimless (which would violate the Step 5 claim-before-dispatch invariant). This makes
    eval 4's "detects the missing binding before the first coordination verb" reliably reachable.
  • Finding 2 (Low) — triage role labels lacked the inline reminder. Added a resolution +
    loud-warning note to triage's "Apply outcome" section mirroring decompose (the reference layer via
    label-taxonomy.md already covered it; this restores site-level consistency and makes the PR
    description's "every inlining site" claim accurate).
  • Finding 3 (Low) — track/SKILL.md parent summary inconsistent with children. Added the
    loud-warning-on-absent-default clause to the parent role-invariant summary so it matches
    due/recheck/audit.

CHANGELOG updated to list the added sites. Local gates re-run green: changed-skills (4 skills, 0
errors), portability (0 coupling tokens), markdownlint (0 errors), no trailing whitespace.

@kyle-sexton

Copy link
Copy Markdown
Contributor Author

Post-green review pass — round 2 after fix-pass commit 31a4a7b.

Round Finding Classification Disposition
1 Medium: Step 0 (work/SKILL.md) runs reclaim before binding is ever read VALID Fixed — explicit binding-presence check added before Step 0
1 Low: triage/SKILL.md outcome table missing loud-warning parity VALID Fixed
1 Low: track/SKILL.md parent summary inconsistent with children VALID Fixed
2 Informational: triage's loud-warning note lands after the outcome table inlines defaults Non-blocking, reference-layer already covers it Accepted as-is

Verdict: "Ready to merge." Coverage independently verified across all 9 inlining sites. No inline threads. Flipping to ready.

@kyle-sexton
kyle-sexton marked this pull request as ready for review July 20, 2026 14:43
@claude

claude Bot commented Jul 20, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 1m 24s —— View job


PR Review — feat(work-items): loud binding-presence entry invariant + role-default warning (#449)

  • Gather context (prior review rounds, findings, dispositions)
  • Read changed files for final verification
  • Confirm all inlining sites and invariant structure
  • Post final review

Final verification

This PR has been through two prior review rounds. All three findings from round 1 were addressed in 31a4a7b. I've independently read the key files on HEAD to confirm.

reference/tracker-seam.md — Three-tier discharge is correctly structured (lines 29–68). The binding invariant is placed third, with its discharge asymmetry explicit: jq/seam-script have no recovery path → hard stop; binding has a recovery path → loud+routable, never silent. The coordination-vs-provider-mechanic split maps to the pre-existing routing table. The local-markdown caveat and the deferred gh-native no-lease claim decision are both recorded.

work/SKILL.md — The ## Binding preflight (before Step 0) section (lines 37–49) correctly precedes Step 0's reclaim. It names reclaim as the first coordination verb, distinguishes both arrival paths, and correctly stops rather than dispatching claimless — because this lane is coordination-dependent and the gh-native no-lease claim path is explicitly parked. The local-markdown caveat is cited.

triage/SKILL.md — Line 138 adds the canonical-role resolution note at the close of "Apply outcome": resolve from config.role_labels at action entry, warn loudly on absent binding/entry, stop on malformed. Matches the decompose protection.

track/SKILL.md — Lines 25–29: the parent router's role-invariant summary now reads "warn loudly rather than substituting silently; a present malformed/empty/non-string value is a hard stop" — consistent with due/recheck/audit.

evals.json — Eval 4 (work-unbound-binding-is-loud-and-routable-not-raw-exit-3) has five focused expectations: detection before the first coordination verb, actionable message distinguishing both paths, naming the gh-native tradeoff, loud role-default warning, no forged binding. Well-specified.

plugin.json / CHANGELOG.md0.14.4 → 0.15.0 bump is correct for a behavioral change surfaced to operators. CHANGELOG Added/Changed/Deferred subsections accurately reflect the scope, including the parked decision as a named Deferred item.


One previously noted observation (still present, still non-blocking)

In triage/SKILL.md, the canonical-role loud-warning note (line 138) lands after the outcome table has already inlined (default agent-ready) and (default needs-human) four times (lines 124–127). A model reading linearly could apply those defaults before reaching the resolution instruction. The reference-layer protection in tracker-seam.md ("Role-label resolution is an action-entry invariant" — read at invocation start) covers this gap; the inline reminder is belt-and-suspenders. This is an asymmetry with how work structures the same guidance (inline, before the step), not a correctness gap. If triage gains evals in a future pass, independent eval coverage would validate this path without relying on reference-layer loading order.


Summary

All three round-1 findings are confirmed resolved on HEAD. The invariant design is correct, the coordination-vs-mechanic split is principled (pre-existing, not invented), coverage is verified across all 9 inlining sites, the deferred gh-native no-lease claim decision is properly parked with a recorded trigger, and eval 4 is well-specified. Ready to merge.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 31a4a7ba92

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/work-items/reference/tracker-seam.md Outdated
…in the binding preflight (#449)

The seam coordination-verb list in tracker-seam.md's binding-preflight
section omitted get-item, link-blocks, and add-sub-item — all three
already documented elsewhere in the same file as coordination verbs
that go through the seam ("single-item fetch", "dependency links",
"sub-items"), and all three require a binding at the dispatcher
unconditionally (work-item-tracker.sh:98-102), before its verb-specific
dispatch. An unbound /work-items:track start calls get-item before
reclaim (start.md:20-21), so it still hit the raw exit 3 this invariant
was meant to prevent. CHANGELOG's restatement of the same list is
updated to match.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@claude

claude Bot commented Jul 20, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 46s —— View job


PR Review — feat(work-items): loud binding-presence entry invariant + role-default warning (#449)

  • Gather context and understand the request
  • Read the full PR diff (all 3 commits)
  • Review the latest fix commit (2c16cd0) — single-item fetch and dependency-link verbs added to binding preflight
  • Verify coordination-verb list completeness in tracker-seam.md
  • Check consistency across work/SKILL.md binding preflight and CHANGELOG.md
  • Compile and post findings

Round 3 review — latest commit 2c16cd0

This pass reviews the fix commit that closed the Codex finding (P2) about get-item, link-blocks, and add-sub-item being omitted from the coordination-verb list in the binding preflight.

Codex finding — confirmed real, correctly fixed

The root cause was real. track/actions/start.md lines 20–21 calls get-item before reclaim in its snippet:

"$TRACKER" get-item "<id>"
"$TRACKER" reclaim "<id>"

The dispatcher (work-item-tracker.sh lines 98–102) applies the binding check universally, before verb dispatch, so get-item requires the binding just as reclaim does. With the prior verb list omitting get-item, a model following the skill could attempt the snippet unbound and hit the raw exit 3 the invariant was meant to prevent.

Verb-list exhaustiveness — verified correct

The updated tracker-seam.md coordination-verb list now reads:

create-item, get-item, claim, renew-lease, reclaim, link-blocks, add-sub-item, list-frontier, capabilities

Cross-checked against the dispatcher's accepted-verb set (work-item-tracker.sh lines 84–122):

Dispatcher branch Verbs
case direct-pass create-item, get-item, claim, renew-lease, reclaim, link-blocks, add-sub-item, capabilities
list-frontier → dispatches as list-items list-frontier

All 9 verbs are now listed, and the binding check at lines 98–102 applies to all of them before the case statement runs. The list is exhaustive. ✅

CHANGELOG consistency — correct

The CHANGELOG.md restatement of the same verb list was updated in lockstep with tracker-seam.md. Both now agree on all 9 verbs. ✅

One informational observation (non-blocking, consistent with round-2 accepted note)

track/actions/start.md (not changed in this PR) calls get-item as its first coordination verb with no inline binding-preflight reminder — the protection comes from tracker-seam.md's invariant, read transitively via track/SKILL.md's instruction to read it at invocation start. This is the same reference-layer pattern noted as non-blocking for triage/SKILL.md in round 2. The locality is weaker than the explicit ## Binding preflight (before Step 0) section in work/SKILL.md, but it's covered. If track/actions/start.md gains a review pass in a future cycle, an inline reminder matching work/SKILL.md's pattern would strengthen it.


Full changeset summary (all 3 commits)

All three prior findings are confirmed resolved on HEAD. The Codex P2 finding (get-item/link-blocks/add-sub-item omission) is correctly closed. The invariant design is correct, the coordination-vs-provider-mechanic split is principled and pre-existing, coverage is verified complete across all 9 inlining sites and all 9 coordination verbs, the deferred gh-native no-lease claim decision is properly parked with a named trigger, and eval 4 is well-specified. Ready to merge.

@kyle-sexton
kyle-sexton merged commit dd00dbf into main Jul 20, 2026
17 checks passed
@kyle-sexton
kyle-sexton deleted the feat/449-work-items-no-checkout-entry-invariant branch July 20, 2026 15:59
kyle-sexton added a commit that referenced this pull request Jul 20, 2026
…schedule (#700)

## Summary

- Binds the work-item-tracker seam for this repo:
`.work-item-tracker.json` with `provider: github`, `lease_ttl_hours:
24`.
- Seeds `.github/recurring-schedule.json` as an empty `{"items":[]}`
skeleton so `due`/`recheck`/`work` stop reporting "no recurring schedule
configured" instead of hard-erroring.

## Fix

`.work-item-tracker.json` was never committed on this repo (the flagship
dogfood repo for the work-items plugin family), so every seam
coordination verb (`list-frontier`, `claim`, `reclaim`) exit-3'd here.
This forced the `/work-items:work` loop lanes to bypass the seam
entirely via direct `gh` label queries.

Per issue #560's decision brief (RECOMMENDED option, confirmed via a
live human interview this session):
- **Provider: `github`** — the only bundled adapter with
`reclaim`/race-safe `claim`; `local-markdown` is never a coordination
surface (`reclaim: false` in its manifest).
- **`lease_ttl_hours: 24`** — reclaim's activity check (non-lease
comments, open cross-referenced PRs) means TTL never steals active work;
it only bounds a crashed session's stale claim.
- **Empty recurring-schedule skeleton** — stops degradation without
starting any cadence clock; real recurring items deferred to a separate
seeding pass.
- **No `config.role_labels` remap** — verified against `CONTRACT.md`'s
`list-frontier` spec directly: `--autonomous` only excludes
`needs-human`-labeled items, it never gates inclusion on the
`autonomous-eligible` label. So this repo's `status: ready` (vs. the
skill's `agent-ready` default, which is actually a medley-only
`GovernedRepositories.cs` ExtraLabel, not part of the org `_core`
taxonomy) is a cosmetic naming difference, not a functional gap.

## Verification

- `jq .` on both new files: valid JSON.
- `git check-ignore -v` on both paths: not ignored (exit 1).
- Re-ran the setup `check` probes against the written files: binding
parses, carries `schema_version`/`provider`/`config.lease_ttl_hours`;
schedule parses with the `{"items":[]}` root shape.
- No lint/build changes — pure config addition, no code touched.

## Related

- Closes #560
- Cross-referenced in #560: #416 (wayfind seam-bypass), #478/#479
(absorb loop rules into skills), #449 (seam no-local-checkout mode,
since resolved by #690)

Closes #560

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automated Opened by automation.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

work-items: triage/work lanes have no documented no-local-checkout mode — seam assumes a project root

1 participant