Skip to content

Draft companion PRs for citations outside knowledge/ before a retirement lands - #221

Merged
tzhouam merged 1 commit into
mainfrom
kb/companion-prs
Sep 28, 2026
Merged

tzhouam merged 1 commit into
mainfrom
kb/companion-prs

Conversation

@tzhouam

@tzhouam tzhouam commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator

Knowledge-service redesign follow-up (design §7.5): when a knowledge change retires, replaces or purges rules still cited outside knowledge/, the service drafts the companion PR that updates those citations. The change waits, with its rules still active, and resumes once the companion merges. Before this, such changes just went to people.

  • Drafting: companion.stage_companion runs when the gate's only problem is external citations.
    • The citing files are rewritten: a replaced ID becomes its replacement; a list or table entry for a retired rule is dropped; other mentions lose the ID, with indentation kept so YAML stays valid.
    • Only the companion whitelist is touched.
    • The knowledge change waits as companion_pending.
  • Publishing: the companion is a draft labelled kb:companion via open_companion_pr, and goes into the human queue.
    • The publisher refuses paths outside the whitelist, and refuses post_verdict or enqueue on a companion. It recognizes companions by branch as well as label, so this fails closed if the label didn't apply.
    • A staged but unpublished companion is recovered by the scheduler.
  • Merge: once the companion merges, the waiting change is rebuilt on current main and published.
    • The companion is marked merged only after that succeeds (a failed fetch retries); the rebuild waits while paused.
    • The companion's for_changeset is the source of truth for the link.
  • Close: a companion closed unmerged sends the change to people, and doesn't count as an overturn.

Commit hook approved; full suite and SPEC freshness pass locally.

🤖 Generated with Claude Code

…ent lands

When a knowledge change retires, replaces or purges rules that files outside
knowledge/ still cite, the design has the service draft a companion PR
that updates those citations. The knowledge change waits (its rules stay
active, so nothing ever cites a retired rule) and resumes automatically once
the companion merges. Until now such changes just went to people.

- companion.stage_companion runs when the gate's only problem is external
  citations (not for held sweep change sets or forced-human ones). Each
  citing file is rewritten: a replaced rule's ID becomes its replacement; a
  list or table entry citing a retired rule is dropped; any other mention
  loses the ID (indentation kept, so nested YAML stays valid). Only the
  companion whitelist (skills, plugins, adapters,
  doc, playbooks) is touched. The knowledge change set waits as
  companion_pending.
- The companion goes out through open_companion_pr as a draft labelled
  kb:companion, and into the human queue. The publisher refuses any path
  outside the companion whitelist (knowledge/, .github/, src/, tools/) and
  refuses post_verdict or enqueue on a companion, so only people can ready
  and merge it. Companions are recognized by their branch as well as the
  label, so a label that failed to apply cannot open that door (fail closed).
  A companion staged but not handed over (a crash) is published by the
  scheduler's recovery pass.
- The scheduler follows the companion. On merge it rebuilds the waiting
  change on current main (the citations are gone, so it passes the gate and
  is published; a change set that never had a PR is superseded directly).
  The companion is marked merged only once every waiting change was
  handled, so a failed fetch or a crash retries the rebuild next pass. The
  rebuild waits while the repository (or everything) is paused. The change a
  companion belongs to comes from the companion itself (for_changeset), so a
  crash between staging the companion and linking the change still rebuilds
  it on merge.
  If the companion is closed unmerged, the change goes to people. Companion
  closures do not count toward the overturn breaker.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-28T17:30:52.705123Z 85b6bbd PR opened
ℹ️ About Codex in GitHub

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

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

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@tzhouam
tzhouam merged commit 33b26a5 into main Sep 28, 2026
5 checks passed

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 85b6bbd962

ℹ️ About Codex in GitHub

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

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

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

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

Comment on lines +71 to +73
rt.ledger.update_changeset(changeset_id, status="companion_pending",
detail={**waiting["detail"], "companion": companion_id})
publish_companion(rt, lifecycle, companion_id)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep parents actionable when companion publication fails

The parent is moved to companion_pending before publication is known to be possible. In the default shadow mode, a private/non-publishing repository, or a deployment without an outbox, publish_companion immediately makes the companion shadow_recorded; a rejected open_companion_pr acknowledgment similarly makes it failed. Neither terminal state is revisited by the scheduler or merge.advance, so the original knowledge change remains companion_pending forever. Avoid staging the companion in non-publishing modes or restore the parent to human whenever its companion cannot be opened.

Useful? React with 👍 / 👎.

Comment on lines +37 to +38
if line.lstrip().startswith(("- ", "* ", "|")):
continue # a list or table entry about the retired rule

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve mixed list and table entries

When a cited ID occurs anywhere in a Markdown bullet or table row, this deletes the entire line. The scanned skills/, doc/, and other files contain arbitrary prose, so an entry such as - Check DEMO-1a and retain the rollback procedure loses the unrelated instruction when only DEMO-1a is retired; rows mentioning multiple rules have the same problem. Only drop entries proven to represent that rule alone, and otherwise remove just the token.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant