Claude GitHub Copilot Skill

issue-authoring

Draft or refine IDD-ready GitHub issues, roadmap issues, and sub-issues before the normal IDD execution loop begins. Use when a request is too large or ambiguous for one reviewable change, when work needs decomposition or dependency encoding, or when the user asks for issue draft

LLM Mart · 0 points · 9 views 39 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download kurone-kito-idd-skill-skills_issue-authoring-8a62fb6.zip · 64 KB
Part of kurone-kito/idd-skill — 3 skills

Install

skills CLI npx skills add https://github.com/kurone-kito/idd-skill/tree/main/skills/issue-authoring
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install kurone-kito-idd-skill@llmmart
Git git clone https://github.com/kurone-kito/idd-skill.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole kurone-kito/idd-skill collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Issue Authoring

Use this skill to prepare issue-ready work before execution starts. Keep the skill concise and treat the repository docs as the canonical source for the full contract and schema. The canonical source bundle lives in this repository; install copies in the agent-specific skill directory your runtime reads.

Stable Phases

Use two stable phases:

  1. Intake and Clarification — inspect relevant context, identify ambiguity, run a secondary critique or explicit self-critique, and ask only the questions that block safe issue drafting. Keep clarification bounded; use the repository-local issueAuthoring.maxClarificationRounds value when available, otherwise default to 3 rounds. Under-clarification stop rule: if, after bounded clarification, you still cannot name the concrete surface to edit or an objective verification for a candidate task, route it to needs-decision or ask — do not publish a confidently-vague ready issue. Reliability over speed.
  2. Decompose and Draft — restate the request in implementation terms, split it into atomic tasks, classify readiness, reuse existing issues when safe, and draft the smallest issue shape that preserves dependencies and reviewability.

Preserve low-readiness work in stable buckets: ready, deferred, needs-decision, blocked-by-human, and out-of-scope.

Workflow

  1. Read the bundled contract in references/contract.md.
  2. Reuse or extend an existing issue before creating a new one — but never edit the body of an actively-claimed or open-PR issue (its claimed agent will not pick the change up); cover it with a follow-up issue instead. See the contract's claim-state precondition.
  3. Choose the smallest safe output shape:
    • orphan issue for one ready autonomous task only when the target repository discovers orphans (issue-scope: roadmap-first, the default, via the orphan fallback, or orphan-first) and any configured orphan-first-policy approval step can be completed after drafting
    • roadmap plus sub-issues for multi-task or multi-session work
    • stable non-ready buckets for deferred, needs-decision, blocked-by-human, or out-of-scope work
  4. Prefix-first: resolve the target repository's marker prefix before emitting any authoring marker — roadmap-id, blocked-by, autopilot-suitability, or effort. Use the prefix documented by the target repository's onboarding or IDD docs, and ask the user instead of guessing when the prefix is not discoverable. Never default to this source repository's idd-skill prefix in an installed bundle.
  5. Keep dependencies machine-readable and minimal:
    • roadmap identity via <!-- <marker-prefix>-roadmap-id: ... -->
    • active child issues via roadmap task-list links
    • issue-to-issue dependencies via Blocked by #NNN
    • sequential roadmap dependencies via <!-- <marker-prefix>-blocked-by: ... --> only when a separate roadmap must close first
    • keep independent sibling work in roadmap task lists unless a true correctness, availability, or ordering constraint requires a dependency edge
  6. Before publishing a ready orphan, roadmap, or child body, run the audit-authored-issue linter against it as the mechanical pre-publish gate — see Mechanical pre-publish gate in the bundled contract, including the manual fallback for instructions-only installs with no helper runtime. Resolve every reported failure before treating the issue as ready. Before newly publishing a body into the needs-decision or blocked-by-human bucket instead, also run the linter, passing --expect-bucket <needs-decision|blocked-by-human> (choose the one matching value) — the same gate section's --expect-bucket flag requires the matching authoring-bucket marker for that publish, closing the gap where a non-ready body would otherwise never be audited at all.
  7. Publish each ready drafted body directly under the authoring hold once it passes the mechanical gate (step 6) and the critique pass (the Intake and Clarification phase above) — no separate publish approval is needed. Only skip publishing when the current request explicitly asked for a preview instead. Manage the authoring label for each created or updated issue:
    • resolve issueAuthoring.authoringLabelName, defaulting to status:authoring

    • create the label with gh label create before first use when the target repository does not already have it

    • treat label creation or application failure as a publishing blocker

    • apply the label before updating an existing issue

    • acquire per-target ownership before editing an existing issue or roadmap; the shared label is a claim-suppression lock, not an owner token. Follow the append-only owner-marker and re-read protocol in references/workflow-boundary.md and stop without editing when ownership or the target snapshot conflicts

    • for a new Stage 1 set, generate one opaque set ID and reuse it in every owner marker for that set; when resuming an interrupted set, recover and verify its persisted set ID from the exact trusted owner markers and reuse it instead of generating a replacement; never infer set membership from the label alone

    • when a set includes a parent roadmap, publish a valid roadmap shell under the authoring hold before any child; acquire and verify that roadmap as the set anchor, leaving its ## Tracks list empty only until child issue numbers exist. Without a parent roadmap, use the designated lead target as the anchor

    • acquire and verify the set anchor before publishing or acquiring any child; do not acquire children independently, and stop all edits if any target cannot join that anchor's verified set

    • before each child acquisition or resume, append and verify a same-owner anchor heartbeat (or reuse one — see the heartbeat-coalescing rule below), re-fetch the anchor's paginated log, then append the child marker and immediately re-fetch both anchor and child. Stop with the label in place if anchor ownership changed between those reads

    • Heartbeat coalescing (issueAuthoring.heartbeatCoalesceWindow, default PT2M): before appending a heartbeat, replay the target's paginated log; reuse the latest trusted marker instead of appending when it is the same owner/set/session, its mode is acquire/bootstrap/resume/heartbeat, it is younger than the window, and its body-sha256 matches the just-fetched body — re-fetch and verify the reused marker exactly as a fresh one. This window never applies to acquire, bootstrap, resume, release, release-guard, or release-complete appends themselves — only a heartbeat append may be skipped

    • persist the anchor's canonical repository/issue identity in every owner marker for the set; the anchor marker points to itself, and a resume must stop if the interrupted set's anchor cannot be proven

    • immediately before every Stage 1 body or relationship edit, re-fetch both the edited target and the set anchor; require each target's expected owner token independently, plus the same set, anchor, and owning session, and require an unchanged expected target snapshot before editing

    • immediately before that edit, renew both generations with a trusted same-owner-per-target heartbeat marker (one marker when target and anchor coincide; reuse applies here too), re-fetch and verify both, and stop if renewal or ownership verification fails

    • create new issues only through a capability-checked publication command that applies the authoring label atomically and carries an exact hidden publication token for target, anchor, set, and session; if that operation is unavailable, stop before creating the issue — never intentionally create an unlabeled issue

    • the hidden publication token is this exact HTML-first body line. anchor reuses the opaque target value only when this new issue is itself the set anchor (self-reference); for a non-anchor child, anchor is instead the set anchor's already-resolved real <owner>/<repo>#<number> reference, not an opaque id (full rule: references/contract.md's "New-issue ownership" section):

      <!-- <marker-prefix>-authoring-publication: target=<opaque-target-id>; anchor=<opaque-anchor-id>; set=<opaque-set-id>; session=<opaque-session-id>; token=<opaque-publication-token> -->
      
    • The originating Stage 1 hold uses this append-only publication-intent record, whose anchor follows the same self-anchor/non-anchor-child rule:

      <!-- <marker-prefix>-authoring-publication-intent: target=<opaque-target-id>; anchor=<opaque-anchor-id>; set=<opaque-set-id>; session=<opaque-session-id>; token=<opaque-publication-token>; journal=<owner>/<repo>#<number>; issue=<owner>/<repo>#<number>|none; actor=<trusted-marker-actor>; state=<pending|member|cleanup|abandoned> -->
      

      issue is the returned canonical issue identity or none. Append state=pending; issue=none before creation, then append the returned identity while it remains pending, append member only after the owner marker is verified, and append cleanup before any safe-close mutation. Append abandoned only after closed/label-absent verification. On resume, paginate the hold log and select the latest valid record for the exact token tuple; missing, conflicting, or out-of-order records fail closed, while pending and cleanup remain recovery holds.

      journal is the durable record location. For an existing set, use the verified originating Stage 1 hold; for a standalone set with no existing issue or anchor, use the repository-level authoring journal target configured at issueAuthoring.journalIssue in .github/idd/config.json (an owner/repo#number reference to a pre-existing, durable, comment-only issue) -- an unset issueAuthoring.journalIssue only blocks a standalone set; an existing set with a verified Stage 1 hold needs no journal configuration at all. Do not create that journal as part of the same set. If the applicable location cannot be resolved -- no verified Stage 1 hold for an existing set, or issueAuthoring.journalIssue unset or unverifiable for a standalone set -- stop with blocked-by-human before creating any target. On every paginated replay, require actor to equal the API author and verify that actor is a trusted marker login with the required write-level permission or configured bot/app trust. An untrusted, malformed, or conflicting exact-token record is not valid evidence; fail closed and retain the hold.

      Generate the opaque target id and token before creation because the new issue's own number is not yet known, and generate anchor the same way only when this new issue is the set anchor itself -- otherwise reuse the anchor's already-resolved real reference, per the self-anchor/non-anchor-child rule above. Before issuing the create, persist those preallocated IDs, the exact token, and state=pending in that journal. After a successful create, attach and verify the returned issue identities on that pending record before appending the owner marker. If the pre-create hold write cannot be verified, do not create; if the post-create identity attachment cannot be verified, leave the returned issue held for recovery. Transition to member only after owner-marker verification or abandoned only after the verified safe close and label removal. On resume, match the exact token and persisted identities; an incomplete scan or state mismatch is recovery.

    • immediately after a new issue is created and labeled, append its mode=acquire owner marker with the current set ID, then re-fetch the labels, body, and owner comments before treating it as a set member

    • an atomically labeled publication is not set membership until its owner marker is verified; persist each returned target identity in the journal before appending the marker. On resume, reconcile recorded identities and only issues carrying this set's exact publication token; an incomplete scan or unmarked match is a recovery hold, so never infer membership or completion from the shared label alone

    • if owner-marker append or verification is uncertain for a new issue, reconcile the returned comment ID and the paginated owner-marker log with bounded retries before closing; if a trusted marker is found, retain the label and recover or reopen the issue as a set member. Otherwise re-fetch labels, body, current claimed-by state, and the paginated owner-marker log; if that final read proves no competing claim or owner marker, append state=cleanup before closing the issue or removing its authoring label. Re-fetch and verify closed/label-absent state, then append state=abandoned. If any disposition or cleanup read is uncertain, retain state=cleanup, leave the issue held, and report the recovery hold

    • if an allegedly atomic create unexpectedly returns an unlabeled issue, re-fetch its labels, body, current claimed-by state, and paginated owner-marker log before closing. If a trusted claim or owner marker from another session/set is present, do not close or overwrite the exposed issue; report the ownership conflict and stop. If no competing claim is present, apply and verify the authoring label as a safe hold, then re-fetch its labels, body, current claimed-by state, and paginated owner-marker log again before closing. If that hold or final re-read cannot be verified, leave the issue open and report the recovery hold. Deletion needs admin permission and is not the default recovery path

    • held issues under the label ARE the drafts: do in-place body edits, roadmap relationship wiring, and re-lint of already-published bodies on the published issue itself, under the same label

    • if a session is interrupted before the set is fully wired, leave the label and owner markers in place — the label suppresses Discover and the markers preserve the set identity for a later verified resume

    • read every target and anchor owner-marker log with paginated retrieval and deterministic comment order; never rely on a single API page

    • after the release checklist passes and the user explicitly requests release — or, for a single target whose body carried the review-fix-loop-cutoff marker at Stage 1 publication time (never a marker added later), the narrow auto-release exception in Authoring hold and release — preflight and verify or reuse a matching mode=release marker for every target (with supersedes equal to the current owner token) before removing any label; record its GitHub comment ID, never append a duplicate on retry, append and reconcile an anchor-only mode=release-guard marker before the first label removal, keep the set anchor held, and remove it last. Recheck each target's expected owner token independently, plus the shared set/anchor/session, recorded marker, and expected snapshot immediately before each removal. Renew and verify the set anchor heartbeat first (reuse applies here too), re-fetching its current owner, set, anchor, and session; only then renew and verify the target heartbeat when distinct (one marker when they coincide; reuse applies here too). Remove non-anchor labels one at a time and verify the whole set. After the final anchor label removal is verified, reuse or append the anchor-only mode=release-complete marker and record its comment ID. Reconcile that ID and the paginated anchor log with bounded retries; a successful POST or verification timeout is inconclusive. If the trusted marker is found, keep labels absent and close the set. If a complete fresh read conclusively proves that no trusted marker was appended, restore labels for every target and leave every target generation open. If reads remain inconclusive, keep the release guard and current labels/state in place, leave the set held, and record a recovery hold. Never infer marker absence or roll back from a verification timeout. Discover must treat the reconciled release guard as suppressing every target until the anchor completion marker is found. Treat each release marker, removal, and completion marker as provisional until the durable completion event is reconciled. If a later removal or verification fails, retry a failed post-removal read with a bounded fresh read, restore labels for already processed targets while the owner/set still match, verify the restored set, and leave every target generation open

  8. Stop at the single approval boundary: release. Publishing under the hold does not by itself authorize starting the IDD execution loop — only the user's explicit release request does, except the narrow review-fix-loop-cutoff auto-release exception in Authoring hold and release.

Reference Routing

  • For the bundled contract, output schemas, and discoverability guard: read references/contract.md.
  • For the bundled two-stage authoring/release contract and the boundary with the IDD execution loop: read references/workflow-boundary.md.
  • For concrete drafting patterns and example prompts: read references/draft-patterns.md.
  • When editing this bundle inside the source repository, keep the bundled references synchronized with the canonical maintenance docs at repo-root docs/issue-authoring-skill.md and docs/idd-workflow.md (relative links are avoided here since this file is mirrored at a different path depth in .claude/skills/issue-authoring/).

Output Checklist

  • Preserve low-readiness work in stable buckets instead of dropping it.
  • Keep acceptance criteria explicitly verifiable.
  • Keep human-dependent setup, review, and approval work isolated from ready execution issues whenever possible.
  • Link every active child issue from its roadmap body.
  • Justify each dependency edge and keep independent sibling work as roadmap task-list entries.
  • Record reuse or extension decisions when the skill does not create a new issue.
  • Avoid widening drafting output beyond the user request without saying so.
  • Run the audit-authored-issue linter (or its manual fallback in instructions-only installs) against every drafted ready body, and against every body newly published into needs-decision or blocked-by-human with --expect-bucket; resolve every reported failure before publishing.
  • Name a concrete surface to edit and an objective verification for every ready candidate; route anything else to needs-decision or ask instead of guessing (the under-clarification stop rule).
  • Resolve the target repository's marker prefix before emitting any authoring marker; never assume this source repository's idd-skill prefix in an installed bundle (the prefix-first rule).
Files (idd-skill)
  • references
    • contract.md 114.9 KB
      # Bundled Issue Authoring Contract
      
      This file keeps the `issue-authoring` bundle usable when it is installed
      or copied outside this repository root. It mirrors the canonical
      contract in `docs/issue-authoring-skill.md`. That canonical document
      exists only inside this bundle's source repository — an installed copy
      of this bundle should not expect it to be present.
      
      ## Target marker prefix
      
      **Prefix-first**: resolve the target repository's hidden marker prefix
      before emitting _any_ authoring marker — `roadmap-id`, `blocked-by`,
      `autopilot-suitability`, or `effort`. Resolve it once, up front, not as
      an afterthought once a marker is already half-drafted.
      
      - Use the prefix documented by the target repository's onboarding or
        IDD instructions.
      - In this source repository the prefix is `idd-skill`, but installed
        bundles must not assume that value elsewhere. Never default to
        `idd-skill` in an installed bundle; use it only when the target
        repository actually configured that value.
      - If the prefix is not discoverable from the repository docs or user
        context, stop and ask instead of emitting a guessed marker
        (preventive; no observed incident yet). A prefix the operator already
        confirmed during an onboarding hearing (Steps 1A-1C of
        `idd-template/ONBOARDING.md`) counts as a resolved value under "user
        context" — even before it is committed anywhere in the target
        repository's tree — and does not require asking again.
      
      ## Trigger policy
      
      Use this bundle when direct implementation would skip the issue hygiene
      that the IDD execution loop depends on.
      
      Invoke it when one or more of the following are true:
      
      - the request is too large or ambiguous for one reviewable change
      - the likely solution needs decomposition into multiple atomic tasks
      - dependencies or execution order must be made explicit before work can
        start safely
      - the user wants a roadmap, issue breakdown, or parallelizable work
        plan
      
      Skip it when all of the following are true:
      
      - the task fits one reviewable change
      - verification is already clear
      - no roadmap, dependency marker, or issue split is needed
      - the user did not ask for issue drafting first
      
      ## Stable phases
      
      The bundle uses two stable phases. These names mirror the canonical
      contract and should stay stable for copied bundles.
      
      ### 1. Intake and Clarification
      
      In this phase, the agent:
      
      - inspects the relevant code, docs, and existing issues
      - identifies assumptions and ambiguity that affect issue quality
      - runs a secondary critique pass before drafting
      - asks the user only the questions that block safe issue drafting
      
      The critique pass is agent-neutral: use a subagent or rubber-duck
      reviewer when available, otherwise run an explicit self-critique
      locally. Clarification must be bounded; use the repository-local
      `issueAuthoring.maxClarificationRounds` value when available,
      otherwise default to 3 rounds. If safe drafting is still impossible
      after that, stop and report the remaining blockers instead of looping
      indefinitely.
      
      **Under-clarification stop rule.** If, after bounded clarification, you
      still cannot name the concrete surface to edit or an objective
      verification for a candidate task, route it to `needs-decision` or ask
      — do not publish a confidently-vague `ready` issue. Reliability over
      speed. This is distinct from the "Under-specified" specificity band
      below: that band judges an already-drafted body's wording, while this
      rule stops publication earlier, during Intake, before a body is even
      drafted.
      
      ### 2. Decompose and Draft
      
      In this phase, the agent:
      
      - restates the clarified request in implementation-facing terms
      - splits work into atomic tasks
      - checks whether each task is suitable for autonomous execution
      - reuses or extends existing issues before creating new ones
      - drafts orphan issues, roadmap packages, sub-issues, or non-ready
        buckets as appropriate
      
      ## Readiness buckets
      
      Do not silently drop low-confidence or low-readiness work. Route each
      candidate task into one stable bucket:
      
      - **ready**: passes limited scope, clear verification, and autonomous
        completion
      - **deferred**: plausible, but priority, timing, or decomposition is not
        strong enough for execution
      - **needs-decision**: depends on a product, policy, or design choice
      - **blocked-by-human**: waits on a person, credential, asset, or outside
        system
      - **out-of-scope**: does not belong in the repository or skill scope
      
      ## Specificity target
      
      Issue drafting should aim for a level of specificity where a
      middle-tier cloud model can implement the task without drifting. This
      is a practical drafting heuristic, not a hard model requirement. The
      goal is to avoid both hidden assumptions that only a top-tier model can
      infer and step-by-step runbooks that cost too much to author.
      
      ### Three specificity bands
      
      | Band                | Practical signal                                                                                                          | Drafting response                                                                    |
      | ------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
      | **Under-specified** | Stable execution likely depends on a frontier cloud model class                                                           | Add missing constraints, split scope, or make acceptance criteria more explicit      |
      | **Target**          | A middle-tier cloud model class can implement the issue without drifting                                                  | Treat this as the preferred drafting target when the execution axes already pass     |
      | **Over-specified**  | Even a lightweight local or compact cloud model class could follow the issue mechanically because it has become a runbook | Remove procedural micromanagement while keeping invariants, file anchors, and checks |
      
      The capability tiers above are practical heuristics, not a fixed
      compatibility matrix or runtime requirement.
      
      ### How the specificity target interacts with readiness
      
      This heuristic does not replace the IDD execution axes:
      
      - **Limited scope** still decides whether the work fits one issue or
        needs a roadmap.
      - **Clear verification** still decides whether success is objectively
        checkable.
      - **Autonomous completion** still decides whether the task can finish
        without outside coordination.
      
      An issue can be specific yet still fail A4 or A4.5 because it is too
      broad, not verifiable, or blocked on a human decision. Conversely, an
      issue that passes those gates can still be under-specified if it leaves
      too much implementation shape implicit. The drafting target is therefore
      "ready and stable for a middle-tier model," not "maximally detailed."
      
      ## Executability gate for code spec-units
      
      For a **code spec-unit** — a drafted unit whose acceptance criteria are
      objectively executable (a script, function, or test the drafted issue
      itself specifies) — an authoring session can validate the draft before
      publishing by building a throwaway reference implementation against its
      own stated acceptance check and accepting the draft only if that
      reference implementation passes. This reuses the downstream execution
      loop as an upstream ground-truth gate: it catches drafts whose
      acceptance criteria are internally inconsistent, non-trivially
      unsatisfiable, or otherwise not actually implementable, before a
      downstream executor ever claims the issue. The reference implementation
      is a discarded validation probe, never published — it does not cross the
      Publication boundary below; only the drafted issue itself is published,
      and building the probe does not start the IDD execution loop.
      
      This is a **recommended practice for repositories or domains where a
      drafted code spec-unit has an objectively executable acceptance
      check**, not a change to this repository's own mechanical
      `bin/idd-audit-authored-issue.mjs` checks or a new requirement on this
      repository's own issue-authoring practice — most of this repository's
      issues are multi-file engineering changes without a single executable
      acceptance check to validate against.
      
      - **Weak-model semantic self-review stays advisory.** When a weak
        authoring model reviews its own draft for semantic quality, treat the
        verdict as advisory only, never a hard veto on publishing — mirroring
        the narrow-question guidance for weak-model judgment calls in
        `docs/idd-workflow.md`'s Weak-model guardrails section.
      - **Decompose and draft want different model traits.** Decomposition
        (judgment about scope and structure) tolerates a verbose reasoning
        model; the structured draft step (emitting the exact spec/acceptance-
        criteria block) is more reliable on a leaner, more literal model,
        whose chain-of-thought does not compete with the drafted block for
        token budget. Pick the model per sub-task, not per pipeline, when both
        are available.
      - **Redraft and re-decomposition are limited rescue mechanisms, not
        reliable fixes.** A bounded redraft loop tends to re-roll rather than
        converge, because a weak author regenerates rather than incrementally
        fixes. Re-decomposing a repeatedly-failing unit is usually low-value
        too: most authoring failures are hard-but-atomic rather than
        over-broad, and splitting a hard-but-atomic unit tends to produce
        incoherent sub-units that do not recompose. Treat a code spec-unit
        that repeatedly fails this gate as a candidate for `needs-decision` or
        human/stronger-model authoring instead of looping indefinitely.
      
      ## Reuse-first issue policy
      
      Before creating any new issue, check whether the work already has a
      suitable home.
      
      **Claim-state precondition (check this first).** Before reusing or
      extending _any_ existing issue, determine whether it has an **active
      claim** (its latest valid `claimed-by` comment is newer than the
      configured `claim-stale-age`; distributed default 24 h) or an **open
      PR**, or is otherwise actively executing. If so, you **MUST NOT edit its
      body**: the working agent snapshots the issue body into its B2 plan and
      treats that plan as authoritative — it never re-reads the body, so a
      post-claim body edit is silently lost and becomes an implementation gap.
      You **may** add a separate **comment** (never an edit or append to the
      body), but **must not** rely on the claimed agent acting on it. Cover
      the intended change with a **follow-up issue** (or a roadmap track around
      it), and you **SHOULD** post a cross-reference comment on the claimed
      issue linking the follow-up. Stale or reclaimable claims (latest
      `claimed-by` older than `claim-stale-age`) are exempt — the next claimer
      re-reads the latest body, so editing them is safe.
      
      Then apply these checks in order:
      
      1. If an existing open issue already matches the task and only lacks the
         new schema details, extend that issue instead of cloning it.
      2. If an existing open roadmap already owns the initiative, add or
         refine task-list entries there instead of creating a competing
         umbrella.
      3. If an existing issue is close but too broad, split follow-up work
         out of it rather than widening the original issue further. When the
         issue being split is itself a roadmap child, update the parent
         roadmap's `## Tracks` list in the same authoring action — add the
         new issue's link and adjust any sequencing notes (a short dated note
         is the observed good pattern) — subject to the claim-state
         precondition above applied to the roadmap issue's own claim/PR
         state, and record the provenance in the new issue's body (e.g.,
         `Split out of #<n>`).
      4. If an existing issue has an **active claim**, an open PR, or is
         otherwise being actively executed, do **not** edit its body or
         repurpose it (see the claim-state precondition, which exempts
         stale/reclaimable claims); create a follow-up issue or extend the
         roadmap around it instead.
      5. Create a brand-new issue only when no existing issue can absorb the
         work without harming ownership, clarity, or reviewability.
      
      Report when the bundle reuses, extends, or declines to reuse an issue
      so a later session can follow the reasoning.
      
      **Recent-window scan for just-discovered problems.** The checks above
      assume the work already has a candidate home to reuse or extend. When
      instead authoring an ad hoc issue for a problem **just discovered**
      during the current session — a build-breaking regression noticed
      mid-session, for example, rather than a task drafted from an existing
      backlog — run a recent-window duplicate scan immediately before
      publishing: list the newest issues regardless of state and check
      whether a concurrent session already authored the same problem.
      
      ```sh
      gh issue list --repo <owner>/<repo> --state all --limit 20
      # or, scoped to a recency window:
      gh issue list --repo <owner>/<repo> --state all --search "created:>=<YYYY-MM-DD>"
      ```
      
      A hit routes back into the checks above: extend the discovered issue
      instead of publishing a duplicate. When the race slips past this scan
      anyway (near-simultaneous discovery), the outcome is **anticipated and
      self-resolving, not a coordination failure**: both sessions proceed
      independently through their own claim and implementation cycle;
      whichever PR merges first wins; the other session manually verifies
      the fix already landed on the default branch, then closes its own
      issue and (unmerged) PR as superseded, citing the verifying evidence.
      This is the same manual verify-then-close judgment call the execution
      loop's B2.0 supersession re-check (`idd-work.instructions.md`) applies
      after claim — this scan only adds an earlier, pre-publish checkpoint.
      A fast enough race can still surface even after B2.0; when it does, it
      resolves the same way.
      
      **Same-shape follow-up chains.** A different case from both checks
      above: an issue whose own acceptance criteria explicitly ask for a
      follow-up issue with the same acceptance criteria when the round does
      not fully complete (a "retry again" pattern, e.g., an iterative
      measurement or convergence task). Before drafting such a
      same-shape successor, state what measurable forward progress the
      just-completed round achieved — a changed metric, a narrowed diagnosis,
      a newly-tested hypothesis, a newly-discovered and now-fixed blocker.
      When the round produced no such signal (the same result, the same
      diagnosis, no new information beyond the predecessor), route to
      `needs-decision` (or an equivalent hold) instead of authoring another
      identical-shape issue, and record why the chain paused so a later
      session or human can see the reasoning. This is a sibling check, not a
      replacement: the checks above guard against an accidental duplicate;
      this guards against a correct-but-repeated pattern continuing past the
      point it stops being useful.
      
      ## Output chooser
      
      Choose the smallest safe output shape:
      
      - **Orphan issue**: one autonomous task can finish the work, no
        roadmap-level coordination is needed, and the target repository
        discovers orphans — i.e. `issue-scope` is `roadmap-first` (the
        default; orphans are picked up as the fallback when no roadmap work is
        startable) or `orphan-first` (orphans first). If the repository uses
        `orphan-first-policy: maintainer-approved`, surface the required
        post-publication maintainer approval step. If the repository sets
        `issue-scope: roadmap` (roadmap-only) or disables public orphan-first
        discovery with `orphan-first-policy: public-disabled`, surface that
        constraint and prefer a roadmap package instead.
      - **Roadmap plus sub-issues**: the request needs visible sequencing,
        parallel tracks, multiple ready issues, or multi-session handoff.
      - **Stable non-ready buckets**: some work is deferred, blocked by a
        human, waiting on a decision, or outside the repository scope.
      
      When the repository keeps the broader issue-author approval gate,
      surface the same post-publication approval step for orphan issues,
      roadmaps, and sub-issues whenever the issue author is not
      self-authorizing under the repository's
      `maintainer-approval-actors` policy. The configured ready label from
      `approvalSignals.readyLabelName` (default: `idd:ready`) is accepted
      according to `approvalSignals.labelFreshnessMode` (`presence-only` by
      default, optional `event-freshness`), while standalone `IDD ready`
      comments from a maintainer approval actor must stay fresh against the
      latest issue content and generated-plan update (or an equivalent
      draft-stability signal). Until that approval condition is satisfied,
      route the draft to the
      approval-needed fallback bucket instead of the normal ready-to-start
      set.
      
      ## Human-dependency isolation
      
      Treat unresolved human dependency as a side effect that should be
      isolated away from ready execution issues whenever possible.
      
      - **Front-load** human-dependent work when coding cannot start safely
        until a person provides a decision, credential, permission,
        maintainer-only action, external setup, or policy choice, or until an
        unavailable system becomes usable again.
      - **Back-load** human-dependent work when the remaining dependency is
        subjective review, publication choice, optional polish, or another
        post-implementation judgment that should not block an otherwise
        autonomous core change.
      - Keep the central execution issue as close as possible to a pure
        autonomous unit: clear repository-local scope, no hidden human handoff
        in the implementation steps or acceptance criteria, and objective
        verification.
      - Preserve unavoidable human-dependent work in an explicit stable
        bucket, dependency edge, or approval-needed hold rather than mixing it
        into a ready issue.
      - Route unresolved choices to `needs-decision`, route waiting on people,
        credentials, maintainer-only actions, or unavailable systems to
        `blocked-by-human`, use `deferred` when timing or decomposition is not
        strong enough yet, and keep approval-gated ready work in the
        approval-needed hold instead of the normal ready-to-start set.
      - If a task cannot be expressed without unresolved human coordination in
        the middle of implementation, it is not yet `ready`.
      
      This principle complements the execution axes rather than replacing
      them: it is a practical way to protect autonomous completion and clear
      verification during issue drafting.
      
      ## Hidden human-dependency validation
      
      Before publishing a `ready` issue, run a short pre-publication check for
      hidden human dependency. Treat this as a routing aid, not a rigid
      wording linter: the question is whether the work still depends on
      unresolved human action, not whether the draft used one forbidden
      phrase.
      
      Ask these checks:
      
      1. Does implementation require credentials, external access, hardware,
         or infrastructure that the executing agent cannot already reach? If
         yes, route the work to `blocked-by-human` unless that dependency can
         be front-loaded into a separate prerequisite issue.
      2. Does any implementation step or acceptance criterion depend on a
         product, policy, or design decision that has not been made? If yes,
         route the work to `needs-decision`.
      3. Do the acceptance criteria require subjective human approval instead
         of objective verification? If yes, rewrite the ready issue around
         measurable checks and back-load the optional review or publication
         judgment.
      4. Does a roadmap narrative hide human-dependent work inside prose while
         the visible task list presents the item as execution-ready? If yes,
         preserve that work in an explicit stable bucket, approval-needed
         hold, or blocking issue instead of burying it in the narrative.
      5. Is any dependency marker being used only to group related work or
         express preference order? If yes, remove the fake blocker and use
         task-list structure or sequencing notes instead. Keep dependency
         edges only for true start blockers.
      
      Normal post-implementation code review, merge approval, or publication
      choice does not by itself make an otherwise autonomous issue non-ready.
      The ready issue should still carry its own objective verification even
      when a human will look at the result afterward.
      
      ## Codebase-fidelity validation
      
      Before publishing a `ready` issue, run a short pre-publication check that
      the spec stays faithful to the existing codebase. Treat this as a routing
      aid, not a rigid wording linter: A4.5 suitability triage is structural and
      does not read the codebase, so a spec that contradicts established
      semantics can still pass that gate and only surface the mismatch in
      advisory review, costing extra review-fix round-trips.
      
      Ask these checks:
      
      1. When an issue reuses an existing identifier or field name, confirm the
         specified value matches that name's established semantics in the
         codebase — do not overload a name with a new shape or source.
         **Remedy**: mint a new, distinctly named field instead of overloading
         the existing one. Worked example: a candidate issue's acceptance
         criterion reads "set `retryAttempts` to the elapsed wait time in
         milliseconds" — `retryAttempts` already means a whole-pass apply
         attempt _count_ in `audit-pr-cleanup.mts`'s `CleanupAuditReport`, so
         reusing it for a duration overloads an established name with an
         incompatible shape. Fix: mint a new field instead, e.g.
         `retryWaitMs`, and leave `retryAttempts` untouched.
      2. Flag values that are mutable at runtime — specify a live read at the
         point of use rather than a one-time capture at construction.
      3. When an issue proposes to **delete, replace, or "align to upstream"**
         code, first check the target for an intentional-divergence signal — a
         local change made on purpose to differ from upstream. If one is present,
         require the issue body to acknowledge that divergence and justify
         overriding it, rather than silently reverting hardening a consumer added
         deliberately (blind "resync to upstream" resets are a recurring
         Discover→plan-cycle waste when the divergence turns out to be
         intentional). The recommended portable signal is a canonical inline
         code-comment convention (for example a `do-not-revert:` / `idd-divergence:`
         marker) — it travels with vendored files and needs no repo-wide label
         taxonomy. An owner/CODEOWNERS marker or a referenced tracking issue may
         also serve, but the code-comment convention is the recommended default.
         Do not hard-code any single consumer's divergence-tracking mechanism.
      4. When an issue drafts a **template resync or reimport** (pulling a
         newer `idd-template/` revision into a repository that already
         adopted IDD), consult the **upstream target ref's** copy of
         `docs/customization.md`'s "Documentation lint compatibility"
         section (added 2026-08-05, commit `6ceaa6dd`) before treating
         `.markdownlint.yml` / `.markdownlint-cli2.yaml` / `.cspell.config.yml`
         as unchanged. `docs/customization.md` is itself part of the
         imported core file set, so it resolves in an installed or adopter
         context once present — but an adopter whose prior import predates
         that commit has no such section in their own local copy yet, which
         is exactly the named gap to document in the resync issue, not a
         documentation-consultation failure. Either the target ref's
         `docs/customization.md` section or, from a source checkout of
         `idd-skill` itself, `idd-template/ONBOARDING.md`'s "Re-importing"
         section, documents the same named gap: an adopter's own rule
         customizations for these files need a by-hand merge into the new
         import rather than an assumed carry-forward, and
         `idd-onboard.mjs --import` reports a `blockedOverwrites` finding
         instead of silently keeping a same-named local file as-is, unless
         the import used `--force`, which still writes the file and reports
         it in the verdict JSON (`plan` as an `overwrite` entry,
         `filesChanged`, and `written`) but omits it from
         `blockedOverwrites` so the import is not blocked (observed
         2026-08-12/13 on an
         adopter repository, `setup.ubuntu`, kurone-kito/idd-skill#2012).
      5. When drafting a resync issue's Background, run a mechanical
         placeholder diff against the **upstream `idd-skill` source
         repository's** `idd-template/` trees at the two relevant refs —
         never a tree inside the target/adopter repository itself, which
         retains no local `idd-template/` directory of its own once IDD is
         imported.
         - **Baseline ref.** Use the exact tag or commit SHA actually
           imported at the adopter's prior onboarding when it is explicitly
           recorded (for example in the original onboarding PR/commit
           message) or when the operator can confirm it directly. Do not
           infer it from the adopter's current file content: neither a diff
           against the import commit nor a reverse- or forward-substitution
           content-match against a candidate upstream tree reliably pins a
           single ref — onboarding substitutes placeholder values and
           permits legitimate post-substitution edits, an import commit's
           diff itself only records the already-transformed adopter
           snapshot, and more than one upstream commit can plausibly yield
           the same imported subset. When no explicit record or operator
           confirmation is available, report the baseline as
           unresolved/ambiguous in the resync issue itself rather than
           guessing one from content alone. Do not construct `v<iddVersion>`
           (`.github/idd/config.json`) as the baseline without this check:
           `iddVersion` is only a coarse signal and can be stale, an adopter
           still on `0.1.0` has no matching tag at all (`CHANGELOG.md`
           records that `0.1.0` predates the tag discipline), and an adopter
           who pinned a raw
           commit SHA at import time instead of a tag may have no
           `v<iddVersion>` tag matching what they actually imported either.
         - **Target ref.** The new release/ref the resync targets.
         - **Scope.** Intersect both trees with the Step 2 "File list" core
           file set as it reads **at the target ref**
           (`idd-template/ONBOARDING.md`'s generated file-list block) plus
           whichever optional profile artifacts the adopter selected, not
           the complete `idd-template/` tree — a file such as
           `idd-template/ONBOARDING.md` itself is never copied into an
           adopter, so reporting it as changed is noise. Use the target
           ref's manifest, not the baseline ref's: a file the target release
           newly added to the core or a selected profile is exactly the kind
           of change a resync issue must report, and the baseline ref's own
           manifest predates it.
         - **Token filter.** Compare each ref's own placeholder table in
           effect at that ref, not today's list applied to both — a
           placeholder added or removed between the two refs is itself
           exactly the kind of token-identity change this check exists to
           report, and reusing one ref's list for the other's tree would
           hide that change. At a ref from commit `e55ccd9c` (2026-05-12)
           onward, that table is Onboarding Reference — Placeholder Values'
           "Final placeholder meanings" table
           (`docs/onboarding/placeholders.md`). An older ref has no such
           file — the placeholders were documented directly inside
           `idd-template/ONBOARDING.md`'s own "Step 1C — Collect placeholder
           values" section instead; use that section's list as the
           allowlist for a baseline ref that old. Never match every
           `{{...}}`-shaped span unfiltered either way — an unrestricted
           match also catches ordinary GitHub Actions expressions such as
           `${{ github.token }}` in an imported workflow file.
         - **Excluded paths.** Skip `docs/onboarding/placeholders.md`,
           `docs/customization.md`, and `docs/onboarding/policy-decisions.md`
           — these deliberately keep `{{...}}` tokens literal to document
           the placeholder syntax itself, so diffing them misidentifies
           literal documentation as an outstanding substitution.
      
         Compare the actual token identities per changed file, not only the
         aggregate occurrence count: a same-count one-for-one placeholder
         swap changes what an adopter must substitute without changing the
         count. Name any file whose placeholder tokens changed, rather than
         asserting a file needs no placeholder substitution as an unverified
         default (observed 2026-08-12/13 on an adopter repository,
         `setup.ubuntu`, kurone-kito/idd-skill#2012).
      
      ## Live-observed claim citation
      
      When a drafted issue's Background section (or its `## Goal` / `## Why
      this matters` equivalent, per the schema in use) asserts a "live
      observed" runtime behavior claim (as opposed to a claim verifiable by
      reading static source), cite a concrete, checkable artifact for it — a
      permalink, a PR/comment/run ID, or an inline reproduction snippet —
      rather than only a prose description of the observed event. A drafting
      session that already has the artifact in hand (a PR review thread, a
      workflow run, an adopter's own report) should cite it directly instead
      of paraphrasing from memory; a worked example already exists elsewhere
      in this file: "(observed 2026-08-12/13 on an adopter repository,
      `setup.ubuntu`, kurone-kito/idd-skill#2012)".
      
      This is not a mechanical `audit-authored-issue` gate check: a
      live-observed claim is prose-level and not reliably machine-detectable
      without a high false-positive risk. Apply this discipline at drafting
      time instead, before an unsupported claim ships in one of these
      sections that another session or reviewer cannot independently
      re-verify.
      
      ## Dependency minimization
      
      Encode a dependency edge only when it reflects a true correctness,
      availability, or ordering constraint.
      
      - keep independent sibling tasks as roadmap task-list entries, with
        short sequencing or parallelization notes when that helps reviewers or
        later agents
      - use visible or sequential dependency markers only when the issue
        cannot start safely until the dependency resolves
      - do not create an artificial serial chain when sibling tasks could be
        reviewed and verified independently
      - do not split one natural, cohesive change into artificial sibling
        issues only to widen parallel execution
      - whenever an issue's own narrative states that its work cannot safely
        start until another named issue resolves, encode `Blocked by #NNN`
        for that issue rather than leaving the constraint as prose-only
        sequencing. Discover and A4.5 honor the hard `Blocked by` edge, not
        a narrative "runs after #NNN" note: A4.5 Actionability inspects the
        body, not completability, so a narrative-only dependency reports the
        issue startable the moment its other filters pass, and claiming it
        then means either violating the asserted constraint or doing the
        referenced issue's unresolved work first. This rule is general, not
        limited to a fixed list of cases; the two recurring patterns below
        are illustrative, not exhaustive
      - **example — docs or operator-help child that documents behavior
        implemented by sibling issues**: encode `Blocked by #NNN` for those
        implementation issues (or otherwise sequence the docs child to run
        after they merge) so the documentation is written against **shipped**
        behavior. Describing designed-but-unshipped behavior in the present
        tense is a recurring advisory-review-thrash pattern; "describe shipped
        behavior" is a true ordering constraint, so this edge is consistent
        with the encode-only-a-real-constraint rule above
      - **example — finalize or verify track whose acceptance criteria
        assert state produced by sibling implementation tracks**: encode
        `Blocked by #NNN` on **each** such sibling rather than stating the
        ordering only in prose. A prose-sequenced finalize track reports
        startable the moment its build foundation closes, and claiming it
        then means either failing its acceptance criteria or doing
        the siblings' unmerged work
      - once a `Blocked by #NNN` / `Depends on #NNN` reference resolves —
        the referenced issue closes **with its required outcome verified as
        delivered**, not merely closed as not-planned, superseded without an
        equivalent implementation, or later reopened — revisit the blocked
        issue's own body and remove that reference and its explanatory wait
        prose, rather than leaving it in place as inert history, but keep
        any prose identifying the delivered artifact or interface this
        issue's own scope depends on. A line naming several references
        (`Blocked by #10, #11`) keeps the still-open ones — remove only the
        resolved reference, and remove the whole line only once every
        reference on it has resolved. When the
        underlying constraint is not actually met, reopen the prerequisite
        issue or repoint the dependency line at an open replacement issue
        instead of leaving a stale edge in place:
        `discover-readiness-check` blocks only on an `OPEN` referenced
        issue, regardless of why it closed, so retaining the edge alone does
        not keep the dependent issue blocked. (Observed 2026-08-13 on issue
        #1994's `Blocked by #1985` note, after #1985 closed; reported in
        #2002.) This cleanup is more than tidiness: stale wait-explaining
        prose can trip `checkVerifiability`'s subjective-approval heuristic
        in
        `suitability-triage.mts`, which matches either a single line
        combining a subjective-subject word (`maintainer`, `stakeholder`,
        `human`, `opinion`, `judgment`/`judgement`, `ux`, or `feel` — not
        only authority nouns) with a gate word (`approval`, `sign-off`/
        `signoff`, `decision`, or `preference`), or a gate word followed
        within 80 characters — including across lines — by a
        subjective-subject word.
        This still fires even though the structural dependency filter
        already correctly treats the closed reference as unblocking
      
      When an issue keeps a dependency edge, justify each dependency edge in
      the surrounding issue body and confirm that the split still preserves
      natural cohesion.
      
      ## Nested roadmap nodes
      
      Use a nested roadmap when one roadmap track needs its own coordination
      boundary, active child list, or multi-session handoff. A nested roadmap
      is still a roadmap node, not a normal execution candidate.
      
      Authoring rules:
      
      - reference the nested roadmap from the parent roadmap task list instead
        of hiding it in prose
      - give the nested roadmap its own roadmap marker and `## Tracks` section
        that links the active child work it coordinates
      - treat the nested roadmap as a coordination/audit node for discovery
        and roadmap audit; do not draft it as normal A3/A4/A5 execution work
      - use two-level or three-level nesting only when the intermediate
        roadmap has its own active child work or handoff boundary
      - do not use `Blocked by #NNN` or
        `<!-- <marker-prefix>-blocked-by: ... -->` only to group leaf issues
        under an active nested roadmap; reserve those encodings for true
        execution dependencies or sequential roadmap dependencies between
        separate roadmaps
      
      Validation expectations:
      
      - each nested roadmap node is linked from its parent roadmap task list
      - each nested roadmap node links its own active child work from its body
      - cycles, duplicate references, and closed intermediate roadmaps with
        hidden open descendants must be surfaced as validation failures or
        explicit follow-up notes, not silently normalized away
      
      ## Required dependency encoding
      
      - Roadmap identity via `<!-- <marker-prefix>-roadmap-id: ... -->`
      - Active child issues via roadmap task-list links
      - Issue-to-issue dependencies via `Blocked by #NNN`
      - Sequential roadmap dependencies via
        `<!-- <marker-prefix>-blocked-by: ... -->` only when a separate
        roadmap
        must close first
      
      ## Required draft content
      
      ### Candidate files format
      
      The `## Candidate files` section is not free-form prose: the
      `discover-shared-file-overlap` evidence helper parses it as machine input
      for the A4 Step 2 high-contention shared-file check (see
      [High-contention shared-file overlap](https://github.com/kurone-kito/idd-skill/blob/main/docs/policy-constants.md#high-contention-shared-files)).
      Populate it accurately rather than as a loose reading aid for humans.
      Optional for an orphan or roadmap issue; required for a
      [child issue under a roadmap](#child-issue-under-a-roadmap) (see
      [Required draft content](#required-draft-content) below).
      
      - List each candidate file path inside backticks, one path (or one
        bullet) per line — for example `` - `src/scripts/idd-onboard.mts` ``.
        The parser extracts every backtick-quoted path in the section,
        including continuation lines of a multi-line bullet.
      - A bullet with no backticks at all still falls back to its leading
        path-like token, but backtick-quoting every path is the reliable form
        and should always be used.
      - The section ends at the next Markdown heading, **of any level** —
        even a deeper subheading closes it. Anything inside it that looks
        like a path — backtick-quoted or a bare bulleted leading token — is
        parsed as a candidate file, so keep unrelated notes, caveats, or
        subheadings outside the section.
      
      ### Orphan issue
      
      - title with a concise user-facing summary
      - `## Background` or `## Goal`
      - `## Proposed change`
      - `## Acceptance criteria`
      - an autopilot-suitability footer at the end of the body (visible
        line + `<!-- <marker-prefix>-autopilot-suitability: N -->` marker;
        see [Autopilot-suitability score](#autopilot-suitability-score))
      - an optional effort footer next to it (visible line +
        `<!-- <marker-prefix>-effort: S|M|L -->` marker; see
        [Effort hint](#effort-hint)) — a soft Discover selection tie-breaker,
        fail-safe on absence
      
      Validation expectations:
      
      - no `<marker-prefix>-roadmap-id` marker
      - no `<marker-prefix>-blocked-by` marker
      - acceptance criteria are explicitly verifiable
      - the issue stays discoverable under the target repository's
        `issue-scope` setting
      - exactly one autopilot-suitability footer with an integer 1-5
        marker; a score of `1` carries the configured `blocked-by-human` label
        (default `status:blocked-by-human`), unless an
        `authoring-bucket: needs-decision` marker substitutes the configured
        needs-decision label instead (see
        [Authoring-bucket marker](#authoring-bucket-marker))
      - passes the `audit-authored-issue` mechanical pre-publish gate for the
        `orphan` shape (see [Mechanical pre-publish gate](#mechanical-pre-publish-gate))
      
      ### Roadmap issue
      
      - title that describes the umbrella initiative
      - `## Goal`
      - `## Background` or `## Why this matters`
      - `## Tracks`
      - `## Success criteria`
      - one `<!-- <marker-prefix>-roadmap-id: <roadmap-id> -->` marker
      - an autopilot-suitability footer at the end of the body (visible
        line + `<!-- <marker-prefix>-autopilot-suitability: N -->` marker)
      - an optional effort footer next to it (visible line +
        `<!-- <marker-prefix>-effort: S|M|L -->` marker; see
        [Effort hint](#effort-hint)) — a soft Discover selection tie-breaker,
        fail-safe on absence
      
      Validation expectations:
      
      - every active child issue or nested roadmap node is referenced from the
        roadmap body
      - the roadmap explains why multiple issues exist
      - sequencing and blocking are explicit
      - each dependency edge is justified and preserves natural cohesion
      - nested roadmap entries stay identifiable as coordination/audit nodes
        instead of normal execution leaves
      - exactly one autopilot-suitability footer with an integer 1-5
        marker; a score of `1` carries the configured `blocked-by-human` label
        (default `status:blocked-by-human`), unless an
        `authoring-bucket: needs-decision` marker substitutes the configured
        needs-decision label instead (see
        [Authoring-bucket marker](#authoring-bucket-marker))
      - passes the `audit-authored-issue` mechanical pre-publish gate for the
        `roadmap` shape (see [Mechanical pre-publish gate](#mechanical-pre-publish-gate))
      
      ### Child issue under a roadmap
      
      - title with a concrete task summary
      - `## Background`
      - `## Proposed change`
      - `## Acceptance criteria`
      - `## Candidate files` (see
        [Candidate files format](#candidate-files-format) above)
      - optional dependency line or sequential roadmap marker when needed
      - an autopilot-suitability footer at the end of the body (visible
        line + `<!-- <marker-prefix>-autopilot-suitability: N -->` marker)
      - an optional effort footer next to it (visible line +
        `<!-- <marker-prefix>-effort: S|M|L -->` marker; see
        [Effort hint](#effort-hint)) — a soft Discover selection tie-breaker,
        fail-safe on absence
      
      Validation expectations:
      
      - the issue is referenced from its parent roadmap task list
      - acceptance criteria are locally verifiable
      - `## Candidate files` lists the files the child is expected to touch,
        so the A4 Step 2 high-contention shared-file check
        (`discover-shared-file-overlap`) can actually engage instead of
        silently no-opping for lack of input
      - any dependency marker is resolvable, intentionally chosen, and
        justified
      - the issue can be claimed independently without absorbing sibling work
      - exactly one autopilot-suitability footer with an integer 1-5
        marker; a score of `1` carries the configured `blocked-by-human` label
        (default `status:blocked-by-human`), unless an
        `authoring-bucket: needs-decision` marker substitutes the configured
        needs-decision label instead (see
        [Authoring-bucket marker](#authoring-bucket-marker))
      - passes the `audit-authored-issue` mechanical pre-publish gate for the
        `child` shape (see [Mechanical pre-publish gate](#mechanical-pre-publish-gate))
      
      ## Drafted issue prose language
      
      A drafted issue's human-readable prose sections — `## Background` (or
      `## Goal`/`## Why this matters`), `## Proposed change`,
      `## Acceptance criteria`, and the roadmap shape's `## Tracks` /
      `## Success criteria` — follow the target repository's resolved
      `authoringLanguage` value from `.github/idd/config.json`:
      
      - A fixed BCP-47-shaped tag (for example `en`, `ja`, `fr`) makes the
        drafted prose use that language.
      - The literal `match-source` matches the operator's live conversational
        language during an interactive/hearing issue-authoring session.
      - An absent field defaults to English.
      
      See `docs/customization.md`'s Authoring Language section for the full
      field definition.
      
      **Marker/footer carve-out**: this never changes any HTML-comment
      marker's machine-parsed format, nor any visible-line mirror whose exact
      wording a mechanical regex parses. Concretely, the autopilot-suitability
      and effort footers' visible lines (`_Autopilot suitability: N / 5 ...`
      / `_Effort: S | M | L ...`) must stay in their exact canonical English
      wording regardless of `authoringLanguage`, since `audit-authored-issue`
      matches them against a fixed English-phrase regex.
      
      ## A4.5 Suitability Gate Alignment
      
      When an issue is published and reaches the IDD discover phase, the A4.5
      pre-claim gate will evaluate it against seven suitability checks. The
      authoring skill should catch these issues before publishing:
      
      | Check                    | Authoring Bucket     | How to Prevent                                                                  |
      | ------------------------ | -------------------- | ------------------------------------------------------------------------------- |
      | Repository Fit (Check 1) | `out-of-scope`       | Ensure issue is scoped to this repository; escalate if it crosses boundaries    |
      | Coherence (Check 2)      | `ready` or escalated | Validate issue body against schema before publish                               |
      | Safety/trust (Check 3)   | `ready` or escalated | Screen issue body for code injection and untrusted markers                      |
      | Duplicates (Check 4)     | `ready` or escalated | Run reuse-first checks before creating a new issue                              |
      | Actionability (Check 5)  | `ready` or escalated | Ensure the issue describes concrete work; escalate if blocked by human decision |
      | Autonomy (Check 6)       | `ready` or escalated | Ensure agent can complete without external coordination                         |
      | Verifiability (Check 7)  | `ready` or escalated | Ensure success is verifiable; escalate if it requires subjective approval       |
      
      **Check 7 escape-hatch pattern**: an either/or acceptance-criteria bullet
      where one branch is a substantive change and the other reads as "or
      document the gap/tradeoff" is not an automatic Check 7 PASS -- the
      documentation branch must itself name a concrete, checkable requirement,
      or evaluate it on its own merits and route to `needs-decision`. See
      `idd-suitability.instructions.md`'s Edge Cases section ("Escape-hatch
      acceptance criteria") for the full worked example.
      
      Pre-publish validation checklist:
      
      1. **Coherence**: Issue body is well-formed, title+description are
         clear, intent is parseable
      2. **Safety**: No code injection, marker injection, or untrusted input
         in issue body
      3. **Uniqueness**: Reuse-first check passed; no duplicate or superseded
         work
      4. **Human dependency isolation**: Ready issues do not hide unresolved
         decisions, credentials, subjective approvals, or mid-implementation
         human handoffs
      5. **Mechanical audit**: the drafted body passes the
         `audit-authored-issue` linter for its declared shape (see
         [Mechanical pre-publish gate](#mechanical-pre-publish-gate))
      
      If any check is uncertain, route the issue to `needs-decision` or
      `blocked-by-human` during drafting instead of publishing a
      marginally-ready issue.
      
      ## Mechanical pre-publish gate
      
      Before publishing a drafted `ready` **orphan, roadmap, or child** body
      (the shapes the linter supports), run the `audit-authored-issue`
      linter against it when a helper runtime is available. Before newly
      publishing a body into the **`needs-decision`** or **`blocked-by-human`**
      bucket instead, also run it, passing
      `--expect-bucket <needs-decision|blocked-by-human>` (choose the one
      matching value): without this, the two mechanical
      checks below that key off the `authoring-bucket` marker
      (see [Authoring-bucket marker](#authoring-bucket-marker)) never
      actually fire in practice, since a non-`ready` body is otherwise never
      run through this gate at all — exactly the gap that let #2636/#2637
      publish without their required label (#2639 follow-up). `--expect-bucket`
      requires the matching marker to be present, failing when it is absent
      or disagrees; omit it for a `ready` publish or an edit to an
      already-published legacy body, where the marker stays optional and
      fail-safe on absence as documented in that section. `deferred` and
      `out-of-scope` bodies are not audited by this gate either way. It
      mechanically re-checks a subset of the structural rules this contract
      states in prose — the autopilot-suitability marker's
      exactly-one/coherent-value rule, the one-directional check that a
      suitability score of `1` (or an `authoring-bucket: blocked-by-human`
      marker, when present) carries the configured `blocked-by-human` label
      (it does not check the reverse: a non-`1` score paired with the label
      still passes), the equivalent one-directional check for
      `authoring-bucket: needs-decision` and the configured
      `needsDecisionLabelName` label, markerPrefix consistency across every
      authoring marker, the declared shape's required section headings, the
      roadmap-id/blocked-by dependency-marker rules, and visible/hidden line
      agreement for the suitability and effort footers — so a weak model does
      not have to hold every rule in its head at once while drafting.
      
      The linter also emits one **advisory, warning-severity-only** finding
      (`prose-dependency`): it flags an issue/PR reference (`#<digits>` or a
      full GitHub issue/PR URL) that appears near coordination language (for
      example "before", "after", "once", "until", "predates", "gate"/"gated",
      "requires", "lands first") with no corresponding encoding for that
      reference as one of four recognized forms: a `Blocked by #NNN` line, a
      `Depends on #NNN` line, a task-list checkbox item (`- [ ] #NNN`), or a
      `Refs #NNN (non-blocking)` line — the same forms
      `extractBlockedByIssueNumbers` / `extractDependencyIssueNumbers` /
      `extractNonBlockingReferenceIssueNumbers` already recognize elsewhere
      in this contract. A task-list checkbox counts regardless of which
      heading it sits under, so a roadmap's own `## Tracks` membership list
      already satisfies this — it is not a separate "dependency-only" list.
      Use `Refs #NNN (non-blocking)` (multi-target: `Refs #NNN, #NNN
      (non-blocking)`) for a reference that is deliberately informational —
      a roadmap narrative naming a related, currently-blocked follow-up
      issue with no ETA, for example — never for a real dependency: unlike
      the other three forms,
      `discover-roadmap-graph.mts`'s traversal never enters this reference's
      target at all, so it cannot become an A1.5 closure-audit blocker, and
      this check treats it as already-encoded the same as the other three
      forms (#2236). This catches the pattern this contract's own
      [Hidden human-dependency validation](#hidden-human-dependency-validation)
      check 4 warns about in prose — a hard precondition stated only in
      narrative text, not encoded as a real dependency marker. A full-URL
      reference is inherently local only when it actually names the current
      repository, since a cross-repo dependency cannot be encoded with these
      repository-local markers at all — flagging it would recommend an
      impossible fix. When the caller supplies the current `owner/repo`
      (`--current-repo`, defaulting to `$GITHUB_REPOSITORY` in CI), a
      full-URL reference naming a different repository is never flagged;
      without that context, a full-URL reference is still flagged by
      default (unchanged behavior) — unless its issue/PR number happens to
      already appear as a local `Blocked by` / `Depends on` / task-list
      marker elsewhere in the body, in which case it is treated as already
      encoded like any other match. A Markdown link's target may carry
      trailing content after the issue/PR number and before the link's
      closing paren — a URL fragment (`#issuecomment-123`), a trailing `/`,
      or a quoted link title (`"..."` or `'...'`) — and the link is still
      recognized as one match; without this, the label's own bare `#NNN`
      would otherwise leak through to the bare-`#` check and be misjudged
      independently of the link's (possibly cross-repo) target. A local
      `owner/repo#N` shorthand (e.g. `kurone-kito/idd-skill#4321`) is also
      recognized, but with the reverse default from the full-URL case above:
      it is flagged only when `--current-repo` is supplied **and**
      case-insensitively matches `owner/repo`; naming a different repository,
      or omitting `--current-repo`, always excludes it, since this shorthand
      was never recognized at all before and a bare `owner/repo` cannot be
      assumed local without confirmation. A reference-style Markdown link
      (`[text][ref]` with a separate `[ref]: target` definition elsewhere in
      the body) is recognized the same way as the inline-link form above,
      including the same `currentRepo`-based local/cross-repo comparison; a
      `ref` with no matching definition is left as literal text and falls
      through to the bare-`#` check like any other unrecognized shape. A
      quoted link title may contain a backslash-escaped quote matching its own
      delimiter (`\"` inside a `"..."` title, or `\'` inside a `'...'` title)
      without ending the title early and losing the rest of the link. An empty
      or whitespace-only `--current-repo` (or `$GITHUB_REPOSITORY`) is treated
      the same as omitting it entirely, rather than as a known repository that
      can never match. A nested/child list item's reference is evaluated
      together with its full ancestor chain's coordination-language text
      instead of being scoped away from it, while a sibling bullet at the same
      indentation — nested or top-level — still starts its own separate scope,
      so a tight list (no blank line between sibling items) never reads two
      consecutive bullets' coordination language as one continuous sentence.
      This holds for every nested child under a given parent, at any depth — not
      only the first. A continuation line resuming at an ancestor's own
      indentation, after a deeper child has already opened, is attributed to
      that ancestor rather than the deepest open child. A loose list (a blank
      line between sibling items) preserves the same ancestor scope across
      the blank line, as long as the following item's own marker is no deeper
      than whatever is still open at the end of the preceding item — a
      same-depth sibling, or a resumption at a shallower ancestor's own
      level — and the preceding item ends in a list marker rather than
      trailing plain prose (once plain prose follows the last marker, the
      list reads as already having ended, so the blank line is not bridged).
      A blank line directly followed by a more deeply indented marker is also
      not bridged, to avoid grafting an unrelated item onto an open ancestor
      as a false child. Unlike every other check above, a
      `prose-dependency` warning never flips `passed` to `false` and never
      changes the linter's exit code: it prompts the author to either
      convert the prose into a proper dependency marker or consciously
      confirm the reference is a mere breadcrumb.
      
      ```sh
      node scripts/audit-authored-issue.mjs --shape <orphan|roadmap|child> \
        --marker-prefix <resolved-target-prefix> \
        --body-file <path-to-drafted-body> [--label <label>]... \
        [--expect-bucket <needs-decision|blocked-by-human>]
      ```
      
      Or, for npx/package-manager profiles, the equivalent
      `idd-audit-authored-issue` command. Pass `--stdin` instead of
      `--body-file` when the drafted body is not yet written to disk.
      **Always pass `--marker-prefix`** with the prefix resolved under
      [Target marker prefix](#target-marker-prefix): without it, the linter
      falls back to reading `.github/idd/config.json` from the current
      working directory, and if that file is missing or unreadable — for
      example when running from an installed bundle without a local
      checkout of the target repository's config — it silently defaults to
      this source repository's own `idd-skill` prefix, which produces a
      false pass or fail against the wrong prefix instead of an error.
      
      **No helper runtime available (`instructions-only` profile).** The
      linter cannot run without Node.js and the vendored `scripts/`
      directory, and an `instructions-only` install is a first-class
      supported fallback, not a degraded one. Unavailability is never a
      waiver: manually re-verify the same checks listed above against this
      contract's prose and the [Draft schemas](#required-draft-content)
      before publishing.
      
      A `passed: false` report (or non-zero exit, or a failed manual
      re-verification) means the draft is not ready to publish yet,
      regardless of how complete the narrative reads — fix every reported
      finding and re-run before treating the issue as `ready`. The linter (or
      its manual equivalent) is a mechanical structural check, not a
      substitute for the judgment-based checks above (human-dependency
      isolation, codebase fidelity, reuse-first) — passing it is necessary,
      not sufficient, for `ready`.
      
      ## Autopilot-suitability score
      
      > **Status.** Active contract. Authoring **emits** the score footer
      > and Discover **ranks and routes** candidates by it (roadmap #759,
      > fully merged). The score stays advisory: it never bypasses the
      > A4.5/A5 gates and is fail-safe on absence.
      
      Authored issues carry a persisted **autopilot-suitability score**
      from 1 to 5 (higher = more autopilot-suitable). It is the durable,
      graded form of the **Autonomous completion** execution axis: the
      author makes the judgment once, while context is fresh, so the
      Discover phase can rank and route candidates by a cheap read
      instead of re-deriving autonomy per candidate.
      
      | Score | Meaning                     | Typical signals                                                                                                          |
      | ----- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
      | 5     | Autopilot-ideal             | Fully specified; deterministic verification (tests/lint/CI/mechanical); no external systems; no human judgment; isolated |
      | 4     | Strongly autopilot-suitable | Well-specified and verifiable; minor ambiguity resolvable from repo context; no external/human dependency                |
      | 3     | Borderline / mixed          | Autopilot can likely finish but with notable judgment, weaker verification, or review-attention risk                     |
      | 2     | Mostly human                | Agent may draft a partial result; completion needs human judgment, an asset, or review the agent cannot supply           |
      | 1     | Human-only                  | Interactive credentials, real deployment, subjective/design/product judgment, or external coordination                   |
      
      Scores below the configured discovery floor
      (`autopilotSuitability.floor`, default `3`) designate
      **human-oriented issues**: in autopilot runs Discover routes them
      to humans rather than autopilot.
      
      The score is recorded as a **footer at the end of the issue
      body** — a visible line paired with a hidden, prefix-aware
      machine marker, mirroring the `claimed-by` convention (visible
      note + HTML marker):
      
      ```text
      ---
      
      _Autopilot suitability: N / 5 -- higher is more autopilot-suitable;
      below the configured floor is human-oriented._
      
      <!-- {marker-prefix}-autopilot-suitability: N -->
      ```
      
      Binding rules:
      
      - **Authoritative value = the HTML marker**, read prefix-aware via
        `createMarkerRegex(markerPrefix, "autopilot-suitability")` exactly
        as `roadmap-id` / `blocked-by` are. `N` is an integer 1-5. The
        visible line is a human-readable mirror authoring keeps in sync;
        discovery parses only the marker.
      - **Authoring marker, not operational marker.** This is body
        content like `roadmap-id`; it must never be added to
        `OPERATIONAL_MARKERS` in `scripts/protocol-helpers.mjs` or
        subjected to F4 minimization.
      - **One source of truth.** A score of `1` must agree with the configured
        `blocked-by-human` label (default `status:blocked-by-human`); never
        publish a contradiction.
      - **Advisory, never a gate.** The score only ranks/routes
        candidates. The A4.5 suitability gate and A5 claim safety checks
        still run unchanged on whatever issue is selected; a high score
        never bypasses a gate.
      - **Fail-safe on absence.** A missing, non-integer, or
        out-of-range marker means "no score": Discover evaluates the
        issue the normal way and never skips it. Pre-existing issues
        with no score keep flowing.
      
      Backfill is opportunistic: when an existing open issue without a
      score footer is next edited by the authoring flow, add one. No
      bulk backfill of the existing backlog is required. The claim-state
      precondition still applies — never add the footer to the body of an
      actively-claimed or open-PR issue; defer it to a follow-up instead.
      
      ## Effort hint
      
      Authored issues may also carry an **effort hint** — an author-time
      `S | M | L` size estimate, recorded once while context is fresh, that
      Discover consumes as a **soft selection tie-breaker** so autopilot tends
      to clear small issues first and leave large ones for a fresh session.
      Effort is distinct from the autopilot-suitability score: suitability
      captures _autonomy_ (can an agent finish unattended), while effort
      captures _size_ (a fully-autonomous issue can still be large).
      
      | Hint         | Scope                                                                                             | Uncertainty                                                                                        | Example signals                                                                                     |
      | ------------ | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
      | **S** Small  | Touches one module or a small, contained file set                                                 | Little to no open design decision remains once the plan is drafted                                 | One module / a few files; a single reviewable change; little or no review back-and-forth expected   |
      | **M** Medium | Touches a helper plus its callers, or one instr
    • draft-patterns.md 23.8 KB
      # Draft Patterns
      
      Load this file after reading
      [`contract.md`](contract.md) when you need concrete examples or a quick
      chooser for output shapes.
      
      ## Example triggers
      
      - "Break this request into IDD-ready issues before we implement
        anything."
      - "Draft a roadmap for this feature and split the ready work."
      - "Turn this broad request into reviewable orphan issues."
      - "Check whether an existing issue should be extended instead of opening
        a new one."
      
      ## Output chooser
      
      Draft an orphan issue only when one autonomous task can finish the work
      and the target repository discovers orphans (`issue-scope:
      roadmap-first`, the default, via the orphan fallback, or
      `orphan-first`). If the repository uses `orphan-first-policy:
      maintainer-approved`, include a post-publication approval step after the
      final issue content is stable. If the repository sets `issue-scope:
      roadmap` (roadmap-only) or a public repository uses
      `orphan-first-policy: public-disabled`, draft a roadmap package instead.
      
      If the repository keeps the broader secure-by-default issue-author
      approval gate, use the same post-publication approval note whenever the
      issue author will not be self-authorizing under the repository's
      `maintainer-approval-actors` policy. The configured ready label from
      `approvalSignals.readyLabelName` (default: `idd:ready`) is accepted
      according to `approvalSignals.labelFreshnessMode` (`presence-only` by
      default, optional `event-freshness`), while standalone `IDD ready`
      comments from a maintainer approval actor must stay fresh against the
      latest issue content and generated-plan update (or an equivalent
      draft-stability signal). Until that approval condition is
      satisfied, later discovery should treat the issue as part of the
      approval-needed fallback bucket instead of the normal ready-to-start
      set.
      
      Draft a roadmap plus sub-issues when the request needs visible
      sequencing, parallel tracks, or multi-session handoff.
      
      Draft only stable non-ready buckets when the work still depends on a
      human decision, missing asset, or unclear verification.
      
      ## Under-clarification stop rule
      
      Before drafting a `ready` issue, confirm you can name a concrete surface
      to edit and an objective verification for it. If, after bounded
      clarification, you still cannot, route the candidate to `needs-decision`
      or ask — do not publish a confidently-vague `ready` issue. Reliability
      over speed.
      
      This is an Intake-phase gate on your own confidence, not a wording
      judgment on an already-written draft — it is distinct from the
      "Under-specified" band in the next section, which assesses a body that
      has already been drafted.
      
      **Example**: "Improve the error handling in the API layer" fails this
      check — no concrete surface, no objective verification — even before
      you consider how detailed to write the body. Ask which endpoint or
      module, and what the observable failure mode is, or route the request
      to `needs-decision` instead of guessing at a plausible-sounding scope.
      
      ## Specificity target
      
      Execution-ready issue drafts should land in a middle band:
      
      - **Under-specified**: a high-range model still has to infer the real
        implementation shape because the issue names only a vague goal,
        omits the likely surface to edit, or leaves verification too loose.
      - **Target range**: a solid mid-tier cloud model can hold a stable plan
        without extra clarification. The issue points at the relevant
        document, schema, or code surface, explains the constraint, and keeps
        acceptance criteria verifiable without dictating every edit.
      - **Over-specified**: even a lightweight model could follow the issue as
        a script because the body prescribes exact edit order, wording, or
        implementation steps that reviewers do not need.
      
      If a draft feels like it needs a high-range model just to guess the intended
      change, it is still too vague. If it reads like line-by-line assembly
      instructions, it is too detailed.
      
      ## Specificity checklist before publishing
      
      Before you publish a ready issue, confirm:
      
      - the title and background name the concrete artifact or surface that
        should change
      - a mid-tier cloud model could choose a stable implementation direction
        without hidden repository archaeology or a follow-up clarification loop
      - the acceptance criteria verify the outcome, not a step-by-step
        implementation recipe
      - candidate files, examples, and notes act as cues rather than an
        exhaustive script
      - removing one concrete detail would make the issue feel high-range-only,
        while adding more detail would start turning it into a lightweight
        model script
      
      ## Mechanical pre-publish gate
      
      Before you publish a drafted **ready orphan, roadmap, or child** body,
      run the `audit-authored-issue` linter against it when a helper runtime
      is available. It mechanically catches shape and marker mistakes — a
      missing or duplicated autopilot-suitability footer, a wrong
      markerPrefix, a missing required heading for the declared shape, a
      malformed dependency marker — that a confident narrative can otherwise
      mask:
      
      ```sh
      node scripts/audit-authored-issue.mjs --shape orphan \
        --marker-prefix <resolved-target-prefix> --body-file draft.md
      ```
      
      Before newly publishing a body into the `needs-decision` or
      `blocked-by-human` bucket instead, also run it, adding
      `--expect-bucket <needs-decision|blocked-by-human>` (choose the one
      matching value) — without it, the marker/label checks that key off
      `authoring-bucket` never fire, since a non-ready body is otherwise
      never run through this gate at all. Passing `--expect-bucket` also
      skips the ready-shape-only checks (the suitability footer and required
      headings) that a bucket body like `#431` below is never expected to
      carry:
      
      ```sh
      node scripts/audit-authored-issue.mjs --shape orphan \
        --marker-prefix <resolved-target-prefix> --body-file draft.md \
        --expect-bucket needs-decision \
        --label status:needs-decision
      ```
      
      **Always pass `--marker-prefix`** with the prefix resolved under
      [contract.md's Target marker prefix](contract.md#target-marker-prefix):
      without it, the linter falls back to reading
      `.github/idd/config.json` from the current working directory, and
      silently defaults to this source repository's own `idd-skill` prefix
      when that file is missing or unreadable — producing a false pass or
      fail against the wrong prefix instead of an error.
      
      Use `--shape roadmap` or `--shape child` for those shapes, `--stdin`
      instead of `--body-file` when the draft is not yet on disk, and
      `--label <name>` (repeatable) to pass proposed labels for the check
      that a suitability score of `1` carries the configured
      `blocked-by-human` label (default `status:blocked-by-human`), unless an
      `authoring-bucket: needs-decision` marker substitutes the configured
      needs-decision label instead (see
      [Authoring-bucket marker](contract.md#authoring-bucket-marker));
      use `--config <path>` to point at a policy that overrides the label
      name — this check is also one-directional, it does not flag the
      reverse, a non-`1` score paired with the label. Fix every reported
      finding and re-run before publishing; a `passed: false` report means
      the draft is not ready yet, regardless of how complete the narrative
      reads.
      
      **No helper runtime available (`instructions-only` profile):** the
      linter cannot run. `instructions-only` is a first-class supported
      fallback, not a waiver — manually re-verify the same checks against
      [contract.md's Mechanical pre-publish gate](contract.md#mechanical-pre-publish-gate)
      before publishing instead.
      
      ## Hidden human-dependency quick check
      
      Before you publish a `ready` issue, confirm:
      
      - the implementation does not still depend on unresolved credentials,
        access, or unavailable infrastructure
      - unresolved product, policy, or design choices have been routed to
        `needs-decision` instead of being buried in implementation steps
      - acceptance criteria use objective verification, while optional
        post-implementation review stays optional
      - roadmap narrative does not hide human-dependent work that belongs in a
        stable bucket or approval-needed hold
      - dependency markers represent true start blockers rather than grouping
        related work
      
      ## Codebase-fidelity quick check
      
      Before you publish a `ready` issue, confirm:
      
      - when the issue reuses an existing identifier or field name, the
        specified value matches that name's established semantics in the
        codebase — it does not overload a name with a new shape or source;
        remedy: mint a new, distinctly named field instead (see
        [contract.md's worked example](contract.md#codebase-fidelity-validation))
      - values that are mutable at runtime are flagged to specify a live read
        at the point of use rather than a one-time capture at construction
      
      ## Example orphan issue
      
      - `## Background` or `## Goal`
      - `## Proposed change`
      - `## Acceptance criteria`
      - optional `## Candidate files` — see
        [contract.md's Candidate files format](contract.md#candidate-files-format)
        for the exact parse contract before populating it
      - an autopilot-suitability footer at the end of the body (visible
        line + `<!-- <marker-prefix>-autopilot-suitability: N -->` marker)
      
      Use this shape when the work is narrow enough to pass the IDD viability
      gate on its own and the target repository can actually discover orphan
      issues (`issue-scope: roadmap-first`, the default, via the orphan
      fallback, or `orphan-first`). If the repository sets
      `issue-scope: roadmap` (roadmap-only), prefer a one-item roadmap package
      instead of publishing a standalone orphan issue.
      
      ## Example roadmap package
      
      Roadmap issue:
      
      - `## Goal`
      - `## Background` or `## Why this matters`
      - `## Tracks`
      - `## Success criteria`
      - one `<!-- <marker-prefix>-roadmap-id: ... -->` marker
      - an autopilot-suitability footer at the end of the body
      
      Child issue:
      
      - title with a concrete task summary
      - `## Background`
      - `## Proposed change`
      - `## Acceptance criteria`
      - `## Candidate files`
      - optional dependency line or sequential roadmap marker when needed
      - an autopilot-suitability footer at the end of the body
      
      Keep ready child issues in the roadmap task list rather than grouping
      them with hidden dependency markers.
      
      ## Nested roadmap chooser note
      
      Use a nested roadmap when one roadmap track needs its own coordination
      boundary, active child list, or multi-session handoff. Keep the parent
      roadmap pointing to the nested roadmap, and keep the nested roadmap
      pointing to the leaf execution issues it coordinates.
      
      Parent roadmap `## Tracks` excerpt:
      
      ```md
      - [ ] #510 — backend track roadmap
      ```
      
      Nested roadmap `#510` `## Tracks` excerpt:
      
      ```md
      - [ ] #511 — define the backend contract
      - [ ] #512 — wire the contract into Discover
      ```
      
      Treat `#510` as a coordination/audit node, not as a normal execution
      issue. Do not replace that relationship with `Blocked by #NNN` or
      `<!-- <marker-prefix>-blocked-by: ... -->` only to group the leaf
      issues under the parent roadmap.
      
      ## Dependency minimization examples
      
      ### Natural parallel decomposition
      
      Roadmap `## Tracks` excerpt:
      
      ```md
      - [ ] #401 — update the issue-authoring contract
      - [ ] #402 — add draft-pattern examples
      
      _Parallel note: #401 and #402 can proceed independently once the roadmap
      exists because neither task depends on the other's output._
      ```
      
      This is the preferred shape for sibling tasks that can be reviewed and
      verified independently. The roadmap keeps both tasks visible in its task
      list, and the short note explains the safe parallelism without adding a
      fake `Blocked by` edge.
      
      **Caveat — shared CI check definitions.** File-disjoint tracks are not
      automatically execution-order-independent: if one track edits a shared
      CI check's own workflow _definition_ (e.g. a `.yml` file), any other
      in-flight track whose CI run relies on that check inherits a hidden
      ordering dependency, even though the tracks' own edited files never
      overlap. `gh run rerun` re-resolves against the PR branch's own copy
      of the workflow file, so a fix merged to `main` on a sibling track
      stays invisible until the dependent branch pulls it in (see
      `.github/instructions/idd-ci.instructions.md`'s Rerun mechanics). Note
      this dependency in
      the roadmap's parallel note rather than assuming disjoint files always
      mean safe parallelism.
      
      ### Artificial decomposition
      
      Bad serial chain:
      
      ```md
      #401 — update the issue-authoring contract
      #402 — add draft-pattern examples
      
      Blocked by #401
      ```
      
      This is over-serialized when `#402` can be reviewed and verified without
      waiting for `#401`. Do not create a serial chain just to make the order
      feel tidy.
      
      Bad split for parallelism:
      
      ```md
      #410 — add one checklist bullet
      #411 — add one example paragraph
      #412 — add one anti-pattern sentence
      ```
      
      This is an artificial split when the three edits form one natural,
      cohesive authoring change. Do not break a single reviewable task into
      multiple sibling issues only to widen parallel execution.
      
      ### Finalize or verify track that asserts sibling-produced state
      
      Anti-pattern — prose sequencing only:
      
      ```md
      #450 — finalize the config, reconcile the docs, verify the combined result
      
      Blocked by #440
      
      _Runs after the wiring tracks #441-#445._
      ```
      
      The hard `Blocked by #440` names only the build foundation, and the
      after-the-siblings ordering lives in prose. Once `#440` closes, Discover
      reports `#450` startable and A4.5 passes it (Actionability inspects the body,
      not completability) — but its acceptance criteria assert state that only the
      unmerged `#441`–`#445` produce, so claiming it means failing acceptance or
      doing the siblings' work.
      
      Correct — encode `Blocked by` on each sibling whose output the acceptance
      criteria depend on:
      
      ```md
      #450 — finalize the config, reconcile the docs, verify the combined result
      
      Blocked by #440
      Blocked by #441
      Blocked by #442
      Blocked by #443
      Blocked by #444
      Blocked by #445
      ```
      
      Now Discover and A4.5 defer `#450` until every sibling merges, so it is
      claimed only when its acceptance criteria can actually pass.
      
      **Prefix-first**: resolve `<marker-prefix>` from the target repository's
      onboarding or IDD docs before emitting any of these markers —
      `roadmap-id`, `blocked-by`, `autopilot-suitability`, or `effort` — not
      just the dependency markers shown above. Never default to `idd-skill`
      in an installed bundle; use it only when the target repository actually
      configured that prefix.
      
      ## Human-dependency isolation examples
      
      The examples below show how to move unavoidable human side effects to
      explicit boundaries rather than hiding them inside a ready execution
      issue. See [`contract.md`](contract.md) for the routing rules
      (`needs-decision`, `blocked-by-human`, `deferred`, approval-needed).
      
      ### Front-loaded pattern
      
      Use this when coding cannot start safely until a person provides a
      decision, credential, permission, or external setup.
      
      **Bad (mixed)**: One execution issue that mixes implementation with an
      unresolved credential gap:
      
      ```md
      ## Background
      
      Add Stripe webhook support.
      
      ## Proposed change
      
      Implement the `/api/webhooks/stripe` endpoint.
      
      ## Acceptance criteria
      
      - Stripe webhook secret is configured in production.
      - Endpoint returns 200 for valid events.
      ```
      
      This fails the IDD viability gate: the "Stripe webhook secret is
      configured in production" criterion requires a person to perform an
      action in an external system before the issue can be verified. The agent
      cannot autonomously confirm the outcome.
      
      **Good (front-loaded)**: Separate the human-dependent setup into its own
      issue, then write the autonomous implementation issue that depends on it.
      The `## Tracks` task list should contain only ready execution issues;
      route the non-ready blocker to a separate section or a stable non-ready
      bucket.
      
      Roadmap body excerpt:
      
      ```md
      ## Non-ready prerequisites
      
      - **[blocked-by-human]** #431 — obtain Stripe webhook secret for CI
        _(must close before #432 can start)_
      
      ## Tracks
      
      - [ ] #432 — implement /api/webhooks/stripe endpoint
      ```
      
      `#431` — `blocked-by-human` issue:
      
      ```md
      ## Background
      
      The Stripe webhook endpoint (tracked in #432) needs a test-mode webhook
      secret in CI so automated tests can verify the signature check.
      
      ## Required action
      
      1. Create a test-mode Stripe webhook in the Stripe dashboard.
      2. Store the signing secret in the `STRIPE_WEBHOOK_SECRET` repository
         secret.
      3. Reply on this issue with the secret name once added.
      
      ## Ready signal
      
      Close this issue after confirming the secret is available in CI.
      
      <!-- {marker-prefix}-authoring-bucket: blocked-by-human -->
      ```
      
      `#432` — autonomous execution issue (Blocked by #431):
      
      ```md
      ## Background
      
      Parent roadmap: #430
      Blocked by #431
      
      ## Proposed change
      
      Add POST /api/webhooks/stripe that validates the Stripe-Signature header
      and dispatches known event types.
      
      ## Acceptance criteria
      
      - Handler validates the webhook secret sourced from CI `STRIPE_WEBHOOK_SECRET`.
      - Tests use the Stripe test-mode fixture and pass without manual setup.
      - `pnpm test` and `pnpm run lint` pass in CI.
      
      ## Candidate files
      
      - `src/routes/webhooks/stripe.ts`
      ```
      
      The autonomous issue is fully verifiable in CI once the credential
      exists. It does not mention a person setting up anything inside its
      acceptance criteria.
      
      ### Back-loaded pattern
      
      Use this when post-implementation work is subjective review, publication
      choice, optional polish, or a sign-off that should not block an
      otherwise verifiable core change.
      
      **Good (back-loaded)**: Separate the implementation from the optional
      human-gated step:
      
      Roadmap body excerpt (the `## Tracks` list contains only the ready
      execution issue; the deferred step is a narrative note, not a task-list
      entry):
      
      ```md
      ## Tracks
      
      - [ ] #441 — add front-loaded/back-loaded draft-pattern examples
      
      ## Deferred
      
      The website landing page could be updated to showcase the new examples,
      but that publication decision requires maintainer approval and is not a
      blocker for merging #441. Track in a follow-up if approved.
      ```
      
      `#441` — autonomous execution issue:
      
      ```md
      ## Background
      
      Parent roadmap: #440
      
      The draft-patterns reference file does not yet show front-loaded or
      back-loaded human-dependency isolation patterns.
      
      ## Proposed change
      
      Add a "Human-dependency isolation examples" section to
      `skills/issue-authoring/references/draft-patterns.md`.
      
      ## Acceptance criteria
      
      - The section includes at least one front-loaded and one back-loaded
        example using stable bucket names (needs-decision, blocked-by-human,
        deferred, out-of-scope).
      - Examples warn against hiding credentials or product decisions in a
        ready issue.
      - `pnpm run lint:minimum` passes.
      
      ## Candidate files
      
      - `skills/issue-authoring/references/draft-patterns.md`
      ```
      
      The website publication decision stays separate. It is not in the
      acceptance criteria of the ready issue and does not block autonomous
      verification.
      
      ### Warning: hidden human dependencies are the most common IDD stall
      
      The most frequent reason for mid-implementation stalls is an execution
      issue that hides a human-only dependency inside its acceptance criteria
      or implementation steps:
      
      - "Credentials are configured in the production environment" → blocked
        by a person with access.
      - "The design team has approved the final UI spec" → requires subjective
        sign-off before the issue is verifiable.
      - "The external API key is available in the repository secrets" → an
        unavailable system or permission.
      
      When any acceptance criterion cannot be confirmed autonomously through
      tests, lint, CI, or other concrete objective criteria (such as checking
      repository state, file presence, or configuration values), the issue is
      not yet ready. Move that criterion to a `blocked-by-human` or
      `needs-decision` issue and keep the autonomous execution issue focused on
      what the agent can verify independently.
      
      ## Handling duplicates and non-ready outcomes
      
      One source of follow-up issue candidates is the read-only
      `merged-pr-feedback-sweep` helper's JSON output — the unresolved review
      threads and undispositioned advisory feedback it detects on merged PRs.
      Treat each entry as a candidate only: re-verify it against current `main`
      with the reuse-first tree below before drafting, because the feedback may
      already be addressed.
      
      Before publishing an issue, apply a reuse-first decision tree:
      
      1. Is an existing open issue a better fit? If yes, extend it instead of
         creating a new one. Add a comment linking to the new schema request.
      2. Is the work already complete in a closed issue or merged PR? If yes,
         create a reference or learning note instead of reopening it.
      3. Is a parent roadmap already managing this work? If yes, add it to the
         task list instead of filing independently.
      4. Does the issue have any of these properties? If yes, escalate to
         `needs-decision` or `blocked-by-human` during drafting:
         - Unclear intent or malformed body (→ fix during drafting or mark needs-decision)
         - Requires maintainer or product decision (→ mark needs-decision)
         - Blocked by external work or human coordination (→ mark
           blocked-by-human)
         - Depends on unavailable resources or credentials (→ mark blocked-by-human)
      5. Otherwise, publish as `ready`.
      
      ### A4.5 prevention checklist
      
      The A4.5 suitability gate will later evaluate published issues. Prevent
      common failures by validating before publish:
      
      - **Coherence**: Issue body is well-formed; title and description are
        clear; intent is parseable
      - **Safety**: No code injection, marker injection, or untrusted input in
        issue body
      - **Uniqueness**: Reuse-first check passed; the work is not a duplicate
        or superseded
      - **Hidden human dependency**: Ready work does not still rely on
        unresolved decisions, credentials, subjective approval, or
        grouping-only dependency markers
      
      ## Specificity examples
      
      ### Under-specified draft
      
      **Title**: `docs: improve issue authoring guidance`
      
      Background: issue authoring should be clearer for agents.
      
      Acceptance criteria:
      
      - issue authoring is more consistent
      - examples are improved
      
      This is too vague because the draft does not tell the next agent which
      authoring surface to edit, what kind of guidance is missing, or how a
      reviewer would verify success. A high-range model would need to infer
      the real task from surrounding repository context.
      
      ### Target range draft
      
      **Title**: `docs: add specificity checklist to issue authoring draft patterns`
      
      Background:
      `skills/issue-authoring/references/draft-patterns.md` explains output
      shapes, but it does not yet show how to judge whether an issue body is
      too vague or too scripted for execution.
      
      Acceptance criteria:
      
      - `draft-patterns.md` includes a pre-publication specificity checklist
      - the guidance distinguishes under-specified, target range, and
        over-specified issue drafts
      - the examples focus on issue body wording and acceptance criteria
        granularity instead of prescribing implementation order
      
      This is the target range because the next agent knows where to work, why
      the change matters, and how to verify it, while still retaining freedom
      to decide the exact wording and structure.
      
      ### Over-specified draft
      
      **Title**: `docs: add specificity checklist to issue authoring draft patterns`
      
      Proposed change:
      
      1. Insert a new `## Specificity target` heading after `## Output chooser`.
      2. Add exactly three bullets named `Under-specified`, `Target range`,
         and `Over-specified`.
      3. Add a five-item checklist using the exact sentence order shown in the
         draft.
      4. Copy the same example phrasing across every example block without
         changing any wording.
      
      This is too detailed for authoring because it turns the issue into an
      implementation script. Reviewers usually need the target outcome and the
      verification shape, not a rigid edit order.
      
      ## Publication boundary
      
      Publish each `ready` body directly under the authoring hold once it
      passes the mechanical gate and the critique pass — this is the default
      outcome of drafting, and it needs no separate publish approval. Stop
      after publishing (and applying/creating the authoring label) unless
      the user also separately requests release from the authoring hold —
      release is what authorizes starting the IDD execution loop, so a
      request phrased as "start the IDD execution loop" counts as that same
      release request, not a separate path around it.
      
      If the user asked for drafts only (a preview before anything is
      created), honor that instead: stop after reporting the issue set,
      assumptions, and non-ready buckets, without publishing.
      
    • workflow-boundary.md 32.4 KB
      # Workflow Boundary
      
      This bundle handles issue authoring end to end under the authoring
      hold: drafting and publishing are one continuous stage with no
      per-step approval, and release from the authoring hold is the single
      approval boundary that hands off to IDD execution.
      
      ## Two-stage contract
      
      ### Stage 1: Author-and-publish (under the hold)
      
      - Skill drafts issues in the target repository. Each candidate moves
        through the readiness buckets: `deferred` → `ready` or an escalation
        bucket (`needs-decision`, `blocked-by-human`, `out-of-scope`)
      - Before publishing a `ready` body, bundled skill runs the mechanical
        `audit-authored-issue` gate and the critique pass (both unchanged
        and still mandatory)
      - Bundled skill then publishes directly under the configured authoring
        label (`issueAuthoring.authoringLabelName`, defaulting to
        `status:authoring`) — **no prior user approval of the drafted body
        is required**. If the current request asked only for a preview
        (drafts to look at before anything is created), bundled skill stops
        after reporting the proposed set instead of publishing; publishing
        is otherwise the default outcome of drafting, not an opt-in step
      - If the label does not exist in the target repository, bundled skill
        creates it with `gh label create` before first use; label creation or
        application failure blocks publishing
      - For existing issues, bundled skill applies the authoring label before
        updating issue content
      - For new issues, bundled skill requires a capability-checked publication
        command that creates the issue with the authoring label atomically and
        carries an exact hidden publication token for target, anchor, set, and
        session. If the target runtime cannot provide that operation, stop before
        creating the issue. Never intentionally create an unlabeled issue for the
        Stage 1 set
      - The publication token uses this exact HTML-first format. Generate the
        opaque `target` id and token for both markers below -- the new
        issue's own number is not yet known. `anchor` in **both** markers
        depends on the new issue's role in the set: when this new issue is
        itself the set anchor, `anchor` reuses that same opaque `target`
        value (self-reference) -- the `<opaque-anchor-id>` placeholder below
        depicts this self-anchor case only. For a **non-anchor child**,
        `anchor` is instead the set anchor's already-resolved real
        `<owner>/<repo>#<number>` reference, not an opaque id, since the
        anchor already exists with a known number by the time a child is
        created (see the bundle's canonical contract,
        `references/contract.md`'s "New-issue ownership" section, for the
        full rule):
      
        ```html
        <!-- <marker-prefix>-authoring-publication: target=<opaque-target-id>; anchor=<opaque-anchor-id>; set=<opaque-set-id>; session=<opaque-session-id>; token=<opaque-publication-token> -->
        ```
      
        The originating Stage 1 hold uses this append-only publication-intent
        record, whose `anchor` field follows the same self-anchor/non-anchor-child
        rule above:
      
        ```html
        <!-- <marker-prefix>-authoring-publication-intent: target=<opaque-target-id>; anchor=<opaque-anchor-id>; set=<opaque-set-id>; session=<opaque-session-id>; token=<opaque-publication-token>; journal=<owner>/<repo>#<number>; issue=<owner>/<repo>#<number>|none; actor=<trusted-marker-actor>; state=<pending|member|cleanup|abandoned> -->
        ```
      
        Append `state=pending; issue=none` before creation, append the returned issue
        identity while it remains `pending`, append `member` only after owner-marker
        verification, and append `cleanup` before any safe-close mutation. Append
        `abandoned` only after closed/label-absent verification. The append-only
        replay selects the latest valid record for the exact token tuple; missing,
        conflicting, or out-of-order records fail closed, while `pending` and
        `cleanup` remain recovery holds.
      
        `journal` is the durable record location. For an existing set, use the
        verified originating Stage 1 hold; for a standalone set with no existing
        issue or anchor, use the repository-level authoring journal target
        configured at `issueAuthoring.journalIssue` in `.github/idd/config.json`
        (an `owner/repo#number` reference to a pre-existing, durable, comment-only
        issue) -- an unset `issueAuthoring.journalIssue` only blocks a standalone
        set; an existing set with a verified Stage 1 hold needs no journal
        configuration at all. Do not create that journal as part of the same set.
        If the applicable location cannot be resolved -- no verified Stage 1 hold
        for an existing set, or `issueAuthoring.journalIssue` unset or
        unverifiable for a standalone set -- stop with `blocked-by-human` before
        creating any target. On every paginated replay, require `actor` to equal
        the API author and verify that
        actor is a trusted marker login with the required write-level permission or
        configured bot/app trust. An untrusted, malformed, or conflicting
        exact-token record is not valid evidence; fail closed and retain the hold.
      
        Generate the opaque `target` id and publication token before creation
        because the new issue's own number is not yet known, and generate
        `anchor` the same way only when this new issue is the set anchor
        itself -- otherwise reuse the anchor's already-resolved real
        reference, per the self-anchor/non-anchor-child rule above. Persist
        those preallocated IDs, the exact token, and `state=pending` in
        that journal before issuing the create. After a successful create, attach and
        verify the returned issue identities before appending the owner marker; an
        unverifiable pre-create write blocks creation, while an unverifiable
        post-create attachment leaves the issue held for recovery. Only verified
        owner-marker acquisition changes it to `member`, and only verified safe close
        changes it to `abandoned`
      - Immediately after a new issue is created and labeled, bundled skill
        appends its `mode=acquire` owner marker with the current set ID, then
        re-fetches labels, body, and owner comments before treating it as a set
        member
      - If an allegedly atomic create unexpectedly returns an unlabeled issue,
        re-fetch its labels, body, current `claimed-by` state, and paginated
        owner-marker log before closing. If a trusted claim or owner marker from
        another session or set is present, do not close or overwrite the exposed
        issue; report the ownership conflict and stop. If no competing claim is
        present, apply and verify the authoring label as a safe hold, then re-fetch
        the claim and owner logs again before closing. If that hold or final
        re-read cannot be verified, leave the issue open and report the recovery
        hold. Deletion needs admin permission the authoring agent
        typically lacks (and `docs/permissions.md` forbids for normal IDD), so it
        is not the default recovery path
      - If owner-marker append or verification is uncertain for a new issue,
        reconcile the returned comment ID and the paginated owner-marker log with
        bounded retries before closing. If a trusted marker is found, retain the
        label and recover or reopen the issue as a set member. Otherwise re-fetch
        labels, body, current `claimed-by` state, and the paginated owner-marker log;
        if that final read proves no competing claim or owner marker, append
        `state=cleanup` before closing the issue or removing its authoring label.
        Re-fetch and verify closed/label-absent state, then append
        `state=abandoned`. If any disposition or cleanup read is uncertain, retain
        `state=cleanup`, leave the issue held, and report the recovery hold.
      - An atomically labeled publication is not set membership until its owner
        marker is verified. Persist each returned target identity in the durable
        originating Stage 1 hold before appending the marker. On resume, reconcile
        recorded identities and only issues carrying this set's exact publication
        token; an incomplete scan or unmarked match is a recovery hold, so never
        infer membership or completion from the shared label alone. If the final
        safe-close read proves no competing claim or marker, append `state=cleanup`
        before closing the issue or removing its authoring label. Re-fetch and verify
        closed/label-absent state, then append `state=abandoned`; otherwise leave the
        identity and label held for recovery.
      - **Per-target ownership is separate from the hold label.** The configured
        authoring label is a shared claim-suppression lock, not a session lock. Before
        editing an existing issue or roadmap, the skill must fetch a fresh target
        snapshot and resolve its complete claim state, including trusted forced-handoff
        successors and activation-nonce winners, plus its active `claimed-by` and
        open-PR state. A trusted forced-handoff successor is active even without a new
        `claimed-by`; any active execution is a conflict, so do not establish the
        hold. Apply the label if it is absent, then append a hidden owner comment
        using the resolved marker prefix:
      
        ```html
        <!-- <marker-prefix>-authoring-owner: target=<owner>/<repo>#<number>; anchor=<owner>/<repo>#<number>; mode=acquire|resume|bootstrap|heartbeat|release|release-guard|release-complete; owner=<opaque-owner-token>; set=<opaque-set-id>; session=<opaque-session-id>; body-sha256=<64-lowercase-hex|none>; snapshot-sha256=<64-lowercase-hex|none>; supersedes=<opaque-owner-token|none> -->
        ```
      
        _Issue-authoring ownership marker. Do not edit or delete._
      
        Use the same `body-sha256` and `snapshot-sha256` semantics as the portable
        owner protocol: target markers persist the exact fresh body digest, and the
        anchor-only `release-complete` marker carries the recomputed set snapshot.
        For `snapshot-sha256`, compute the SHA-256 digest over the UTF-8 bytes of
        the whole target set's `<owner>/<repo>#<number>:<body-sha256>` lines.
        Normalize each `<owner>` and `<repo>` component with
        `NFC(Unicode-default-lowercase(NFC(component)))`, join them with `/`, and
        serialize each line with that normalized identity. Sort by the identity's
        unsigned UTF-8 byte sequence (shorter equal prefixes first), then issue
        number ascending, and join with a single `\n` and no trailing newline.
        New markers missing these fields are not valid for a new generation; legacy
        markers are migration input only. A legacy marker cannot prove completion
        until its target body and required snapshot are re-fetched and recomputed
        with the canonical algorithm. For this migration check, that algorithm is
        the SHA-256 digest of the UTF-8 bytes of
        `<owner>/<repo>#<number>:<body-sha256>` lines after normalizing each
        owner/repository component with
        `NFC(Unicode-default-lowercase(NFC(component)))`, joining the normalized
        components with `/`, sorting by unsigned UTF-8 identity bytes (shorter
        equal prefixes first) and then issue number ascending, joining with one
        `\n`, and omitting a trailing newline. When the stored snapshot digest
        matches that recomputation, the current verification may accept it.
        Missing, mismatched, or otherwise unverifiable evidence fails closed.
        This legacy-marker behavior is preventive; no observed incident yet.
      
        Append this HTML-first body with a direct JSON `POST` to the issue-comments
        endpoint; do not rely on `gh issue comment` or `gh api -f body=` for the
        owner marker. Verify the returned comment ID and body after posting, then
        re-read the active claim and open-PR state again. If execution began during
        acquisition, stop without editing and leave the verified hold for explicit
        recovery.
      
        Owner tokens are per target: never compare a child target's `owner` value
        literally with the anchor's `owner` value. Every owner-marker log read for a
        target or anchor must use paginated issue-comment retrieval (for example,
        `gh api --paginate` or an API equivalent) and deterministic GitHub comment
        order (`created_at`, then comment ID); never rely on a single API page.
      
        Resolve the set anchor before appending any target marker. `anchor` records
        the canonical owner/repository/issue identity of that anchor; the anchor's
        own marker uses its `target` as the `anchor`, and every other marker in the
        set repeats the same value. A missing or mismatching `anchor` makes a
        marker invalid for set membership, resume, or release. A legacy marker
        without an anchor cannot resume a multi-target set; when no parent roadmap
        identifies the anchor, stop and bootstrap a fresh explicitly designated
        anchor instead of choosing a different lead implicitly.
      
        Only a trusted target-repository marker actor makes a marker valid: the
        current authenticated actor after posting and verifying it **and** passing
        a Write/Maintain/Admin permission check, a configured trusted bot or app,
        or an explicitly enabled Write/Maintain/Admin collaborator. Comment-only
        access is insufficient. If permission cannot be verified and no explicit
        bot/app trust applies, ignore and report the marker; syntax alone never
        grants ownership. For `acquire`, `bootstrap`, and `resume`, `owner` is a
        newly generated opaque per-target owner token; `supersedes=none` for
        `acquire` and `bootstrap`, while `resume` names the prior owner token.
        For any owner marker needed by a later session, the author's trust must also
        be re-evaluable from durable policy: `trustedMarkerActors`, a configured
        trusted bot or app, or an explicitly enabled collaborator whose permission
        can be re-read. The current-session actor path is provisional and cannot
        make a historical marker trusted by itself. Without a durable trust source,
        leave the label and hold in place and report recovery; do not treat the
        marker as set membership or ownership evidence.
        For `release`, retain the current owner token in `owner` and set
        `supersedes` to that same current owner token; `supersedes=none` is invalid
        for a release marker. For `heartbeat`, retain the current owner, set, and
        anchor, set `supersedes` to that same owner token, and do not open or close
        a generation; it only renews the current owner's freshness.
        `release-guard` is valid only on the set anchor. It retains the anchor's
        current owner, set, anchor, and session, and sets `supersedes` to that owner
        token. Append and reconcile it after release-marker preflight but before the
        first label removal. It is the Discover-visible guard for a provisional set
        release and does not close any generation.
        `release-complete` is valid only on the set anchor. It retains the
        anchor's current owner, set, anchor, and session, and sets `supersedes`
        to that owner token. Append and verify it only after every target's
        release marker and label removal has been verified. It is the durable
        terminal event for the set: a later reapplication of the authoring label
        must start a fresh set generation rather than resuming the completed set.
        Within an open generation, the first valid acquisition, bootstrap, or
        resume marker by GitHub comment order wins. A
        `resume` marker opens a new generation only for the exact interrupted set
        and matching prior owner token. A `release` marker must match the current
        owner and set, but remains provisional while its set release is in
        progress; an individual label removal never closes that target's
        generation. During the owning set's own Stage 2 (observed 2026-09-09,
        kurone-kito/idd-skill#2791), the heartbeat renewal and the pre-removal
        ownership recheck must treat that set's provisional `mode=release`
        markers and the anchor's `mode=release-guard` as the expected state
        rather than as a competing generation; the acquisition-time rule that
        a target carrying a release marker cannot be re-acquired until that
        release's `release-complete` is found applies to a later session's
        fresh acquisition of the child, not to the releasing set's own
        rechecks or to a resume of the exact interrupted set, which stays
        the established recovery path when `release-complete` is missing;
        the releasing set's own rechecks never change the current winner,
        unlike a valid resume marker for that exact set, which does. Only
        after a fresh re-read verifies every target's release
        marker and label removal and the anchor's `release-complete` marker does
        the set-level release close all target generations, after which a later
        `acquire` starts a new generation. The
        active generation's freshness is the GitHub `created_at`
        of its latest trusted acquisition, bootstrap, resume, or heartbeat marker;
        a resume marker refreshes that clock, and the label event alone never
        supersedes a fresh owner marker. The current generation's winner owns the
        target; any other
        session must stop without editing and leave the label in place. Do not
        edit or delete owner comments.
      - For a new Stage 1 set, generate one opaque set ID and reuse it in every owner
        marker for that set. When resuming an interrupted set, recover and verify
        its persisted set ID from the exact trusted owner markers and reuse it
        instead of generating a replacement. Persist the resolved anchor identity in
        every marker as well. Before resuming, enumerate the anchor's `## Tracks`
        and a repository-wide paginated issue-comment scan scoped to trusted owner
        markers whose exact `anchor` and `set` match; merge the results by comment
        order and block if enumeration is incomplete. These append-only comments
        are the durable set, anchor, and target membership record; a resume may
        include only targets whose valid markers identify that exact set and anchor.
        Never infer set membership or the anchor from the shared label alone.
      - A non-anchor target cannot prove that its previous set finished from its
        local owner-marker log alone. Before accepting a fresh `mode=acquire` for a
        child whose prior generation has a `mode=release` or `mode=release-guard`
        marker, follow its exact persisted `anchor` identity and fetch that anchor's
        paginated owner-marker log. Require a trusted `mode=release-complete` marker
        for the exact anchor/set/session generation represented by the child's
        current release marker, including the current anchor owner for that release
        generation; never accept an older or newer set's completion. Owner tokens
        are per target, so do not compare the child owner token literally with the
        anchor owner token. If the completion marker is absent, malformed, or cannot
        be fetched conclusively, treat the prior release as interrupted: do not
        acquire the child as a new set, and instead resume that exact set or leave
        its hold in place. A child log, an absent label, or a session-local read is
        never completion evidence. Once the anchor completion is reconciled, the
        old set is closed and a new acquisition may start a new generation.
      - Acquire one set anchor before acquiring any other target: when the set has
        a parent roadmap, first publish a valid roadmap shell under the authoring
        hold, with all required roadmap headings/markers and an empty `## Tracks`
        list allowed only until child issue numbers exist; then acquire and verify
        that roadmap as the set anchor. Only after that anchor is verified may the
        session publish and acquire child targets, and it must wire their real
        numbers into `## Tracks` before release. When no parent roadmap exists, use
        the designated lead target as the anchor. The anchor winner serializes
        acquisition for the whole set; no session may publish or acquire children
        independently. Before each child acquisition or resume, append and verify
        a same-owner heartbeat on the anchor, re-fetch the anchor's paginated log,
        and require its current owner token, set, anchor, and session. Append the
        child marker only after that validation, then immediately re-fetch both
        anchor and child and require the same anchor ownership; if either read
        changes, leave the child hold in place and stop rather than forming a split
        set. If any target cannot be acquired under that anchor, stop all body and
        relationship edits, leave labels and append-only markers in place, and
        require an exact verified resume of that set rather than allowing a split
        ownership set.
        After each `acquire`/`resume`/`bootstrap` marker POST, wait the configured
        `claim.verifySettleDelay`, replay the full paginated log, and choose the
        winner by deterministic comment order; an immediate local read never
        authorizes edits. Apply the same settle delay and full paginated replay after
        every heartbeat before it authorizes an edit or label removal.
      - **Re-read before every edit.** Immediately before each body or roadmap
        relationship update, re-fetch both the target and the set anchor (the same
        fresh snapshot serves both roles when the target is the anchor). Require each
        target's expected owner token independently, plus the same set, anchor, and
        owning session, and require the expected body/label snapshot on the edited
        target to remain unchanged. Also re-read its active `claimed-by` and open-PR
        state; any active claim or open PR is a conflict. An unexpected change,
        competing owner, malformed owner marker, or inability to prove a unique
        owner on either target is a conflict: stop without editing, leave the
        authoring label in place, and record the safe alternative.
      - **Renew before every edit.** After that conflict check and immediately
        before the body or relationship mutation, append and verify a trusted
        `mode=heartbeat` marker for the set anchor first, then re-fetch and verify
        its current owner, set, anchor, and session. Only after the anchor renewal
        succeeds, append and verify the edited target's heartbeat when it is a
        distinct target, then re-fetch both and require each target's expected owner
        token independently, plus the same set, anchor, owning session, and expected
        target snapshot. If either heartbeat cannot be posted or verified, or a
        newer owner appears, stop without editing. A heartbeat never starts a new
        generation and never authorizes release.
      - A target already held by another set is unavailable. A later session may
        resume only when the invocation identifies the exact interrupted set and
        the hold is past `issueAuthoring.authoringStaleAge`; it must append a
        `mode=resume` owner marker with a new owner token and `supersedes` value
        matching the prior owner token before re-running the same acquisition check.
        For a stale held target with no valid owner marker, append a trusted
        `mode=bootstrap` marker with the current set ID, a new owner token, and
        `supersedes=none`; this starts a new generation and is not evidence of any
        prior set membership. The first valid bootstrap marker wins. Staleness
        alone never authorizes takeover: use the latest trusted generation marker's
        GitHub `created_at` for marked targets, and the label event only for
        legacy-unowned bootstrap. A competing active marker still stops the
        session. If the target runtime provides an atomic acquisition helper, use
        it; otherwise this append-only conflict check is mandatory, including for
        `instructions-only` installs.
      - **The held issue IS the draft.** In-place body edits, roadmap
        relationship wiring (publish/acquire the roadmap anchor first, then
        publish/acquire children and wire their real issue numbers), and re-lint of
        already-published bodies all happen on the published issue, under the same
        label — not in a session-local buffer that a later session cannot see
      - **Interrupted-session guard.** If a Stage 1 session stops before the
        set is fully wired and stable, the authoring label stays on every
        issue it already published, and its owner markers stay in place. The
        label suppresses Discover while the markers preserve set identity and
        target membership for a later verified resume; a later session must not
        infer either from the label alone.
      
      ### Stage 2: Release (the single approval boundary)
      
      - The user's explicit hold-release request is the only approval this
        bundle's workflow requires — except the narrow review-fix-loop-cutoff
        auto-release exception in
        [Authoring hold and release](contract.md#authoring-hold-and-release) —
        and it authorizes IDD execution for the released issues
      - Before removing the authoring label, bundled skill runs a release
        checklist that absorbs the rigor of the dropped middle step:
        - every child issue is referenced from its parent roadmap's
          `## Tracks` list
        - no unsubstituted placeholder (a leftover `#TBD`, template
          stand-in, or similar) remains in any published body
        - the `audit-authored-issue` linter (or its manual fallback under
          `instructions-only`) is green on every published body in the set
      - Keep the set anchor held until every other target's label removal is
        verified, and remove the anchor label last. For every target, first
        re-fetch owner comments during release-marker preflight. If a valid
        current-owner/set `mode=release` marker already exists, reuse the earliest
        matching GitHub comment ID; otherwise append one with `supersedes` equal to
        the current owner token, re-fetch to verify it, and record its comment ID.
        Complete that preflight for the whole set before removing any label. A
        retry of an open generation must reuse the recorded or earliest matching
        marker and never append an indistinguishable duplicate. Then, before
        removing any label, append or reuse the anchor-only `mode=release-guard`
        marker and re-fetch the anchor's paginated owner-marker log with bounded
        retries, requiring the exact current owner, set, anchor, session, and marker
        body. If that guard is not found conclusively, leave all labels in place and
        stop. The guard suppresses Discover for the whole set during the provisional
        label-removal window; it does not close the set. When this release is
        proceeding under the narrow review-fix-loop-cutoff auto-release
        exception in
        [Authoring hold and release](contract.md#authoring-hold-and-release)
        instead of an explicit human release request, also verify here --
        immediately before the first label removal below, whether that
        removal is a non-anchor target's or the anchor's own -- that the
        marked target is the sole member of its authoring set: it carries no
        `<marker-prefix>-roadmap-id` marker (never a roadmap anchor), and a
        repository-wide paginated issue-comment scan for trusted owner
        markers whose exact `set` matches finds no sibling target -- the
        same repository-wide, fail-closed enumeration the resume procedure
        above requires, since a sibling's marker lives on the sibling's own
        issue and never appears in the marked target's own comment log;
        block on incomplete or inconclusive enumeration the same way. If
        either condition fails, or the scan cannot be completed, the
        exception does not authorize removing any label for this release;
        fall back to the ordinary explicit human release-request
        precondition for the whole set instead. Then, immediately
        before each label removal, append and verify the set anchor's
        `mode=heartbeat` first, re-fetching it and requiring its current owner, set,
        anchor, and session. Only after that succeeds, append and verify the target
        heartbeat when it is distinct (one marker serves both roles when they
        coincide), then re-fetch both and require each target's expected owner token
        independently, plus the shared set/anchor/session, recorded release-marker
        comment, and expected label/body snapshot. Remove non-anchor labels one
        target at a time and re-fetch each result. After the final anchor label
        removal is verified, re-fetch every target and verify its current release
        marker, absent label, and expected body snapshot; any drift leaves the set
        open and prevents completion. Then reuse the earliest
        valid current-owner/set/session `mode=release-complete` marker on the anchor,
        or append one and record its returned comment ID. Re-fetch that ID and the
        anchor's paginated owner-marker log with bounded retries, requiring the exact
        current owner, set, anchor, session, and marker body. Treat a successful POST
        or a verification timeout as inconclusive until reconciliation finishes: if
        the trusted marker is found, keep the labels absent and close the set; if a
        complete fresh read conclusively proves that no trusted marker was appended,
        reapply the authoring label to every target and leave the set generations
        open; if reads remain inconclusive, keep the release guard and current
        labels/state in place, leave the set held, and record a recovery hold. Never
        infer marker absence or roll back from a verification timeout. Treat every
        release marker,
        heartbeat, label removal, and completion marker as provisional: no target
        generation closes until every target's release marker and label removal are
        verified and the durable completion marker is reconciled, at which point the
        set-level release closes all target generations together. If any later
        removal or verification fails, re-fetch every target already processed,
        retrying a failed post-removal read with a bounded fresh read, restore its
        authoring label while the current owner/set still matches, and verify the
        restored set state; leave every target generation open and stop. If
        restoration cannot be completed or a newer owner has appeared, record a
        set-level recovery hold and never claim a partial release.
      - Bundled skill removes the authoring label from all published issues
        only after the release checklist passes and the user's release
        request is explicit, except the narrow review-fix-loop-cutoff
        auto-release exception in
        [Authoring hold and release](contract.md#authoring-hold-and-release)
      - Release remains a human action; nothing in this bundle auto-releases
        a held issue set, except that same narrow, marker-scoped exception
      - For an ordinary human-gated release, under an orchestrator and
        delegated-worker split, the release action itself must be
        performed by whichever party directly holds the verified user's
        release request, never relayed as a claim for the other party to
        trust —
        mirroring how Discover and Claim already stay the orchestrator's
        own job under `docs/idd-workflow.md`'s Orchestrator fan-out
        variant. A delegated worker that receives only a relayed release
        claim, even from its own orchestrator, must refuse to act on it and
        require the party holding the actual request to release directly.
        This rule does not extend to the narrow review-fix-loop-cutoff
        auto-release exception above, which by design runs with no user
        release request for any party to hold in the first place — see
        [Authoring hold and release](contract.md#authoring-hold-and-release)
        (observed 2026-09-17, kurone-kito/idd-skill#3102)
      
      ## A4.5 Gate Timing
      
      The IDD discover phase evaluates published issues through the A4.5
      pre-claim suitability gate. This gate runs after an issue is published
      but before it is claimed for work.
      
      **Why A4.5 exists**: Issues drafted with incomplete information or from
      assumptions that did not hold when published may fail A4.5 checks
      (incoherent, unsafe, duplicate, etc.). A4.5 catches these before they
      waste agent time during work.
      
      **Prevention during drafting**: This bundle is where coherence, safety,
      and uniqueness should be validated **before** publishing. A4.5 runs
      seven suitability checks; the three that drafting can most directly
      prevent (coherence, safety, uniqueness) correspond to bucket escalation
      triggers during drafting:
      
      - If an issue might be incoherent → escalate to `needs-decision` during
        drafting
      - If an issue might contain untrusted input → escalate to `blocked-by-human`
        or fix during drafting
      - If an issue might be a duplicate → run reuse-first checks during
        drafting before publishing
      
      When these prevent-during-drafting checks are applied correctly, published
      issues will pass A4.5; if they do not, A4.5 will catch them at discover
      time and report the specific failure (unclear, invalid, duplicate).
      
      ## Use this bundle to
      
      - prepare IDD-ready orphan issues when the target repository discovers
        orphans (`issue-scope: roadmap-first`, the default, via the orphan
        fallback, or `orphan-first`), including any required
        `orphan-first-policy` approval handoff
      - prepare roadmap packages and child issues when work needs visible
        sequencing or parallel tracks
      - surface non-ready buckets instead of guessing through blockers
      
      ## Do not use this bundle to
      
      - start the Discover -> Claim -> Work loop implicitly
      - treat bundled references as a replacement for repository execution
        instructions
      - publish a body that has not passed the mechanical
        `audit-authored-issue` gate and the critique pass
      - remove the authoring label from any issue without an explicit
        release request, except the narrow review-fix-loop-cutoff
        auto-release exception in
        [Authoring hold and release](contract.md#authoring-hold-and-release)
      
      ## Handoff to execution
      
      Once the authoring label is removed from every issue in a released
      set — via the user's explicit release request, or, for a single
      marked target only, the narrow review-fix-loop-cutoff auto-release
      exception — execution is authorized: the repository's normal entry
      file and routed `.github/instructions/*.instructions.md` phase files
      (Discover, Claim, Work) may pick up the released issue(s). This bundle
      does not itself start that loop.
      
  • SKILL.md 19.8 KB
    ---
    name: issue-authoring
    description: Draft or refine IDD-ready GitHub issues, roadmap issues, and sub-issues before the normal IDD execution loop begins. Use when a request is too large or ambiguous for one reviewable change, when work needs decomposition or dependency encoding, or when the user asks for issue drafting, roadmap planning, or parallelizable task breakdown.
    ---
    
    # Issue Authoring
    
    Use this skill to prepare issue-ready work before execution starts.
    Keep the skill concise and treat the repository docs as the canonical
    source for the full contract and schema.
    The canonical source bundle lives in this repository; install copies in
    the agent-specific skill directory your runtime reads.
    
    ## Stable Phases
    
    Use two stable phases:
    
    1. **Intake and Clarification** — inspect relevant context, identify
       ambiguity, run a secondary critique or explicit self-critique, and
       ask only the questions that block safe issue drafting. Keep
       clarification bounded; use the repository-local
       `issueAuthoring.maxClarificationRounds` value when available,
       otherwise default to 3 rounds. **Under-clarification stop rule**: if,
       after bounded clarification, you still cannot name the concrete
       surface to edit or an objective verification for a candidate task,
       route it to `needs-decision` or ask — do not publish a
       confidently-vague `ready` issue. Reliability over speed.
    2. **Decompose and Draft** — restate the request in implementation
       terms, split it into atomic tasks, classify readiness, reuse existing
       issues when safe, and draft the smallest issue shape that preserves
       dependencies and reviewability.
    
    Preserve low-readiness work in stable buckets: ready, deferred,
    needs-decision, blocked-by-human, and out-of-scope.
    
    ## Workflow
    
    1. Read the bundled contract in
       [references/contract.md](references/contract.md).
    2. Reuse or extend an existing issue before creating a new one — but
       never edit the body of an actively-claimed or open-PR issue (its
       claimed agent will not pick the change up); cover it with a follow-up
       issue instead. See the contract's claim-state precondition.
    3. Choose the smallest safe output shape:
       - orphan issue for one ready autonomous task only when the target
         repository discovers orphans (`issue-scope: roadmap-first`, the
         default, via the orphan fallback, or `orphan-first`) and any
         configured `orphan-first-policy` approval step can be completed
         after drafting
       - roadmap plus sub-issues for multi-task or multi-session work
       - stable non-ready buckets for deferred, needs-decision,
         blocked-by-human, or out-of-scope work
    4. **Prefix-first**: resolve the target repository's marker prefix
       before emitting any authoring marker — `roadmap-id`, `blocked-by`,
       `autopilot-suitability`, or `effort`. Use the prefix documented by
       the target repository's onboarding or IDD docs, and ask the user
       instead of guessing when the prefix is not discoverable. Never
       default to this source repository's `idd-skill` prefix in an
       installed bundle.
    5. Keep dependencies machine-readable and minimal:
       - roadmap identity via
         `<!-- <marker-prefix>-roadmap-id: ... -->`
       - active child issues via roadmap task-list links
       - issue-to-issue dependencies via `Blocked by #NNN`
       - sequential roadmap dependencies via
         `<!-- <marker-prefix>-blocked-by: ... -->` only when a separate
         roadmap
         must close first
       - keep independent sibling work in roadmap task lists unless a true
         correctness, availability, or ordering constraint requires a
         dependency edge
    6. Before publishing a ready orphan, roadmap, or child body, run the
       `audit-authored-issue` linter against it as the mechanical
       pre-publish gate — see
       [Mechanical pre-publish gate](references/contract.md#mechanical-pre-publish-gate)
       in the bundled contract, including the manual fallback for
       `instructions-only` installs with no helper runtime. Resolve every
       reported failure before treating the issue as ready. Before newly
       publishing a body into the `needs-decision` or `blocked-by-human`
       bucket instead, also run the linter, passing
       `--expect-bucket <needs-decision|blocked-by-human>` (choose the one
       matching value) — the same gate section's `--expect-bucket` flag
       requires the matching `authoring-bucket` marker for that publish,
       closing the gap where a non-ready body would otherwise never be
       audited at all.
    7. Publish each `ready` drafted body directly under the authoring hold
       once it passes the mechanical gate (step 6) and the critique pass
       (the Intake and Clarification phase above) — no separate publish
       approval is needed. Only skip publishing when the current request
       explicitly asked for a preview instead. Manage the authoring label
       for each created or updated issue:
       - resolve `issueAuthoring.authoringLabelName`, defaulting to
         `status:authoring`
       - create the label with `gh label create` before first use when the
         target repository does not already have it
       - treat label creation or application failure as a publishing blocker
       - apply the label before updating an existing issue
       - acquire per-target ownership before editing an existing issue or
         roadmap; the shared label is a claim-suppression lock, not an owner
         token. Follow the append-only owner-marker and re-read protocol in
         [references/workflow-boundary.md](references/workflow-boundary.md)
         and stop without editing when ownership or the target snapshot
         conflicts
       - for a new Stage 1 set, generate one opaque set ID and reuse it in every
         owner marker for that set; when resuming an interrupted set, recover and
         verify its persisted set ID from the exact trusted owner markers and
         reuse it instead of generating a replacement; never infer set membership
         from the label alone
       - when a set includes a parent roadmap, publish a valid roadmap shell under
         the authoring hold before any child; acquire and verify that roadmap as
         the set anchor, leaving its `## Tracks` list empty only until child issue
         numbers exist. Without a parent roadmap, use the designated lead target
         as the anchor
       - acquire and verify the set anchor before publishing or acquiring any
         child; do not acquire children independently, and stop all edits if any
         target cannot join that anchor's verified set
       - before each child acquisition or resume, append and verify a same-owner
         anchor heartbeat (or reuse one — see the heartbeat-coalescing rule
         below), re-fetch the anchor's paginated log, then append the child
         marker and immediately re-fetch both anchor and child. Stop with the
         label in place if anchor ownership changed between those reads
       - **Heartbeat coalescing** (`issueAuthoring.heartbeatCoalesceWindow`,
         default `PT2M`): before appending a heartbeat, replay the target's
         paginated log; reuse the latest trusted marker instead of appending
         when it is the same owner/set/session, its mode is
         `acquire`/`bootstrap`/`resume`/`heartbeat`, it is younger than the
         window, and its `body-sha256` matches the just-fetched body — re-fetch
         and verify the reused marker exactly as a fresh one. This window never
         applies to `acquire`, `bootstrap`, `resume`, `release`,
         `release-guard`, or `release-complete` appends themselves — only a
         `heartbeat` append may be skipped
       - persist the anchor's canonical repository/issue identity in every owner
         marker for the set; the anchor marker points to itself, and a resume must
         stop if the interrupted set's anchor cannot be proven
       - immediately before every Stage 1 body or relationship edit, re-fetch both
         the edited target and the set anchor; require each target's expected owner
         token independently, plus the same set, anchor, and owning session, and
         require an unchanged expected target snapshot before editing
       - immediately before that edit, renew both generations with a trusted
         same-owner-per-target heartbeat marker (one marker when target and anchor
         coincide; reuse applies here too), re-fetch and verify both, and stop if
         renewal or ownership verification fails
       - create new issues only through a capability-checked publication command
         that applies the authoring label atomically and carries an exact hidden
         publication token for target, anchor, set, and session; if that operation
         is unavailable, stop before creating the issue — never intentionally
         create an unlabeled issue
       - the hidden publication token is this exact HTML-first body line.
         `anchor` reuses the opaque `target` value only when this new issue
         is itself the set anchor (self-reference); for a non-anchor child,
         `anchor` is instead the set anchor's already-resolved real
         `<owner>/<repo>#<number>` reference, not an opaque id (full rule:
         `references/contract.md`'s "New-issue ownership" section):
    
         ```html
         <!-- <marker-prefix>-authoring-publication: target=<opaque-target-id>; anchor=<opaque-anchor-id>; set=<opaque-set-id>; session=<opaque-session-id>; token=<opaque-publication-token> -->
         ```
    
       - The originating Stage 1 hold uses this append-only publication-intent
         record, whose `anchor` follows the same self-anchor/non-anchor-child
         rule:
    
         ```html
         <!-- <marker-prefix>-authoring-publication-intent: target=<opaque-target-id>; anchor=<opaque-anchor-id>; set=<opaque-set-id>; session=<opaque-session-id>; token=<opaque-publication-token>; journal=<owner>/<repo>#<number>; issue=<owner>/<repo>#<number>|none; actor=<trusted-marker-actor>; state=<pending|member|cleanup|abandoned> -->
         ```
    
         `issue` is the returned canonical issue identity or `none`. Append
         `state=pending; issue=none` before creation, then append the returned
         identity while it remains `pending`, append `member` only after the owner
         marker is verified, and append `cleanup` before any safe-close mutation.
         Append `abandoned` only after closed/label-absent verification. On
         resume, paginate the hold log and select the latest valid record for the
         exact token tuple; missing, conflicting, or out-of-order records fail
         closed, while `pending` and `cleanup` remain recovery holds.
    
         `journal` is the durable record location. For an existing set, use the
         verified originating Stage 1 hold; for a standalone set with no existing
         issue or anchor, use the repository-level authoring journal target
         configured at `issueAuthoring.journalIssue` in `.github/idd/config.json`
         (an `owner/repo#number` reference to a pre-existing, durable,
         comment-only issue) -- an unset `issueAuthoring.journalIssue` only
         blocks a standalone set; an existing set with a verified Stage 1 hold
         needs no journal configuration at all. Do not create that journal as
         part of the same set. If the applicable location cannot be resolved --
         no verified Stage 1 hold for an existing set, or
         `issueAuthoring.journalIssue` unset or unverifiable for a standalone
         set -- stop with `blocked-by-human` before creating any target. On
         every paginated replay, require `actor` to equal the API author and
         verify that actor is a trusted marker login with the required write-level
         permission or configured bot/app trust. An untrusted, malformed, or
         conflicting exact-token record is not valid evidence; fail closed and
         retain the hold.
    
         Generate the opaque `target` id and token before creation because the
         new issue's own number is not yet known, and generate `anchor` the
         same way only when this new issue is the set anchor itself --
         otherwise reuse the anchor's already-resolved real reference, per
         the self-anchor/non-anchor-child rule above. Before issuing the
         create, persist those preallocated
         IDs, the exact token, and `state=pending` in that journal. After
         a successful create, attach and verify the returned issue identities on
         that pending record before appending the owner marker. If the pre-create
         hold write cannot be verified, do not create; if the post-create identity
         attachment cannot be verified, leave the returned issue held for recovery.
         Transition to `member` only after owner-marker verification or
         `abandoned` only after the verified safe close and label removal. On
         resume, match the exact token and persisted identities; an incomplete
         scan or state mismatch is recovery.
       - immediately after a new issue is created and labeled, append its
         `mode=acquire` owner marker with the current set ID, then re-fetch the
         labels, body, and owner comments before treating it as a set member
       - an atomically labeled publication is not set membership until its owner
         marker is verified; persist each returned target identity in the journal
         before appending the marker. On resume, reconcile
         recorded identities and only issues carrying this set's exact publication
         token; an incomplete scan or unmarked match is a recovery hold, so never
         infer membership or completion from the shared label alone
       - if owner-marker append or verification is uncertain for a new issue,
         reconcile the returned comment ID and the paginated owner-marker log with
         bounded retries before closing; if a trusted marker is found, retain the
         label and recover or reopen the issue as a set member. Otherwise re-fetch
         labels, body, current `claimed-by` state, and the paginated owner-marker
         log; if that final read proves no competing claim or owner marker, append
         `state=cleanup` before closing the issue or removing its authoring label.
         Re-fetch and verify closed/label-absent state, then append
         `state=abandoned`. If any disposition or cleanup read is uncertain,
         retain `state=cleanup`, leave the issue held, and report the recovery hold
       - if an allegedly atomic create unexpectedly returns an unlabeled issue,
         re-fetch its labels, body, current `claimed-by` state, and paginated
         owner-marker log before closing. If a trusted claim or owner marker from
         another session/set is present, do not close or overwrite the exposed
         issue; report the ownership conflict and stop. If no competing claim is
         present, apply and verify the authoring label as a safe hold, then
         re-fetch its labels, body, current `claimed-by` state, and paginated
         owner-marker log again before closing. If that hold or final re-read
         cannot be verified, leave the issue open and report the recovery hold.
         Deletion needs admin permission and is not the default recovery path
       - held issues under the label ARE the drafts: do in-place body
         edits, roadmap relationship wiring, and re-lint of already-published
         bodies on the published issue itself, under the same label
       - if a session is interrupted before the set is fully wired, leave the
         label and owner markers in place — the label suppresses Discover and
         the markers preserve the set identity for a later verified resume
       - read every target and anchor owner-marker log with paginated retrieval and
         deterministic comment order; never rely on a single API page
       - after the release checklist passes and the user explicitly requests
         release — or, for a single target whose body carried the
         review-fix-loop-cutoff marker at Stage 1 publication time (never a
         marker added later), the narrow auto-release exception in
         [Authoring hold and release](references/contract.md#authoring-hold-and-release)
         — preflight and verify or reuse a matching `mode=release` marker
         for every target (with `supersedes` equal to the current owner token)
         before removing any label; record its GitHub comment ID, never append a
         duplicate on retry, append and reconcile an anchor-only
         `mode=release-guard` marker before the first label removal, keep the set
         anchor held, and remove it last. Recheck
         each target's expected owner token independently, plus the shared
         set/anchor/session, recorded marker, and expected snapshot immediately
         before each removal. Renew and verify the set anchor heartbeat first
         (reuse applies here too), re-fetching its current owner, set, anchor,
         and session; only then renew and verify the target heartbeat when
         distinct (one marker when they coincide; reuse applies here too).
         Remove non-anchor labels one at a time and
         verify the whole set. After the final anchor label removal is verified,
         reuse or append the anchor-only `mode=release-complete` marker and record
         its comment ID. Reconcile that ID and the paginated anchor log with
         bounded retries; a successful POST or verification timeout is
         inconclusive. If the trusted marker is found, keep labels absent and
         close the set. If a complete fresh read conclusively proves that no
         trusted marker was appended, restore labels for every target and leave
         every target generation open. If reads remain inconclusive, keep the
         release guard and current labels/state in place, leave the set held, and
         record a recovery hold. Never infer marker absence or roll back from a
         verification timeout. Discover must treat the reconciled release guard as
         suppressing every target until the anchor completion marker is found.
         Treat each release marker, removal, and completion
         marker as provisional until the durable completion event is reconciled.
         If a later removal or verification fails, retry a failed post-removal
         read with a bounded fresh read, restore labels for already processed
         targets while the owner/set still match, verify the restored set, and
         leave every target generation open
    8. Stop at the single approval boundary: release. Publishing under the
       hold does not by itself authorize starting the IDD execution loop —
       only the user's explicit release request does, except the narrow
       review-fix-loop-cutoff auto-release exception in
       [Authoring hold and release](references/contract.md#authoring-hold-and-release).
    
    ## Reference Routing
    
    - For the bundled contract, output schemas, and discoverability guard:
      read [references/contract.md](references/contract.md).
    - For the bundled two-stage authoring/release contract and the
      boundary with the IDD execution loop: read
      [references/workflow-boundary.md](references/workflow-boundary.md).
    - For concrete drafting patterns and example prompts: read
      [references/draft-patterns.md](references/draft-patterns.md).
    - When editing this bundle inside the source repository, keep the
      bundled references synchronized with the canonical maintenance docs at
      repo-root `docs/issue-authoring-skill.md` and `docs/idd-workflow.md`
      (relative links are avoided here since this file is mirrored at a
      different path depth in `.claude/skills/issue-authoring/`).
    
    ## Output Checklist
    
    - Preserve low-readiness work in stable buckets instead of dropping it.
    - Keep acceptance criteria explicitly verifiable.
    - Keep human-dependent setup, review, and approval work isolated from
      ready execution issues whenever possible.
    - Link every active child issue from its roadmap body.
    - Justify each dependency edge and keep independent sibling work as
      roadmap task-list entries.
    - Record reuse or extension decisions when the skill does not create a
      new issue.
    - Avoid widening drafting output beyond the user request without saying
      so.
    - Run the `audit-authored-issue` linter (or its manual fallback in
      `instructions-only` installs) against every drafted ready body, and
      against every body newly published into `needs-decision` or
      `blocked-by-human` with `--expect-bucket`; resolve every reported
      failure before publishing.
    - Name a concrete surface to edit and an objective verification for
      every `ready` candidate; route anything else to `needs-decision` or
      ask instead of guessing (the under-clarification stop rule).
    - Resolve the target repository's marker prefix before emitting any
      authoring marker; never assume this source repository's `idd-skill`
      prefix in an installed bundle (the prefix-first rule).
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related