[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M736W281ACF2N4TFK1SWFX5Q":3,"skill-same:01M736W281ACF2N4TFK1SWFX5Q":50},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":18,"linkOnly":19,"markdownContent":20,"markdownBody":21,"frontMatter":22,"refName":23,"commitSha":24,"skillDirectory":25,"forksCount":13,"repositoryHtmlUrl":26,"repositoryHomepageUrl":6,"ownerHtmlUrl":27,"ownerBlogUrl":6,"ownerDescription":28,"updatedAt":29,"install":30,"resources":43},"01M736W281ACF2N4TFK1SWFX5Q","deliver-plan-tracking-issue",null,"Open or resume one lightweight issue-backed plan tracker and carry it through implementation, review, PR delivery, strict closeout, and archive handoff.","graysurf\u002Fagent-runtime-kit","graysurf","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F10785178?v=4","01M736PQHYKHFMNBYF8BT93NM4","01M736PQJWYH7G046WAN7EQCHD",0,"MIT","https:\u002F\u002Fgithub.com\u002Fgraysurf\u002Fagent-runtime-kit\u002Fblob\u002Fmain\u002Ftests\u002Fgolden\u002Fhermes\u002Fplugins\u002Fdispatch\u002Fskills\u002Fdeliver-plan-tracking-issue\u002Fexpected\u002FSKILL.md",[],[],"2026-11-11 15:11:14",false,"---\nname: deliver-plan-tracking-issue\ndescription: >\n  Open or resume one lightweight issue-backed plan tracker and carry it through\n  implementation, review, PR delivery, strict closeout, and archive handoff.\n---\n\n# Deliver Plan Tracking Issue\n\n## Contract\n\nPrereqs:\n\n- Profile: `tracking`.\n- CLI floors: `plan-issue >=1.0.13`, `plan-tooling >=1.0.1`,\n  `forge-cli >=1.22.12`, `review-specialists`.\n- The tracking issue is absent and ready to open, or open, visible, and\n  reconcilable with `run-state.json`; FSM is not blocked or stale.\n- PR delivery runs the generic code-review outcome in pre-merge context with the\n  full profile and posts\n  native review events per\n  `core\u002Fskills\u002Fcode-review\u002Fcode-review-specialists\u002Freferences\u002FREVIEW_OUTCOME_POSTING_CONTRACT.md`.\n  Every tracking PR runs the full gate; there is no single-author self-review\n  shortcut.\n- Shared family rules apply from\n  `core\u002Fskills\u002Fdispatch\u002Fplan-issue-spec\u002Fskill-family.md`.\n- Internal role ordering and single-writer boundaries apply from\n  `references\u002Foutcome-routing.md`.\n\nInputs:\n\n- `OWNER_REPO`, optional `ISSUE`, `RUN_STATE` (derived when opening a tracker;\n  required when resuming `ISSUE`), `PLAN_BUNDLE`, `SLUG`,\n  `BRANCH`, `PR_NUMBER`, `PROVIDER`, `BASE_REF`, and post-close read-back paths\n  `CLOSED_ISSUE_VIEW_JSON`, `CLOSED_ISSUE_JSON`, and `CLOSED_ISSUE_BODY`.\n- Optional `LINKED_PR` when a PR already exists and should be verified\n  instead of created.\n- Approval evidence for the later close-ready probe.\n- Review-gate artifacts: per-lens `REVIEW_LENS`,\n  `SPECIALIST_REVIEW_COMMENT_FILE`, optional GitHub `REVIEW_THREAD_FILE` for\n  actionable findings, `REVIEW_DECISION`, and `DELIVERY_REVIEW_OUTCOME`\n  (combined outcome body).\n- `REVIEW_OUTCOME_COMMENT`: the native review event URL produced by\n  `forge-cli pr review --submit-review` (or a retained evidence path).\n  `REVIEW_FINDINGS_JSON` is optional and contains finding rows when findings\n  exist.\n- Local terminal identity captured before merge: checkout root, branch,\n  delivered head SHA, base ref, and primary-versus-managed-worktree kind.\n\nOutputs:\n\n- `record open|attach --profile tracking` and `tracking run init` when the\n  tracker does not yet exist or has no run state.\n- Progress checkpoints: `tracking checkpoint --live --post\n  state[,session[,validation]]`.\n- PR delivery through `forge-cli pr deliver --no-merge`, or adoption of an\n  already linked PR, so the review gate runs before merge.\n- Provider review activity through `forge-cli pr review`: one native GitHub\n  `COMMENT` per specialist lens and one combined semantic outcome, expressed\n  only through portable provider \u002F decision \u002F lens flags, with a\n  `--mirror-issue` breadcrumb to the tracking issue. The combined outcome is a\n  native GitHub approval only when an environment-owned router guarantees an\n  identity independent from the PR author; otherwise it is an outcome note.\n- On GitHub, current-head native review summaries read through\n  `forge-cli pr reviews` and semantically dispositioned before the combined\n  owner outcome. GitLab retains the outcome-note flow because native snapshots\n  are GitHub-only in v1.\n- Delivery checkpoint: `tracking checkpoint --live --post state,review`, whose\n  `review` role records the provider review outcome URL and is posted before merge.\n- Per-task ledger sync through `plan-tooling ledger-update`.\n- `forge-cli pr merge` after semantic review and the issue-side review\n  checkpoint; the CLI owns convergence, thread\u002Ftask enforcement, and head\n  binding.\n- Strict `tracking close-ready --expect-visible`, followed by\n  `record close --profile tracking` only when readiness and approval are complete.\n- Post-close provider read-back plus `record audit --expect-visible`, followed\n  by `plan-archive discover` and dry-run-first `plan-archive migrate` routing;\n  apply remains confirmation-gated.\n- After all plan-required post-merge activation\u002Fdeployment, closeout, archive,\n  and evidence duties, one terminal cleanup result under\n  `core\u002Fpolicies\u002Fgit-delivery.md`: safe removal\u002Frestoration, or explicit\n  retained state with its failed proof and recovery command.\n\nFailure modes:\n\n- Stop on `run-state-stale`, `issue-evidence-missing`, `RECORD_BLOCKED`,\n  `visible-completeness-failed`, PR delivery failure, or any\n  `close-ready` blocker.\n- Stop on provider payload privacy failures such as `local_path_present`; rewrite\n  useful evidence paths to `$HOME\u002F...` and omit remote-useless local artifact\n  paths before retrying.\n- Stop when `github_pending_review_exists` reports an existing pending draft\n  but `data.pending_reviews[]` does not identify exactly one abandoned\n  current-viewer review for this PR; never delete ambiguous review state.\n- Stop on `ledger-rows-pending`; repair the named task rows with\n  `plan-tooling ledger-update` before retrying the gate.\n- Stop when `pr merge` fails closed on review convergence, native change\n  requests, unresolved threads, unchecked tasks, or head drift. Read the\n  matching provider surface, disposition the evidence, update the owner\n  outcome\u002Fcheckpoint when it changed, and only then retry.\n- Forbidden writes: dispatch-profile posts, raw lifecycle comments, raw\n  `gh pr review` \u002F `glab mr approve` for recorded review evidence, or merging before the review\n  gate and `review` checkpoint complete.\n- Stop cleanup when the checkout is dirty\u002Flocked, provider merge truth does not\n  match the captured delivered head, or a downstream terminal duty is still\n  pending. Never force-remove or delete ambiguous local work.\n\n## Outcome Routing\n\nThe user selects the L2 plan outcome, never tracker creation, execution,\nreview, closeout, or archive substeps. This parent selects those phases using\n`references\u002Foutcome-routing.md` and preserves their\nseparate CLI write authorities.\n\nWhen no tracker exists, validate the bundle, open or attach it through\n`plan-issue record`, and initialize run state before implementation. When a\ntracker exists, reconcile live evidence before any mutation. After delivery and\nindependent review, merge only after the issue-side review checkpoint and all\nprovider sweeps pass. Close only after `tracking close-ready` returns\n`ready: true`; then run archive discovery and migration directly through\n`plan-archive`, dry-run first and apply only with explicit confirmation.\n\n## Entrypoint\n\n```bash\nplan-tooling validate --file \"$PLAN_BUNDLE\u002F$SLUG-plan.md\" --format text --explain\n\n# Open and capture a tracker only when ISSUE is absent. An explicit ISSUE is\n# read back and resumed; it must never pass through record open.\nPROVIDER=\"$(forge-cli repo view --repo \"$OWNER_REPO\" --format json \\\n  | python3 -c 'import json,sys; print(json.load(sys.stdin)[\"data\"][\"provider\"])')\"\ncase \"$PROVIDER\" in\n  github) PLAN_LABEL_ARGS=(--label workflow::plan --label workflow::tracking) ;;\n  gitlab) PLAN_LABEL_ARGS=(--label workflow::tracking --label plan) ;;\n  *) echo \"unsupported tracker provider: $PROVIDER\" >&2; exit 64 ;;\nesac\n\nif [ -z \"${ISSUE:-}\" ]; then\n  TRACKER_JSON=\"$(plan-issue --repo \"$OWNER_REPO\" --format json record open \\\n    --profile tracking --bundle \"$PLAN_BUNDLE\" --title \"$TITLE\" \\\n    --label type::chore --label area::docs \\\n    --label state::needs-triage \\\n    \"${PLAN_LABEL_ARGS[@]}\")\"\n  ISSUE=\"$(printf '%s\\n' \"$TRACKER_JSON\" \\\n    | python3 -c 'import json,sys; print(json.load(sys.stdin)[\"payload\"][\"result\"][\"issue\"][\"number\"])')\"\n  ISSUE_URL=\"$(printf '%s\\n' \"$TRACKER_JSON\" \\\n    | python3 -c 'import json,sys; print(json.load(sys.stdin)[\"payload\"][\"result\"][\"issue\"][\"url\"])')\"\n\n  RUN_INIT_JSON=\"$(plan-issue --format json tracking run init \\\n    --provider-repo \"$OWNER_REPO\" --issue \"$ISSUE\" \\\n    --bundle \"$PLAN_BUNDLE\" \\\n    --execution-state-file \"$PLAN_BUNDLE\u002F$SLUG-execution-state.md\" \\\n    --branch \"$BRANCH\" \\\n    --now \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\")\"\n  RUN_STATE=\"$(printf '%s\\n' \"$RUN_INIT_JSON\" \\\n    | python3 -c 'import json,sys; print(json.load(sys.stdin)[\"payload\"][\"result\"][\"run_state_path\"])')\"\nelse\n  : \"${RUN_STATE:?RUN_STATE is required when ISSUE is supplied}\"\n  TRACKER_JSON=\"$(forge-cli --provider \"$PROVIDER\" --repo \"$OWNER_REPO\" --format json issue view \"$ISSUE\")\"\n  ISSUE_URL=\"$(printf '%s\\n' \"$TRACKER_JSON\" \\\n    | python3 -c 'import json,sys; print(json.load(sys.stdin)[\"data\"][\"url\"])')\"\nfi\n\nplan-issue --format json tracking status \\\n  --provider-repo \"$OWNER_REPO\" \\\n  --issue \"$ISSUE\" \\\n  --profile tracking \\\n  --run-state \"$RUN_STATE\" \\\n  --expect-visible\n\nplan-tooling ledger-update \\\n  --execution-state \"$PLAN_BUNDLE\u002F$SLUG-execution-state.md\" \\\n  --task \"$TASK_ID\" \\\n  --status done \\\n  --evidence \"$EVIDENCE\"\n\nplan-issue --format json tracking run update \\\n  --run-state \"$RUN_STATE\" \\\n  --phase validating \\\n  --validation-overall pass \\\n  --validation-command \"$VALIDATION_COMMAND\" \\\n  --validation-status pass \\\n  --validation-evidence \"$VALIDATION_LOG\" \\\n  --now \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"\n\nplan-issue --format json tracking checkpoint \\\n  --provider-repo \"$OWNER_REPO\" \\\n  --issue \"$ISSUE\" \\\n  --profile tracking \\\n  --run-state \"$RUN_STATE\" \\\n  --live \\\n  --post state,session,validation \\\n  --repair-dashboard\n\n# Deliver the PR without merging so the review gate has a window (adopt and\n# verify LINKED_PR through pr deliver existing-PR adoption when it already exists).\nforge-cli pr deliver --repo \"$OWNER_REPO\" \\\n  --kind feature --title \"$PR_TITLE\" \\\n  --head \"$BRANCH\" --base main \\\n  --body-file \"$PR_BODY_FILE\" \\\n  --test-first-evidence \"$EVIDENCE_DIR\" \\\n  --no-merge --format json\n\n# Shared read-only specialist gate (min testing + maintainability).\nreview-specialists scope --base \"$BASE_REF\" --testing --maintainability --format json\n\n# Native review events (GitHub) per REVIEW_OUTCOME_POSTING_CONTRACT.md: one\n# COMMENT per semantic lens as each lens returns, then the combined\n# APPROVE\u002FREQUEST_CHANGES outcome. The local head is the reviewed specialist\n# diff; forge-cli rejects the write if the provider head has drifted.\nEXPECTED_REVIEW_HEAD=\"$(git rev-parse HEAD)\"\nSUBMIT_REVIEW=()\n[ \"$PROVIDER\" = github ] &&\n  SUBMIT_REVIEW=(--submit-review --expected-head \"$EXPECTED_REVIEW_HEAD\")\nFINAL_SUBMIT_REVIEW=()\nREVIEW_CONVERGENCE_ARGS=()\n[ \"$PROVIDER\" = gitlab ] && REVIEW_CONVERGENCE_ARGS=(--review-convergence=false)\n\nSELECTED_REVIEW_LENSES=(testing maintainability)\n# Append every risk lens selected by the full pre-merge review.\nREVIEW_LENS_ARGS=()\nTRACKING_LENS_ARGS=()\nfor selected_lens in \"${SELECTED_REVIEW_LENSES[@]}\"; do\n  REVIEW_LENS_ARGS+=(--lens \"$selected_lens\")\n  TRACKING_LENS_ARGS+=(--review-lens \"$selected_lens\")\ndone\n\n# Repeat this specialist block once for each returned lens: testing,\n# maintainability, plus any risk lens selected by the full pre-merge review.\nTHREAD_FILE_ARGS=()\nif [ \"$PROVIDER\" = github ] && [ -n \"${REVIEW_THREAD_FILE:-}\" ]; then\n  THREAD_FILE_ARGS=(--thread-file \"$REVIEW_THREAD_FILE\")\nfi\nforge-cli --provider \"$PROVIDER\" pr review \"$PR_NUMBER\" \\\n  --repo \"$OWNER_REPO\" \\\n  --decision comments-only \\\n  \"${SUBMIT_REVIEW[@]}\" \\\n  \"${THREAD_FILE_ARGS[@]}\" \\\n  --comment-file \"$SPECIALIST_REVIEW_COMMENT_FILE\" \\\n  --lens \"$REVIEW_LENS\" \\\n  --issue \"$ISSUE\" --mirror-issue --format json\n\n# Read native review bodies after specialist posting and repair. Disposition\n# actionable current-head summaries before the combined owner outcome; stale\n# summaries are informational. When summary_truncated is true, retrieve the\n# full review body through provider read tooling and stop if it is unavailable.\nPRE_SUBMIT_PR=\"$(\n  forge-cli --provider \"$PROVIDER\" --repo \"$OWNER_REPO\" \\\n    --format json pr view \"$PR_NUMBER\"\n)\"\nEXPECTED_REVIEW_HEAD=\"$(\n  printf '%s\\n' \"$PRE_SUBMIT_PR\" |\n    jq -er 'select(.ok == true) | .data.head_sha'\n)\" || exit $?\nreadonly EXPECTED_REVIEW_HEAD\nif [ \"$PROVIDER\" = github ]; then\n  PRE_SUBMIT_REVIEWS=\"$(\n    forge-cli --provider \"$PROVIDER\" --repo \"$OWNER_REPO\" \\\n      --format json pr reviews \"$PR_NUMBER\"\n  )\"\n  printf '%s\\n' \"$PRE_SUBMIT_REVIEWS\"\n  printf '%s\\n' \"$PRE_SUBMIT_REVIEWS\" |\n    jq -e --arg head \"$EXPECTED_REVIEW_HEAD\" \\\n      '.ok == true and .data.head_sha == $head' >\u002Fdev\u002Fnull\nfi\n\n# Bind a routed combined native outcome to the provider head just inspected.\ncase \"${AGENT_RUNTIME_FORGE_IDENTITY_ROUTER_REQUIRED:-}\" in\n  1|[Tt][Rr][Uu][Ee]|[Yy][Ee][Ss])\n    [ \"$PROVIDER\" = github ] &&\n      FINAL_SUBMIT_REVIEW=(--submit-review --expected-head \"$EXPECTED_REVIEW_HEAD\")\n    ;;\nesac\n\n# Capture the outcome bytes once. Initial submission, guarded recovery, and\n# the single retry must all use this immutable value rather than rereading a\n# mutable file path. Preserve capture failures before freezing the value, and\n# use `--option=value` below so hyphen-leading Markdown remains one argv value.\nEXPECTED_REVIEW_BODY=\"$(cat \"$DELIVERY_REVIEW_OUTCOME\")\" || exit $?\nreadonly EXPECTED_REVIEW_BODY\nNATIVE_REVIEW_CMD=(\n  forge-cli --provider \"$PROVIDER\" --repo \"$OWNER_REPO\" --format json\n  pr review \"$PR_NUMBER\"\n  --decision \"$REVIEW_DECISION\"\n  \"${FINAL_SUBMIT_REVIEW[@]}\"\n  --comment=\"$EXPECTED_REVIEW_BODY\"\n  \"${REVIEW_LENS_ARGS[@]}\"\n  --issue \"$ISSUE\" --mirror-issue\n)\n# Clear stale selector state, then preserve the failed command status and JSON.\nunset PENDING_REVIEW_ID\nset +e\nNATIVE_REVIEW_JSON=\"$(\"${NATIVE_REVIEW_CMD[@]}\" 2>&1)\"\nNATIVE_REVIEW_STATUS=$?\nset -e\n\nif [ \"$NATIVE_REVIEW_STATUS\" -ne 0 ]; then\n  if [ \"$PROVIDER\" != github ] || ! printf '%s\\n' \"$NATIVE_REVIEW_JSON\" |\n    jq -e '.ok == false and .error.code == \"github_pending_review_exists\"' \\\n      >\u002Fdev\u002Fnull; then\n    printf '%s\\n' \"$NATIVE_REVIEW_JSON\" >&2\n    exit \"$NATIVE_REVIEW_STATUS\"\n  fi\n\n  # Fetch a fresh post-conflict pr reviews snapshot.\n  if [ \"$PROVIDER\" = github ]; then\n    POST_CONFLICT_REVIEWS=\"$(\n      forge-cli --provider \"$PROVIDER\" --repo \"$OWNER_REPO\" \\\n        --format json pr reviews \"$PR_NUMBER\"\n    )\"\n    PENDING_REVIEW_ID=\"$(\n      printf '%s\\n' \"$POST_CONFLICT_REVIEWS\" |\n        jq -er --arg head \"$EXPECTED_REVIEW_HEAD\" \\\n          --arg body \"$EXPECTED_REVIEW_BODY\" '\n            select(.ok == true and .data.head_sha == $head)\n            | [.data.pending_reviews[]\n                | select(.state == \"PENDING\")\n                | select(.commit_sha == $head)\n                | select(.summary_truncated == false)\n                | select((.summary | rtrimstr(\"\\n\")) == ($body | rtrimstr(\"\\n\")))]\n            | select(length == 1)\n            | .[0].id\n          '\n    )\"\n    if [ -n \"${PENDING_REVIEW_ID:-}\" ]; then\n      DELETE_REVIEW_JSON=\"$(\n        forge-cli --provider \"$PROVIDER\" --repo \"$OWNER_REPO\" \\\n          --format json pr pending-review delete \"$PR_NUMBER\" \\\n          --review \"$PENDING_REVIEW_ID\" \\\n          --expected-head \"$EXPECTED_REVIEW_HEAD\" \\\n          --expected-commit \"$EXPECTED_REVIEW_HEAD\" \\\n          --expected-body=\"$EXPECTED_REVIEW_BODY\" \\\n          --confirm-abandoned\n      )\"\n      POST_DELETE_REVIEWS=\"$(\n        forge-cli --provider \"$PROVIDER\" --repo \"$OWNER_REPO\" \\\n          --format json pr reviews \"$PR_NUMBER\"\n      )\"\n      printf '%s\\n' \"$POST_DELETE_REVIEWS\" |\n        jq -e --arg head \"$EXPECTED_REVIEW_HEAD\" \\\n          --arg id \"$PENDING_REVIEW_ID\" '\n            .ok == true\n            and .data.head_sha == $head\n            and (.data.pending_reviews | map(.id) | index($id) | not)\n          ' >\u002Fdev\u002Fnull\n\n      set +e\n      NATIVE_REVIEW_RETRY_JSON=\"$(\"${NATIVE_REVIEW_CMD[@]}\" 2>&1)\"\n      NATIVE_REVIEW_RETRY_STATUS=$?\n      set -e\n      if [ \"$NATIVE_REVIEW_RETRY_STATUS\" -ne 0 ]; then\n        printf '%s\\n' \"$NATIVE_REVIEW_RETRY_JSON\" >&2\n        exit \"$NATIVE_REVIEW_RETRY_STATUS\"\n      fi\n      NATIVE_REVIEW_JSON=\"$NATIVE_REVIEW_RETRY_JSON\"\n    fi\n  fi\nfi\n\nprintf '%s\\n' \"$NATIVE_REVIEW_JSON\"\nREVIEW_OUTCOME_COMMENT=\"$(\n  printf '%s\\n' \"$NATIVE_REVIEW_JSON\" | jq -er '.data.pr_comment_url'\n)\"\n# Record issue-side review evidence from the native outcome, then post the final\n# state + review checkpoint before merging.\nplan-issue --format json tracking run update \\\n  --run-state \"$RUN_STATE\" \\\n  --phase ready-for-close \\\n  --linked-pr \"$OWNER_REPO#$PR_NUMBER\" \\\n  --review-decision approve \\\n  \"${TRACKING_LENS_ARGS[@]}\" \\\n  --review-outcome-comment \"$REVIEW_OUTCOME_COMMENT\" \\\n  --now \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"\n\nplan-issue --format json tracking checkpoint \\\n  --provider-repo \"$OWNER_REPO\" \\\n  --issue \"$ISSUE\" \\\n  --profile tracking \\\n  --run-state \"$RUN_STATE\" \\\n  --live \\\n  --post state,review \\\n  --repair-dashboard\n\n# Merge only after semantic disposition and the review checkpoint pass. The\n# CLI owns observed quiet timing, native change requests, thread\u002Ftask gates,\n# and provider-head binding. Reuse the inspected\u002Freviewed provider head so a\n# later push cannot enter the merge.\nforge-cli --provider \"$PROVIDER\" pr ready \"$PR_NUMBER\"\nforge-cli --provider \"$PROVIDER\" pr merge \"$PR_NUMBER\" --method squash \\\n  --expected-head \"$EXPECTED_REVIEW_HEAD\" \\\n  \"${REVIEW_CONVERGENCE_ARGS[@]}\"\n\nplan-issue --format json tracking close-ready \\\n  --provider-repo \"$OWNER_REPO\" \\\n  --issue \"$ISSUE\" \\\n  --profile tracking \\\n  --run-state \"$RUN_STATE\" \\\n  --linked-pr \"$OWNER_REPO#$PR_NUMBER\" \\\n  --approval \"$APPROVAL\" \\\n  --expect-visible\n\n# Only after close-ready reports ready=true and blockers=[].\nplan-issue --repo \"$OWNER_REPO\" --format json record close \\\n  --profile tracking --issue \"$ISSUE\" --bundle \"$PLAN_BUNDLE\" \\\n  --linked-pr \"$OWNER_REPO#$PR_NUMBER\" --approval \"$APPROVAL\" \\\n  --add-label state::closed --remove-label state::needs-triage\n\n# Read back the closed provider issue body and comments, then require visible\n# closeout evidence before archive maintenance.\nforge-cli --provider \"$PROVIDER\" --repo \"$OWNER_REPO\" --format json issue view \"$ISSUE\" --with-comments \\\n  >\"$CLOSED_ISSUE_VIEW_JSON\"\njq '{body:.data.body, comments:(.data.comments \u002F\u002F [])}' \\\n  \"$CLOSED_ISSUE_VIEW_JSON\" >\"$CLOSED_ISSUE_JSON\"\njq -r .body \"$CLOSED_ISSUE_JSON\" >\"$CLOSED_ISSUE_BODY\"\n\nplan-issue --repo \"$OWNER_REPO\" --format json record audit \\\n  --profile tracking \\\n  --body-file \"$CLOSED_ISSUE_BODY\" \\\n  --comments-json \"$CLOSED_ISSUE_JSON\" \\\n  --expect-visible\n\nplan-archive discover --source-repo \"$PWD\" --format json\nplan-archive migrate --plan \"$PLAN_BUNDLE\" --issue \"$ISSUE_URL\" --format json\n```\n\nWhen the caller supplies an ordinary provider issue that has not yet received\ntracking lifecycle records, do not enter the resume branch yet. Read the issue\nand audit its comments first. After confirming that the source, plan, and state\nroles are absent, run `record attach --profile tracking` exactly once,\ninitialize its run state, and then resume with the resulting `RUN_STATE`. Never\nattach to an issue that already carries those roles, because attachment posts a\nnew lifecycle set rather than resuming the existing tracker.\n\n`forge-cli pr deliver --no-merge` creates or adopts the draft and completes its\ncheck wait without merging, leaving the window for review. Inspect native\nsummaries and post the owner outcome before the issue-side `review` checkpoint;\nthen mark the PR ready and call `forge-cli pr merge`. The merge primitive owns\nthe observed quiet window, complete\u002Ffinal native-review reads, native change\nrequests, thread\u002Ftask gates, and provider-head binding. When `LINKED_PR` already\nexists, adopt and verify it through `pr deliver` existing-PR adoption instead of\nre-creating it, and record the ref with `tracking run update --linked-pr`.\nObserved convergence is GitHub-only in v1, so GitLab merge calls explicitly pass\n`--review-convergence=false` to neutralize any user-global GitHub policy.\n\nPost one compact specialist review comment per lens as it returns — before any\nrepair — using `--decision comments-only` plus the semantic `--lens`, with\n`--thread-file \"$REVIEW_THREAD_FILE\"` for actionable GitHub findings; the\ncombined delivery outcome posts last with the final decision and selected lenses.\nOn GitHub, read native summaries before the combined outcome; on GitLab, retain\nthe outcome-note path and do not invoke the unsupported snapshot. A\n`summary_truncated` item requires the full review body before disposition; stop\nif it cannot be read. If native submission returns\n`github_pending_review_exists`, preserve the failed command status and JSON and\nfetch a fresh post-conflict snapshot.\nThe command binds the native review to the inspected head with\n`--expected-head`. Choose a recovery id only when\n`data.pending_reviews[]` identifies exactly one current-viewer abandoned node\nfor this PR and the intended body, decision, and head remain current. Run `pr\npending-review delete`, refresh `pr reviews`, and retry the unchanged outcome\nonce; stop on an ambiguous node, a failed guard, or a second rejection. The generic review\noutcome owns the read-only lenses and\nmode selection; this\nskill owns the provider writes, semantic disposition,\ncheckpoint, and merge, and reviewer subagents never post. On\n`review_convergence_activity_changed`, read `forge-cli pr reviews` again,\ndisposition the new evidence, refresh the final outcome\u002Fcheckpoint, and retry.\nFor `unresolved_review_threads` or `unchecked_task_items`, call the matching\n`pr review-threads list` or `pr tasks` read surface, disposition the returned\nitems, and retry. Outdated unresolved threads are auto-dispositioned `stale` by\n`pr merge` (`data.stale_thread_dispositions`) and do not block, so only\nnon-outdated threads need disposition; the `--allow-unresolved-threads` bypass\nnow requires a paired `--allow-unresolved-threads-reason` (recorded as\n`data.unresolved_threads_override_reason`). Do not duplicate quiet-period polling\nin skill prose.\n\nPlan-tracking PRs are `--kind feature` records, so when the test-first gate is\nenabled (`[test_first].require = true` in a repo `.forge-cli.toml` or the\nuser-global `${XDG_CONFIG_HOME:-~\u002F.config}\u002Fforge-cli\u002Fconfig.toml`) the deliver\nabove requires `--test-first-evidence \"$EVIDENCE_DIR\"` — the `verify`-clean\ndirectory the policy-owned `test-first-evidence` CLI flow produces — or it fails closed with\n`test_first_evidence_required`.\n\n## Workflow\n\n1. **Open \u002F preflight** — validate the bundle. Open or attach the tracker and\n   initialize run state when absent; otherwise run `tracking status\n   --expect-visible`. Stop on stale, blocked, or non-visible evidence.\n2. **Implementation \u002F validation** — do local work, update the task ledger\n   after every task transition, and checkpoint only changed roles.\n3. **PR branch** — deliver with `forge-cli pr deliver --no-merge` (or adopt and\n   verify `LINKED_PR` through `pr deliver` existing-PR adoption). Do not merge\n   yet; the review gate runs first.\n4. **Review gate** — run the generic code-review outcome in pre-merge context with the full profile (min `testing` +\n   `maintainability`; add risk lenses per scope). Post each lens's specialist\n   review comment through `forge-cli pr review` as it returns (native `COMMENT`\n   on GitHub via `--submit-review`, semantic `--lens`; `--thread-file`\n   for actionable findings). After repairs, read `forge-cli pr reviews` and\n   disposition every actionable current-head summary; stale summaries are\n   informational. Then post the combined delivery outcome (native GitHub\n   approval only with the independent-identity capability; repeated selected\n   lenses; `--mirror-issue`), per\n   `REVIEW_OUTCOME_POSTING_CONTRACT.md`. Every tracking PR runs the full gate —\n   there is no single-author self-review shortcut. Repair concrete findings in\n   this delivery branch and rerun affected lenses before continuing. A pending\n   native draft uses only the exact-node recovery above; never delete an\n   ambiguous draft or replace the requested native outcome with a note.\n5. **Review + final checkpoint** — set `phase=ready-for-close`, record the linked\n   PR, review decision, lenses, and `--review-outcome-comment` (the provider\n   outcome URL); add `--review-findings-file \"$REVIEW_FINDINGS_JSON\"` when findings\n   exist; then post `state,review` in one live checkpoint. This issue-side\n   `review` evidence is posted before merge.\n6. **Merge** — mark the PR ready, then call `forge-cli pr merge` once semantic\n   review and the issue-side checkpoint pass. Let the CLI enforce convergence,\n   native state, threads, tasks, and head binding. On a typed failure, read and\n   disposition the matching evidence; `review_convergence_activity_changed`\n   requires a refreshed owner outcome\u002Fcheckpoint before retry.\n   `review_convergence_head_changed` requires rebinding delivery evidence to\n   the new head, then re-run validation and affected review lenses, read the\n   current-head summaries, post a new owner outcome, and refresh the\n   validation\u002Freview checkpoint before retry.\n7. **Close-ready \u002F closeout** — run `tracking close-ready --expect-visible`.\n   Stop on every blocker. On `ready: true`, write the closing summary, perform\n   only controller-authorized final-role\u002Fdashboard repair, and call `record\n   close --profile tracking` with linked PR and approval evidence.\n8. **Closeout read-back** — fetch the closed provider issue with comments and\n   run `record audit --profile tracking --expect-visible`; stop unless the\n   closeout role is visible and lint-clean.\n9. **Archive maintenance** — only after closeout read-back succeeds, run\n    `plan-archive discover`, then the default dry-run `plan-archive migrate`;\n    apply only\n    after explicit confirmation and a clean plan.\n10. **Terminal local cleanup** — after archive and every plan-required\n    post-merge deployment, activation, evidence, or local closeout duty, recheck\n    provider merge\u002Fhead truth and local status. Restore a clean primary checkout\n    to base, or run `git-cli worktree remove \u003Cpath-or-slug> --format json` from\n    the primary checkout through the supported hooked shell; the target-aware\n    lease guard must confirm no live foreign owner before removal. If that proof\n    or hook is unavailable, retain the worktree. Delete the local\n    branch only when its tip equals the provider-confirmed delivered head,\n    including after squash merge. Retain and report dirty, locked, missing, or\n    unverifiable state.\n\n## Boundary\n\nOwns:\n\n- Delivery-scope judgement, validation strength, review-gate orchestration and\n  the provider review writes (per-lens specialist comments + the combined native\n  outcome), native-summary disposition, typed merge-failure repair, final\n  state\u002Freview checkpoint timing, the merge, strict closeout, read-back, and\n  archive routing.\n- Plan-required post-merge duties and exactly-once terminal local cleanup after\n  strict provider closeout\u002Fread-back.\n\nMust not:\n\n- Use dispatch-profile semantics, let reviewer subagents post provider comments,\n  close with any blocker, archive before close read-back, or merge before the\n  review gate and `review` checkpoint complete.\n\nInternal phases:\n\n- Open, execution, delivery, independent review, closeout, and archive phases\n  follow `references\u002Foutcome-routing.md`; they are not separate user\n  choices.\n","# Deliver Plan Tracking Issue\n\n## Contract\n\nPrereqs:\n\n- Profile: `tracking`.\n- CLI floors: `plan-issue >=1.0.13`, `plan-tooling >=1.0.1`,\n  `forge-cli >=1.22.12`, `review-specialists`.\n- The tracking issue is absent and ready to open, or open, visible, and\n  reconcilable with `run-state.json`; FSM is not blocked or stale.\n- PR delivery runs the generic code-review outcome in pre-merge context with the\n  full profile and posts\n  native review events per\n  `core\u002Fskills\u002Fcode-review\u002Fcode-review-specialists\u002Freferences\u002FREVIEW_OUTCOME_POSTING_CONTRACT.md`.\n  Every tracking PR runs the full gate; there is no single-author self-review\n  shortcut.\n- Shared family rules apply from\n  `core\u002Fskills\u002Fdispatch\u002Fplan-issue-spec\u002Fskill-family.md`.\n- Internal role ordering and single-writer boundaries apply from\n  `references\u002Foutcome-routing.md`.\n\nInputs:\n\n- `OWNER_REPO`, optional `ISSUE`, `RUN_STATE` (derived when opening a tracker;\n  required when resuming `ISSUE`), `PLAN_BUNDLE`, `SLUG`,\n  `BRANCH`, `PR_NUMBER`, `PROVIDER`, `BASE_REF`, and post-close read-back paths\n  `CLOSED_ISSUE_VIEW_JSON`, `CLOSED_ISSUE_JSON`, and `CLOSED_ISSUE_BODY`.\n- Optional `LINKED_PR` when a PR already exists and should be verified\n  instead of created.\n- Approval evidence for the later close-ready probe.\n- Review-gate artifacts: per-lens `REVIEW_LENS`,\n  `SPECIALIST_REVIEW_COMMENT_FILE`, optional GitHub `REVIEW_THREAD_FILE` for\n  actionable findings, `REVIEW_DECISION`, and `DELIVERY_REVIEW_OUTCOME`\n  (combined outcome body).\n- `REVIEW_OUTCOME_COMMENT`: the native review event URL produced by\n  `forge-cli pr review --submit-review` (or a retained evidence path).\n  `REVIEW_FINDINGS_JSON` is optional and contains finding rows when findings\n  exist.\n- Local terminal identity captured before merge: checkout root, branch,\n  delivered head SHA, base ref, and primary-versus-managed-worktree kind.\n\nOutputs:\n\n- `record open|attach --profile tracking` and `tracking run init` when the\n  tracker does not yet exist or has no run state.\n- Progress checkpoints: `tracking checkpoint --live --post\n  state[,session[,validation]]`.\n- PR delivery through `forge-cli pr deliver --no-merge`, or adoption of an\n  already linked PR, so the review gate runs before merge.\n- Provider review activity through `forge-cli pr review`: one native GitHub\n  `COMMENT` per specialist lens and one combined semantic outcome, expressed\n  only through portable provider \u002F decision \u002F lens flags, with a\n  `--mirror-issue` breadcrumb to the tracking issue. The combined outcome is a\n  native GitHub approval only when an environment-owned router guarantees an\n  identity independent from the PR author; otherwise it is an outcome note.\n- On GitHub, current-head native review summaries read through\n  `forge-cli pr reviews` and semantically dispositioned before the combined\n  owner outcome. GitLab retains the outcome-note flow because native snapshots\n  are GitHub-only in v1.\n- Delivery checkpoint: `tracking checkpoint --live --post state,review`, whose\n  `review` role records the provider review outcome URL and is posted before merge.\n- Per-task ledger sync through `plan-tooling ledger-update`.\n- `forge-cli pr merge` after semantic review and the issue-side review\n  checkpoint; the CLI owns convergence, thread\u002Ftask enforcement, and head\n  binding.\n- Strict `tracking close-ready --expect-visible`, followed by\n  `record close --profile tracking` only when readiness and approval are complete.\n- Post-close provider read-back plus `record audit --expect-visible`, followed\n  by `plan-archive discover` and dry-run-first `plan-archive migrate` routing;\n  apply remains confirmation-gated.\n- After all plan-required post-merge activation\u002Fdeployment, closeout, archive,\n  and evidence duties, one terminal cleanup result under\n  `core\u002Fpolicies\u002Fgit-delivery.md`: safe removal\u002Frestoration, or explicit\n  retained state with its failed proof and recovery command.\n\nFailure modes:\n\n- Stop on `run-state-stale`, `issue-evidence-missing`, `RECORD_BLOCKED`,\n  `visible-completeness-failed`, PR delivery failure, or any\n  `close-ready` blocker.\n- Stop on provider payload privacy failures such as `local_path_present`; rewrite\n  useful evidence paths to `$HOME\u002F...` and omit remote-useless local artifact\n  paths before retrying.\n- Stop when `github_pending_review_exists` reports an existing pending draft\n  but `data.pending_reviews[]` does not identify exactly one abandoned\n  current-viewer review for this PR; never delete ambiguous review state.\n- Stop on `ledger-rows-pending`; repair the named task rows with\n  `plan-tooling ledger-update` before retrying the gate.\n- Stop when `pr merge` fails closed on review convergence, native change\n  requests, unresolved threads, unchecked tasks, or head drift. Read the\n  matching provider surface, disposition the evidence, update the owner\n  outcome\u002Fcheckpoint when it changed, and only then retry.\n- Forbidden writes: dispatch-profile posts, raw lifecycle comments, raw\n  `gh pr review` \u002F `glab mr approve` for recorded review evidence, or merging before the review\n  gate and `review` checkpoint complete.\n- Stop cleanup when the checkout is dirty\u002Flocked, provider merge truth does not\n  match the captured delivered head, or a downstream terminal duty is still\n  pending. Never force-remove or delete ambiguous local work.\n\n## Outcome Routing\n\nThe user selects the L2 plan outcome, never tracker creation, execution,\nreview, closeout, or archive substeps. This parent selects those phases using\n`references\u002Foutcome-routing.md` and preserves their\nseparate CLI write authorities.\n\nWhen no tracker exists, validate the bundle, open or attach it through\n`plan-issue record`, and initialize run state before implementation. When a\ntracker exists, reconcile live evidence before any mutation. After delivery and\nindependent review, merge only after the issue-side review checkpoint and all\nprovider sweeps pass. Close only after `tracking close-ready` returns\n`ready: true`; then run archive discovery and migration directly through\n`plan-archive`, dry-run first and apply only with explicit confirmation.\n\n## Entrypoint\n\n```bash\nplan-tooling validate --file \"$PLAN_BUNDLE\u002F$SLUG-plan.md\" --format text --explain\n\n# Open and capture a tracker only when ISSUE is absent. An explicit ISSUE is\n# read back and resumed; it must never pass through record open.\nPROVIDER=\"$(forge-cli repo view --repo \"$OWNER_REPO\" --format json \\\n  | python3 -c 'import json,sys; print(json.load(sys.stdin)[\"data\"][\"provider\"])')\"\ncase \"$PROVIDER\" in\n  github) PLAN_LABEL_ARGS=(--label workflow::plan --label workflow::tracking) ;;\n  gitlab) PLAN_LABEL_ARGS=(--label workflow::tracking --label plan) ;;\n  *) echo \"unsupported tracker provider: $PROVIDER\" >&2; exit 64 ;;\nesac\n\nif [ -z \"${ISSUE:-}\" ]; then\n  TRACKER_JSON=\"$(plan-issue --repo \"$OWNER_REPO\" --format json record open \\\n    --profile tracking --bundle \"$PLAN_BUNDLE\" --title \"$TITLE\" \\\n    --label type::chore --label area::docs \\\n    --label state::needs-triage \\\n    \"${PLAN_LABEL_ARGS[@]}\")\"\n  ISSUE=\"$(printf '%s\\n' \"$TRACKER_JSON\" \\\n    | python3 -c 'import json,sys; print(json.load(sys.stdin)[\"payload\"][\"result\"][\"issue\"][\"number\"])')\"\n  ISSUE_URL=\"$(printf '%s\\n' \"$TRACKER_JSON\" \\\n    | python3 -c 'import json,sys; print(json.load(sys.stdin)[\"payload\"][\"result\"][\"issue\"][\"url\"])')\"\n\n  RUN_INIT_JSON=\"$(plan-issue --format json tracking run init \\\n    --provider-repo \"$OWNER_REPO\" --issue \"$ISSUE\" \\\n    --bundle \"$PLAN_BUNDLE\" \\\n    --execution-state-file \"$PLAN_BUNDLE\u002F$SLUG-execution-state.md\" \\\n    --branch \"$BRANCH\" \\\n    --now \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\")\"\n  RUN_STATE=\"$(printf '%s\\n' \"$RUN_INIT_JSON\" \\\n    | python3 -c 'import json,sys; print(json.load(sys.stdin)[\"payload\"][\"result\"][\"run_state_path\"])')\"\nelse\n  : \"${RUN_STATE:?RUN_STATE is required when ISSUE is supplied}\"\n  TRACKER_JSON=\"$(forge-cli --provider \"$PROVIDER\" --repo \"$OWNER_REPO\" --format json issue view \"$ISSUE\")\"\n  ISSUE_URL=\"$(printf '%s\\n' \"$TRACKER_JSON\" \\\n    | python3 -c 'import json,sys; print(json.load(sys.stdin)[\"data\"][\"url\"])')\"\nfi\n\nplan-issue --format json tracking status \\\n  --provider-repo \"$OWNER_REPO\" \\\n  --issue \"$ISSUE\" \\\n  --profile tracking \\\n  --run-state \"$RUN_STATE\" \\\n  --expect-visible\n\nplan-tooling ledger-update \\\n  --execution-state \"$PLAN_BUNDLE\u002F$SLUG-execution-state.md\" \\\n  --task \"$TASK_ID\" \\\n  --status done \\\n  --evidence \"$EVIDENCE\"\n\nplan-issue --format json tracking run update \\\n  --run-state \"$RUN_STATE\" \\\n  --phase validating \\\n  --validation-overall pass \\\n  --validation-command \"$VALIDATION_COMMAND\" \\\n  --validation-status pass \\\n  --validation-evidence \"$VALIDATION_LOG\" \\\n  --now \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"\n\nplan-issue --format json tracking checkpoint \\\n  --provider-repo \"$OWNER_REPO\" \\\n  --issue \"$ISSUE\" \\\n  --profile tracking \\\n  --run-state \"$RUN_STATE\" \\\n  --live \\\n  --post state,session,validation \\\n  --repair-dashboard\n\n# Deliver the PR without merging so the review gate has a window (adopt and\n# verify LINKED_PR through pr deliver existing-PR adoption when it already exists).\nforge-cli pr deliver --repo \"$OWNER_REPO\" \\\n  --kind feature --title \"$PR_TITLE\" \\\n  --head \"$BRANCH\" --base main \\\n  --body-file \"$PR_BODY_FILE\" \\\n  --test-first-evidence \"$EVIDENCE_DIR\" \\\n  --no-merge --format json\n\n# Shared read-only specialist gate (min testing + maintainability).\nreview-specialists scope --base \"$BASE_REF\" --testing --maintainability --format json\n\n# Native review events (GitHub) per REVIEW_OUTCOME_POSTING_CONTRACT.md: one\n# COMMENT per semantic lens as each lens returns, then the combined\n# APPROVE\u002FREQUEST_CHANGES outcome. The local head is the reviewed specialist\n# diff; forge-cli rejects the write if the provider head has drifted.\nEXPECTED_REVIEW_HEAD=\"$(git rev-parse HEAD)\"\nSUBMIT_REVIEW=()\n[ \"$PROVIDER\" = github ] &&\n  SUBMIT_REVIEW=(--submit-review --expected-head \"$EXPECTED_REVIEW_HEAD\")\nFINAL_SUBMIT_REVIEW=()\nREVIEW_CONVERGENCE_ARGS=()\n[ \"$PROVIDER\" = gitlab ] && REVIEW_CONVERGENCE_ARGS=(--review-convergence=false)\n\nSELECTED_REVIEW_LENSES=(testing maintainability)\n# Append every risk lens selected by the full pre-merge review.\nREVIEW_LENS_ARGS=()\nTRACKING_LENS_ARGS=()\nfor selected_lens in \"${SELECTED_REVIEW_LENSES[@]}\"; do\n  REVIEW_LENS_ARGS+=(--lens \"$selected_lens\")\n  TRACKING_LENS_ARGS+=(--review-lens \"$selected_lens\")\ndone\n\n# Repeat this specialist block once for each returned lens: testing,\n# maintainability, plus any risk lens selected by the full pre-merge review.\nTHREAD_FILE_ARGS=()\nif [ \"$PROVIDER\" = github ] && [ -n \"${REVIEW_THREAD_FILE:-}\" ]; then\n  THREAD_FILE_ARGS=(--thread-file \"$REVIEW_THREAD_FILE\")\nfi\nforge-cli --provider \"$PROVIDER\" pr review \"$PR_NUMBER\" \\\n  --repo \"$OWNER_REPO\" \\\n  --decision comments-only \\\n  \"${SUBMIT_REVIEW[@]}\" \\\n  \"${THREAD_FILE_ARGS[@]}\" \\\n  --comment-file \"$SPECIALIST_REVIEW_COMMENT_FILE\" \\\n  --lens \"$REVIEW_LENS\" \\\n  --issue \"$ISSUE\" --mirror-issue --format json\n\n# Read native review bodies after specialist posting and repair. Disposition\n# actionable current-head summaries before the combined owner outcome; stale\n# summaries are informational. When summary_truncated is true, retrieve the\n# full review body through provider read tooling and stop if it is unavailable.\nPRE_SUBMIT_PR=\"$(\n  forge-cli --provider \"$PROVIDER\" --repo \"$OWNER_REPO\" \\\n    --format json pr view \"$PR_NUMBER\"\n)\"\nEXPECTED_REVIEW_HEAD=\"$(\n  printf '%s\\n' \"$PRE_SUBMIT_PR\" |\n    jq -er 'select(.ok == true) | .data.head_sha'\n)\" || exit $?\nreadonly EXPECTED_REVIEW_HEAD\nif [ \"$PROVIDER\" = github ]; then\n  PRE_SUBMIT_REVIEWS=\"$(\n    forge-cli --provider \"$PROVIDER\" --repo \"$OWNER_REPO\" \\\n      --format json pr reviews \"$PR_NUMBER\"\n  )\"\n  printf '%s\\n' \"$PRE_SUBMIT_REVIEWS\"\n  printf '%s\\n' \"$PRE_SUBMIT_REVIEWS\" |\n    jq -e --arg head \"$EXPECTED_REVIEW_HEAD\" \\\n      '.ok == true and .data.head_sha == $head' >\u002Fdev\u002Fnull\nfi\n\n# Bind a routed combined native outcome to the provider head just inspected.\ncase \"${AGENT_RUNTIME_FORGE_IDENTITY_ROUTER_REQUIRED:-}\" in\n  1|[Tt][Rr][Uu][Ee]|[Yy][Ee][Ss])\n    [ \"$PROVIDER\" = github ] &&\n      FINAL_SUBMIT_REVIEW=(--submit-review --expected-head \"$EXPECTED_REVIEW_HEAD\")\n    ;;\nesac\n\n# Capture the outcome bytes once. Initial submission, guarded recovery, and\n# the single retry must all use this immutable value rather than rereading a\n# mutable file path. Preserve capture failures before freezing the value, and\n# use `--option=value` below so hyphen-leading Markdown remains one argv value.\nEXPECTED_REVIEW_BODY=\"$(cat \"$DELIVERY_REVIEW_OUTCOME\")\" || exit $?\nreadonly EXPECTED_REVIEW_BODY\nNATIVE_REVIEW_CMD=(\n  forge-cli --provider \"$PROVIDER\" --repo \"$OWNER_REPO\" --format json\n  pr review \"$PR_NUMBER\"\n  --decision \"$REVIEW_DECISION\"\n  \"${FINAL_SUBMIT_REVIEW[@]}\"\n  --comment=\"$EXPECTED_REVIEW_BODY\"\n  \"${REVIEW_LENS_ARGS[@]}\"\n  --issue \"$ISSUE\" --mirror-issue\n)\n# Clear stale selector state, then preserve the failed command status and JSON.\nunset PENDING_REVIEW_ID\nset +e\nNATIVE_REVIEW_JSON=\"$(\"${NATIVE_REVIEW_CMD[@]}\" 2>&1)\"\nNATIVE_REVIEW_STATUS=$?\nset -e\n\nif [ \"$NATIVE_REVIEW_STATUS\" -ne 0 ]; then\n  if [ \"$PROVIDER\" != github ] || ! printf '%s\\n' \"$NATIVE_REVIEW_JSON\" |\n    jq -e '.ok == false and .error.code == \"github_pending_review_exists\"' \\\n      >\u002Fdev\u002Fnull; then\n    printf '%s\\n' \"$NATIVE_REVIEW_JSON\" >&2\n    exit \"$NATIVE_REVIEW_STATUS\"\n  fi\n\n  # Fetch a fresh post-conflict pr reviews snapshot.\n  if [ \"$PROVIDER\" = github ]; then\n    POST_CONFLICT_REVIEWS=\"$(\n      forge-cli --provider \"$PROVIDER\" --repo \"$OWNER_REPO\" \\\n        --format json pr reviews \"$PR_NUMBER\"\n    )\"\n    PENDING_REVIEW_ID=\"$(\n      printf '%s\\n' \"$POST_CONFLICT_REVIEWS\" |\n        jq -er --arg head \"$EXPECTED_REVIEW_HEAD\" \\\n          --arg body \"$EXPECTED_REVIEW_BODY\" '\n            select(.ok == true and .data.head_sha == $head)\n            | [.data.pending_reviews[]\n                | select(.state == \"PENDING\")\n                | select(.commit_sha == $head)\n                | select(.summary_truncated == false)\n                | select((.summary | rtrimstr(\"\\n\")) == ($body | rtrimstr(\"\\n\")))]\n            | select(length == 1)\n            | .[0].id\n          '\n    )\"\n    if [ -n \"${PENDING_REVIEW_ID:-}\" ]; then\n      DELETE_REVIEW_JSON=\"$(\n        forge-cli --provider \"$PROVIDER\" --repo \"$OWNER_REPO\" \\\n          --format json pr pending-review delete \"$PR_NUMBER\" \\\n          --review \"$PENDING_REVIEW_ID\" \\\n          --expected-head \"$EXPECTED_REVIEW_HEAD\" \\\n          --expected-commit \"$EXPECTED_REVIEW_HEAD\" \\\n          --expected-body=\"$EXPECTED_REVIEW_BODY\" \\\n          --confirm-abandoned\n      )\"\n      POST_DELETE_REVIEWS=\"$(\n        forge-cli --provider \"$PROVIDER\" --repo \"$OWNER_REPO\" \\\n          --format json pr reviews \"$PR_NUMBER\"\n      )\"\n      printf '%s\\n' \"$POST_DELETE_REVIEWS\" |\n        jq -e --arg head \"$EXPECTED_REVIEW_HEAD\" \\\n          --arg id \"$PENDING_REVIEW_ID\" '\n            .ok == true\n            and .data.head_sha == $head\n            and (.data.pending_reviews | map(.id) | index($id) | not)\n          ' >\u002Fdev\u002Fnull\n\n      set +e\n      NATIVE_REVIEW_RETRY_JSON=\"$(\"${NATIVE_REVIEW_CMD[@]}\" 2>&1)\"\n      NATIVE_REVIEW_RETRY_STATUS=$?\n      set -e\n      if [ \"$NATIVE_REVIEW_RETRY_STATUS\" -ne 0 ]; then\n        printf '%s\\n' \"$NATIVE_REVIEW_RETRY_JSON\" >&2\n        exit \"$NATIVE_REVIEW_RETRY_STATUS\"\n      fi\n      NATIVE_REVIEW_JSON=\"$NATIVE_REVIEW_RETRY_JSON\"\n    fi\n  fi\nfi\n\nprintf '%s\\n' \"$NATIVE_REVIEW_JSON\"\nREVIEW_OUTCOME_COMMENT=\"$(\n  printf '%s\\n' \"$NATIVE_REVIEW_JSON\" | jq -er '.data.pr_comment_url'\n)\"\n# Record issue-side review evidence from the native outcome, then post the final\n# state + review checkpoint before merging.\nplan-issue --format json tracking run update \\\n  --run-state \"$RUN_STATE\" \\\n  --phase ready-for-close \\\n  --linked-pr \"$OWNER_REPO#$PR_NUMBER\" \\\n  --review-decision approve \\\n  \"${TRACKING_LENS_ARGS[@]}\" \\\n  --review-outcome-comment \"$REVIEW_OUTCOME_COMMENT\" \\\n  --now \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"\n\nplan-issue --format json tracking checkpoint \\\n  --provider-repo \"$OWNER_REPO\" \\\n  --issue \"$ISSUE\" \\\n  --profile tracking \\\n  --run-state \"$RUN_STATE\" \\\n  --live \\\n  --post state,review \\\n  --repair-dashboard\n\n# Merge only after semantic disposition and the review checkpoint pass. The\n# CLI owns observed quiet timing, native change requests, thread\u002Ftask gates,\n# and provider-head binding. Reuse the inspected\u002Freviewed provider head so a\n# later push cannot enter the merge.\nforge-cli --provider \"$PROVIDER\" pr ready \"$PR_NUMBER\"\nforge-cli --provider \"$PROVIDER\" pr merge \"$PR_NUMBER\" --method squash \\\n  --expected-head \"$EXPECTED_REVIEW_HEAD\" \\\n  \"${REVIEW_CONVERGENCE_ARGS[@]}\"\n\nplan-issue --format json tracking close-ready \\\n  --provider-repo \"$OWNER_REPO\" \\\n  --issue \"$ISSUE\" \\\n  --profile tracking \\\n  --run-state \"$RUN_STATE\" \\\n  --linked-pr \"$OWNER_REPO#$PR_NUMBER\" \\\n  --approval \"$APPROVAL\" \\\n  --expect-visible\n\n# Only after close-ready reports ready=true and blockers=[].\nplan-issue --repo \"$OWNER_REPO\" --format json record close \\\n  --profile tracking --issue \"$ISSUE\" --bundle \"$PLAN_BUNDLE\" \\\n  --linked-pr \"$OWNER_REPO#$PR_NUMBER\" --approval \"$APPROVAL\" \\\n  --add-label state::closed --remove-label state::needs-triage\n\n# Read back the closed provider issue body and comments, then require visible\n# closeout evidence before archive maintenance.\nforge-cli --provider \"$PROVIDER\" --repo \"$OWNER_REPO\" --format json issue view \"$ISSUE\" --with-comments \\\n  >\"$CLOSED_ISSUE_VIEW_JSON\"\njq '{body:.data.body, comments:(.data.comments \u002F\u002F [])}' \\\n  \"$CLOSED_ISSUE_VIEW_JSON\" >\"$CLOSED_ISSUE_JSON\"\njq -r .body \"$CLOSED_ISSUE_JSON\" >\"$CLOSED_ISSUE_BODY\"\n\nplan-issue --repo \"$OWNER_REPO\" --format json record audit \\\n  --profile tracking \\\n  --body-file \"$CLOSED_ISSUE_BODY\" \\\n  --comments-json \"$CLOSED_ISSUE_JSON\" \\\n  --expect-visible\n\nplan-archive discover --source-repo \"$PWD\" --format json\nplan-archive migrate --plan \"$PLAN_BUNDLE\" --issue \"$ISSUE_URL\" --format json\n```\n\nWhen the caller supplies an ordinary provider issue that has not yet received\ntracking lifecycle records, do not enter the resume branch yet. Read the issue\nand audit its comments first. After confirming that the source, plan, and state\nroles are absent, run `record attach --profile tracking` exactly once,\ninitialize its run state, and then resume with the resulting `RUN_STATE`. Never\nattach to an issue that already carries those roles, because attachment posts a\nnew lifecycle set rather than resuming the existing tracker.\n\n`forge-cli pr deliver --no-merge` creates or adopts the draft and completes its\ncheck wait without merging, leaving the window for review. Inspect native\nsummaries and post the owner outcome before the issue-side `review` checkpoint;\nthen mark the PR ready and call `forge-cli pr merge`. The merge primitive owns\nthe observed quiet window, complete\u002Ffinal native-review reads, native change\nrequests, thread\u002Ftask gates, and provider-head binding. When `LINKED_PR` already\nexists, adopt and verify it through `pr deliver` existing-PR adoption instead of\nre-creating it, and record the ref with `tracking run update --linked-pr`.\nObserved convergence is GitHub-only in v1, so GitLab merge calls explicitly pass\n`--review-convergence=false` to neutralize any user-global GitHub policy.\n\nPost one compact specialist review comment per lens as it returns — before any\nrepair — using `--decision comments-only` plus the semantic `--lens`, with\n`--thread-file \"$REVIEW_THREAD_FILE\"` for actionable GitHub findings; the\ncombined delivery outcome posts last with the final decision and selected lenses.\nOn GitHub, read native summaries before the combined outcome; on GitLab, retain\nthe outcome-note path and do not invoke the unsupported snapshot. A\n`summary_truncated` item requires the full review body before disposition; stop\nif it cannot be read. If native submission returns\n`github_pending_review_exists`, preserve the failed command status and JSON and\nfetch a fresh post-conflict snapshot.\nThe command binds the native review to the inspected head with\n`--expected-head`. Choose a recovery id only when\n`data.pending_reviews[]` identifies exactly one current-viewer abandoned node\nfor this PR and the intended body, decision, and head remain current. Run `pr\npending-review delete`, refresh `pr reviews`, and retry the unchanged outcome\nonce; stop on an ambiguous node, a failed guard, or a second rejection. The generic review\noutcome owns the read-only lenses and\nmode selection; this\nskill owns the provider writes, semantic disposition,\ncheckpoint, and merge, and reviewer subagents never post. On\n`review_convergence_activity_changed`, read `forge-cli pr reviews` again,\ndisposition the new evidence, refresh the final outcome\u002Fcheckpoint, and retry.\nFor `unresolved_review_threads` or `unchecked_task_items`, call the matching\n`pr review-threads list` or `pr tasks` read surface, disposition the returned\nitems, and retry. Outdated unresolved threads are auto-dispositioned `stale` by\n`pr merge` (`data.stale_thread_dispositions`) and do not block, so only\nnon-outdated threads need disposition; the `--allow-unresolved-threads` bypass\nnow requires a paired `--allow-unresolved-threads-reason` (recorded as\n`data.unresolved_threads_override_reason`). Do not duplicate quiet-period polling\nin skill prose.\n\nPlan-tracking PRs are `--kind feature` records, so when the test-first gate is\nenabled (`[test_first].require = true` in a repo `.forge-cli.toml` or the\nuser-global `${XDG_CONFIG_HOME:-~\u002F.config}\u002Fforge-cli\u002Fconfig.toml`) the deliver\nabove requires `--test-first-evidence \"$EVIDENCE_DIR\"` — the `verify`-clean\ndirectory the policy-owned `test-first-evidence` CLI flow produces — or it fails closed with\n`test_first_evidence_required`.\n\n## Workflow\n\n1. **Open \u002F preflight** — validate the bundle. Open or attach the tracker and\n   initialize run state when absent; otherwise run `tracking status\n   --expect-visible`. Stop on stale, blocked, or non-visible evidence.\n2. **Implementation \u002F validation** — do local work, update the task ledger\n   after every task transition, and checkpoint only changed roles.\n3. **PR branch** — deliver with `forge-cli pr deliver --no-merge` (or adopt and\n   verify `LINKED_PR` through `pr deliver` existing-PR adoption). Do not merge\n   yet; the review gate runs first.\n4. **Review gate** — run the generic code-review outcome in pre-merge context with the full profile (min `testing` +\n   `maintainability`; add risk lenses per scope). Post each lens's specialist\n   review comment through `forge-cli pr review` as it returns (native `COMMENT`\n   on GitHub via `--submit-review`, semantic `--lens`; `--thread-file`\n   for actionable findings). After repairs, read `forge-cli pr reviews` and\n   disposition every actionable current-head summary; stale summaries are\n   informational. Then post the combined delivery outcome (native GitHub\n   approval only with the independent-identity capability; repeated selected\n   lenses; `--mirror-issue`), per\n   `REVIEW_OUTCOME_POSTING_CONTRACT.md`. Every tracking PR runs the full gate —\n   there is no single-author self-review shortcut. Repair concrete findings in\n   this delivery branch and rerun affected lenses before continuing. A pending\n   native draft uses only the exact-node recovery above; never delete an\n   ambiguous draft or replace the requested native outcome with a note.\n5. **Review + final checkpoint** — set `phase=ready-for-close`, record the linked\n   PR, review decision, lenses, and `--review-outcome-comment` (the provider\n   outcome URL); add `--review-findings-file \"$REVIEW_FINDINGS_JSON\"` when findings\n   exist; then post `state,review` in one live checkpoint. This issue-side\n   `review` evidence is posted before merge.\n6. **Merge** — mark the PR ready, then call `forge-cli pr merge` once semantic\n   review and the issue-side checkpoint pass. Let the CLI enforce convergence,\n   native state, threads, tasks, and head binding. On a typed failure, read and\n   disposition the matching evidence; `review_convergence_activity_changed`\n   requires a refreshed owner outcome\u002Fcheckpoint before retry.\n   `review_convergence_head_changed` requires rebinding delivery evidence to\n   the new head, then re-run validation and affected review lenses, read the\n   current-head summaries, post a new owner outcome, and refresh the\n   validation\u002Freview checkpoint before retry.\n7. **Close-ready \u002F closeout** — run `tracking close-ready --expect-visible`.\n   Stop on every blocker. On `ready: true`, write the closing summary, perform\n   only controller-authorized final-role\u002Fdashboard repair, and call `record\n   close --profile tracking` with linked PR and approval evidence.\n8. **Closeout read-back** — fetch the closed provider issue with comments and\n   run `record audit --profile tracking --expect-visible`; stop unless the\n   closeout role is visible and lint-clean.\n9. **Archive maintenance** — only after closeout read-back succeeds, run\n    `plan-archive discover`, then the default dry-run `plan-archive migrate`;\n    apply only\n    after explicit confirmation and a clean plan.\n10. **Terminal local cleanup** — after archive and every plan-required\n    post-merge deployment, activation, evidence, or local closeout duty, recheck\n    provider merge\u002Fhead truth and local status. Restore a clean primary checkout\n    to base, or run `git-cli worktree remove \u003Cpath-or-slug> --format json` from\n    the primary checkout through the supported hooked shell; the target-aware\n    lease guard must confirm no live foreign owner before removal. If that proof\n    or hook is unavailable, retain the worktree. Delete the local\n    branch only when its tip equals the provider-confirmed delivered head,\n    including after squash merge. Retain and report dirty, locked, missing, or\n    unverifiable state.\n\n## Boundary\n\nOwns:\n\n- Delivery-scope judgement, validation strength, review-gate orchestration and\n  the provider review writes (per-lens specialist comments + the combined native\n  outcome), native-summary disposition, typed merge-failure repair, final\n  state\u002Freview checkpoint timing, the merge, strict closeout, read-back, and\n  archive routing.\n- Plan-required post-merge duties and exactly-once terminal local cleanup after\n  strict provider closeout\u002Fread-back.\n\nMust not:\n\n- Use dispatch-profile semantics, let reviewer subagents post provider comments,\n  close with any blocker, archive before close read-back, or merge before the\n  review gate and `review` checkpoint complete.\n\nInternal phases:\n\n- Open, execution, delivery, independent review, closeout, and archive phases\n  follow `references\u002Foutcome-routing.md`; they are not separate user\n  choices.\n",{"name":5,"description":7},"main","da7119f2ebece510d6955cea72743069f5496c73","tests\u002Fgolden\u002Fhermes\u002Fplugins\u002Fdispatch\u002Fskills\u002Fdeliver-plan-tracking-issue\u002Fexpected","https:\u002F\u002Fgithub.com\u002Fgraysurf\u002Fagent-runtime-kit","https:\u002F\u002Fgithub.com\u002Fgraysurf","Building reliable tools for teams of AI coding agents · Rust \u002F TypeScript · @sympoies","2026-08-29 05:27:47",{"source":8,"skillName":5,"commands":31,"prompt":41,"zipAvailable":42},[32,35,38],{"tool":33,"command":34},"npx","npx skills add graysurf\u002Fagent-runtime-kit --skill deliver-plan-tracking-issue",{"tool":36,"command":37},"bunx","bunx skills add graysurf\u002Fagent-runtime-kit --skill deliver-plan-tracking-issue",{"tool":39,"command":40},"pnpm","pnpm dlx skills add graysurf\u002Fagent-runtime-kit --skill deliver-plan-tracking-issue","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fgraysurf\u002Fagent-runtime-kit\u002Fblob\u002Fmain\u002Ftests\u002Fgolden\u002Fhermes\u002Fplugins\u002Fdispatch\u002Fskills\u002Fdeliver-plan-tracking-issue\u002Fexpected\u002FSKILL.md",true,[44],{"path":45,"resourceType":46,"resourceTypeDesc":47,"sizeBytes":48,"sourceHtmlUrl":49},"references\u002Foutcome-routing.md","REFERENCE","参考文档",3422,"https:\u002F\u002Fgithub.com\u002Fgraysurf\u002Fagent-runtime-kit\u002Fblob\u002Fmain\u002Ftests\u002Fgolden\u002Fhermes\u002Fplugins\u002Fdispatch\u002Fskills\u002Fdeliver-plan-tracking-issue\u002Fexpected\u002Freferences\u002Foutcome-routing.md",[51,57,62,69,76,83],{"skillNo":52,"name":53,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":54,"categories":55,"keywords":56,"publishedAt":18},"01M736XWK14DFRERMQ8RT3HS0Z","removable-skill","https:\u002F\u002Fgithub.com\u002Fgraysurf\u002Fagent-runtime-kit\u002Fblob\u002Fmain\u002Ftests\u002Fruntime-smoke\u002Ffixtures\u002Fskill-lifecycle\u002Fremove-skill\u002Ftests\u002Fgolden\u002Fcodex\u002Fplugins\u002Ffixture\u002Fskills\u002Fremovable-skill\u002FSKILL.md",[],[],{"skillNo":58,"name":53,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":59,"categories":60,"keywords":61,"publishedAt":18},"01M736XTPQEKAYESDM1REN2KAN","https:\u002F\u002Fgithub.com\u002Fgraysurf\u002Fagent-runtime-kit\u002Fblob\u002Fmain\u002Ftests\u002Fruntime-smoke\u002Ffixtures\u002Fskill-lifecycle\u002Fremove-skill\u002Ftests\u002Fgolden\u002Fclaude\u002Fplugins\u002Ffixture\u002Fskills\u002Fremovable-skill\u002FSKILL.md",[],[],{"skillNo":63,"name":64,"nameZh":6,"description":65,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":66,"categories":67,"keywords":68,"publishedAt":18},"01M736XRMWHMJB4X563G9J6QYY","removable-project-skill","Fixture project-local skill used to prove remove-project-skill dry-run coverage.","https:\u002F\u002Fgithub.com\u002Fgraysurf\u002Fagent-runtime-kit\u002Fblob\u002Fmain\u002Ftests\u002Fruntime-smoke\u002Ffixtures\u002Fskill-lifecycle\u002Fremove-project-skill\u002F.agents\u002Fskills\u002Fremovable-project-skill\u002FSKILL.md",[],[],{"skillNo":70,"name":71,"nameZh":6,"description":72,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":73,"categories":74,"keywords":75,"publishedAt":18},"01M736XPT65YZMPCBD4K3RHV4P","project-sample-skill","Fixture project-local skill used to prove create-project-skill governance coverage.","https:\u002F\u002Fgithub.com\u002Fgraysurf\u002Fagent-runtime-kit\u002Fblob\u002Fmain\u002Ftests\u002Fruntime-smoke\u002Ffixtures\u002Fskill-lifecycle\u002Fcreate-project-skill\u002F.agents\u002Fskills\u002Fproject-sample-skill\u002FSKILL.md",[],[],{"skillNo":77,"name":78,"nameZh":6,"description":79,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":80,"categories":81,"keywords":82,"publishedAt":18},"01M736XKZVYWVQA1YB0P459WND","project-local-skill","Fixture project-local skill used by runtime-kit project-local smoke checks.","https:\u002F\u002Fgithub.com\u002Fgraysurf\u002Fagent-runtime-kit\u002Fblob\u002Fmain\u002Ftests\u002Fprojects\u002Fproject-local-smoke\u002F.agents\u002Fskills\u002Fproject-local-skill\u002FSKILL.md",[],[],{"skillNo":84,"name":85,"nameZh":6,"description":86,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":87,"categories":88,"keywords":89,"publishedAt":18},"01M736XHA73KZ5G2TKWSED5P1B","topic-radar","Aggregate read-only AI and technology trend signals (Polymarket, Hacker News, GitHub, arXiv, Hugging Face, news search) into source-grounded Markdown or JSON; the lower-level data engine behind `daily-brief`.","https:\u002F\u002Fgithub.com\u002Fgraysurf\u002Fagent-runtime-kit\u002Fblob\u002Fmain\u002Ftests\u002Fgolden\u002Fhermes\u002Fplugins\u002Freporting\u002Fskills\u002Ftopic-radar\u002Fexpected\u002FSKILL.md",[],[]]