Problem
Since 2026-10-07 every RFC lives in the RFCs product and is kept current through its API as the work happens. Agents do most of that work. Writing to an RFC through the API today means one of four things: save the whole text again, set the status, add a comment, or ask for a review. Everything else an agent learns while building lands in prose or nowhere:
- Which pull requests implement an RFC. The interim rule is one comment per pull request, written by hand, then edited by hand when it merges and when it goes live. RFC 0041 designed the list built from events; it was never built.
- What runs where. A roll records the commit each deployment runs, in the deployment itself, and keeps no history. Nothing connects "rolled at this commit" to "this RFC's pull request is in it".
- The owner's decisions. On 2026-10-07 the marketplace share and the VAT gate were decided in a chat, relayed by an agent, and exist only as a sentence in a status log.
- Waiting. Two pull requests (NDA templates and billing seats) waited a day on a CI fix in a third. Nothing on either RFC showed it.
- Defects found while building. A database upgrade broke the request log of RFC 0038; the defect, its fix and when the fix went live are in the board's notes, not on the RFC.
- Review findings. A review with one blocking finding and nine follow-ups exists on the pull request only; the RFC part it belongs to cannot say what must land first.
- Where a document stands. An RFC is open, decided or superseded. Nothing says "being built", "partly live" or "abandoned"; the owner asked for exactly these.
The agents working on the platform listed what they miss on the team board on 2026-10-07. This RFC designs each wish on that list, says which ones wait and why, and orders the work into slices.
Proposal
The shape: facts on a document, written by whoever saw them
Everything below follows one pattern. A fact is a typed record that belongs to one document (an RFC or one of its parts): an implementation, a roll, a decision, a block, an issue, a proof. Facts are written through the RFCs API by the person, agent or service that observed them, never inferred from prose, and never by a model's account of its own work. The text stays the place for argument; facts are the place for what happened.
Rules every fact shares:
- Access. A fact is read through the same function that decides every read of its
document (RFC 0065): a caller who cannot read the document gets
NOT_FOUNDfor its facts too. A fact may carry its ownlevel, never below its document's; a security finding on a public RFC sits atinternal. Free text on a fact (a question, a defect's title) goes through the classified cut like document text, and a fact atpublicruns the redaction and strict rules when it is written; a finding refuses it with rule ids and lines. - Who wrote it. Every fact records its author's subject: a person, an agent's machine
identity, or a service (
svc:connectionsfor what the GitHub App reports). An agent's writes are labelled as an agent's on every surface. - History. Facts are append-only in effect: a change is a new state with who and when; nothing is deleted except by erasure of a subject.
- Timeline. Each state change of a fact is a timeline entry beside the status log's
lines (
ListTimelinegains asourcefield:status_log,implementation,roll,decision,block,issue,stage), so an RFC reads as a live record without a version being saved. - Events. Each change publishes an event with ids only (RFC 0022), so webhooks and the event stream carry it.
- Audit. One audit line per write: who, the account, the document and fact ids, the outcome. Never a title, a question or a body.
1. Implementations, fed by the GitHub App
The list RFC 0041 proposed, now concrete. Per document: one row per pull request that implements it.
| Field | Meaning |
|---|---|
repo |
owner/name as GitHub has it |
number |
the pull request's number |
title |
its title, as of the last event |
state |
open, draft, closed (unmerged) or merged |
merged_at, merge_commit |
when it merged and the commit it merged as |
commits |
how many commits the pull request had |
source |
trailer (an Implements: line), manual (linked through the API), backfill |
live |
per deployment: the commit it runs and when that roll finished (section 6) |
private |
the repository is private |
The link. A pull request implements a document when its description carries a line
Implements: RFC 0041
Implements: RFC 0040.1
one per document, matched as a whole line: Implements:, RFC, four digits, an optional
.N for a part. A mention anywhere else links nothing (RFC 0041's rule). The number is
resolved in the account the App's installation belongs to, across its spaces; a number
that names no document, or more than one, records nothing for that line and is reported
on the pull request's row of the installation's delivery log. Editing the description
adds and removes links; a removed link stays in the history with removed_at.
The source. The InOrbit Agent GitHub App (RFC 0077) is already installed on our
organization and already sends pull_request events to the connections service's GitHub
receiver path, which RFC 0077's second slice also builds. One receiver, two readers:
- The connections service verifies the delivery's
X-Hub-Signature-256(HMAC-SHA256 with the App's webhook secret, compared in constant time) before reading anything, drops a delivery whoseX-GitHub-Deliveryid it has already seen, and maps the installation to exactly one account. - It keeps the metadata above and the link lines, never the description itself, a diff or a file.
- It hands
Implements:lines to the labs service (RecordPullRequest) and RFC 0077'sFixes:,Mitigates:andCloses:lines to the incidents service.
The labs service upserts the pull request by account, repository and number, ignores an event older than the state it holds (deliveries can arrive out of order), and updates the links.
How a pull request reaches the RFC view, with the rolls of section 6:
A diagram is drawn here in the RFCs product; this page does not show diagrams yet.
Backfill. GitHub does not redeliver a failed delivery by itself
(GitHub).
A backfill reads the installation's pull requests through the App (closed and open, newest
first, until a given date) and records them with source: backfill; the same call, run
daily, repairs anything a lost delivery left behind. It replaces the "one comment per
pull request" rule: once the list exists, those comments are no longer asked for, and the
existing ones stay as comments.
Cross-repository. One document may be implemented across several repositories of the
account (RFC 0061 spans four). Rows are grouped by repository. A row from a private
repository shows its title and link only to readers at team or above; below that it is
counted ("2 pull requests in a private repository"), as RFC 0041's public table says.
Manual links. LinkPullRequest links a pull request by repository and number for a
repository the App is not installed on. The row says manual and its state is refreshed
only if the App later sees the repository.
2. The iohr rfc command line and the agent identity
Built by core-c7, not redefined here: iohr rfc (list, show, create, save, status,
comment, link-pr, review) over the SDK's RFCs group, and an agent identity: a machine
principal minted per session through the identity stack, holding rfc:write on the
Engineering account's spaces only, never a person's token. This RFC adds commands in the
same shape for each fact as its slice lands (iohr rfc impl, log, stage, ask,
answer, block, issue, rolls, check, diff, changes), generated from the same
OpenAPI document, and names the agent identity as the author of agents' facts.
3. Owner decisions as records
A decision is a question on a document with its options, then the answer.
AskDecision: the question (1 to 2000 characters), 2 to 10 options (each a key and a label), an optional heading anchor, who should answer (default: the document's owner), and an optional due date.AnswerDecision: the option chosen, an optional note, andrelayed_bywhen someone other than the answerer enters it (an agent relaying what the owner said in a chat). The answer records the answerer's subject, the relayer's, the date and the channel (console,app,api,relayed). A relayed answer is shown as relayed until the answerer confirms it in the console or the app.- An answered decision is never edited; a change of mind is a new decision that names the one it replaces.
- The reading view lists open decisions at the top and answered ones under the Decision section; the timeline shows both. Each answer can be quoted into the status log with one call (section 8).
This replaces RFC 0041's ## Open questions checklist in the text for every document
that uses the API.
4. Blocked by
A block says that something on a document waits on something else.
- The blocked side: a document or part, or one of its implementing pull requests.
- The blocker: a pull request (
repo#number, until merged), a CI run (a workflow run or check suite of a pull request's head, until it concludes successfully), a roll (a deployment at or past a commit, until recorded), or another document (until its stage reaches a given value). - Both sides show it: the blocked document lists what it waits on; the blocking pull request's row, on any document it implements, lists what waits on it.
- A block clears itself when its blocker reaches the condition, from the same events that feed sections 1 and 6, and the timeline says so with the time. A person or agent can also clear it by hand with a reason.
Decisions (section 3) and blocks move through these states:
A diagram is drawn here in the RFCs product; this page does not show diagrams yet.
CI runs need the App to receive workflow_run or check_suite events, which need read
access to Actions or Checks
(GitHub). The App has
neither today; the owner adds them and accepts the change on our installation before that
part ships. Pull request and roll blockers do not need it.
5. Issues: defects and review findings
An issue is something found while building a document that has to be fixed.
kind:defect(something broke, in production or in CI) orfinding(from a review).- A title (1 to 200 characters),
blocking(true or false),severityfor defects, andlevel: a security issue is at leastteam, and a vulnerability that is not fixed is alwaysinternal(the CRA rule: never published before the fix). - The fix: one or more pull requests. An issue closes when its fixing pull request merges;
its "fixed live" time comes from the rolls (section 6). It can also be closed by hand as
wont_fixwith a reason. - A finding may name the pull request it was found on and the part it blocks; a part with
an open blocking finding cannot move to stage
live(section 8).
6. Rolls: what runs which RFC's pull requests
Every roll of the platform already ends by recording the commit a deployment runs. It starts recording a roll in the RFCs product as well:
RecordRoll: the deployment, the commit, the commit it replaced, who rolled, when it started and finished, the outcome, and the commits between the two: for each, its sha, the pull request number a squash merge names in its subject, and the deployments that commit affects, computed by the same map CI uses to decide what a change can reach.- A pull request is live in a deployment when a recorded roll of that deployment carries its merge commit, and live when every deployment its merge commit affects has such a roll. A commit that affects no deployment (a document, a test) is shown as "nothing to roll".
- The document shows, per pull request, each deployment, the commit it runs and since when; the space shows rolls newest first.
Rolls are recorded for InOrbit's own accounts only, by the platform's operators and the roll tasks. A customer's deploy events (RFC 0077, "live") come later through the App's deployment events and the same record.
7. Releases as proof
A part can be shipped in a release: repository, tag, the digests of its signed
artifacts, and the result of verifying their attestations (passed, failed, not checked),
recorded by the release workflow with the agent identity. A failed release stays on the
record next to the one that shipped. GitHub's own release event needs read access to
repository contents, which the App does not ask for (RFC 0077: no code), so the release
workflow writes the record instead of the App.
8. Stage, status-log lines and handovers
- Stage. Beside the decision status, a
stage:proposed,building,in_review,partly_live,live,abandoned. Set bySetStagewith a reason, which also appends a status-log line.partly_liveandliveare refused unless the implementations support them (at least one, or all, of the merged pull requests live) and no blocking issue is open. Decided and live reads as completed. The console's home shows stages on its phase bars and filters by them. - Status-log append.
AppendStatus: a date (default today, in UTC) and a line. The service inserts the bullet at the end of the document's status log and saves a version on top of the current one, so an agent adds a line without sending the whole text and without a stale-save conflict. The line passes the same checks as a save. - Handovers. A change of a part's implementer (RFC 0041's people) takes a reason; the history shows from whom, to whom, when and why.
9. Check without saving, and reading as a level
CheckDocument: a text and a level; the answer is the findings of the document checks, the classified-marker parser and, forpublic, the redaction and strict rules on the public cut, by rule id and line. Nothing is saved.GetDocumentwithas_level(managers of the space only): the document, its versions, comments, facts and timeline exactly as a reader at that level gets them, so a classified cut is verified before a document is opened. Audited with the level.
10. The owner's review, where the owner is
RequestReview already records a pending review. When the reviewer has the app
(RFC 0074), the request also arrives as a notification with the document's title and its
open decisions, and the reviewer answers a decision, approves or asks for changes from the
phone. The notification carries ids and the title only at the reader's level; it never
pages (paging stays for incidents).
11. The generic wishes
| Wish | Design |
|---|---|
| Status-log append without a full save | Section 8, AppendStatus. |
| A number chosen at creation | CreateDocument takes the next free number in the space. Numbers are claimed on the team board before a document exists, and in our own accounts they run across spaces. CreateDocument gains an optional number for InOrbit's own accounts (refused when taken in any of the account's spaces), so a claimed number does not need the import. Slice 2. |
| Cross-RFC links and parts | Parts, mentions, supersedes and "measures" exist. Add typed links between documents (depends_on, amends, implements_part_of) as facts, shown on both documents. |
| Search | ListDocuments has a substring query within one space. Add a search across the account's spaces over titles, summaries and the reader's cut of the current text, with a short snippet. Later, after slice 6: needs an index that respects the cut, and nobody has asked for more than the substring search yet. |
| Diff of two versions | DiffVersions: a unified diff of two versions of the reader's cut, computed on the server so every client gets the same answer. |
| What changed since I last looked | MarkSeen per reader and document; ListChanges with since (a version, a time, or the reader's mark): versions, comments, facts and timeline entries after it. |
| Assignment and due dates | People exist (RFC 0041). Add a due date on a document or part and on a decision; the home lists what is overdue. |
| Webhook and SSE on change | Six lab.* events exist and reach webhooks and the event stream. Add one event per new fact (lab.implementation.changed, lab.roll.recorded, lab.decision.asked, lab.decision.answered, lab.block.changed, lab.issue.changed, lab.document.stage, lab.document.access). |
| Machine identity for agents | Section 2, core-c7. |
| Bulk import and export | ImportDocuments (admin, InOrbit's own accounts) and ExportSpace exist. Opening the import to customer accounts is later: no customer has asked, and it needs its own limits and checks per account. |
| Templates | default and blank exist. Templates per space (a document with template: true) later: one template has served every RFC so far. |
| Checklists that tick from pull requests and rolls | A checklist item is a fact with text and an optional condition, the same conditions a block uses; it ticks when its pull request merges, its roll is recorded or its decision is answered. Shown in place of hand-ticked boxes. |
| Measured proof attached | A proof fact holds an evidence record's digest (RFC 0046), a monitor or a check (RFC 0041, section 4). Later: no evidence record is written yet, and a proof that points at nothing would look like one. Monitors can be attached first. |
| Sync from the repository on merge, and the switch to the product as the source | During the transition rfcs:import replaces a document's text with its file whenever a file exists, so a document kept through the API and also committed as a file loses every API edit at the next import unless the two are kept identical by hand (this RFC is one: its file exists only to keep its number). Proposed: a document records its source (repository or product); the import updates only repository documents and reports the others as skipped: product is the source; SetSource moves a document to product once, audited, and an export writes the file back for the repository. A merged change under the RFC folder is imported by a workflow on our own runners with the agent identity, for repository documents only. Slice 2, because every API edit to a committed RFC is at risk until it lands. |
| Studies with their data as attachments | RFC 0065's own next step; not repeated here. |
API
All on RfcsService (iohr.rfcs.v1), REST under /v1/rfcs, every list paged by the
response contract (RFC 0033), every write naming the document's space. Reads need
rfc:read, writes rfc:write; the edge gates them like the existing routes, and the three
route lists (accounts scopes, the protocol's OpenAPI scopes, the edge) gain each route in the
same change.
| RPC | REST | Who |
|---|---|---|
ListImplementations |
GET .../documents/{document_id}/implementations |
readers |
LinkPullRequest, UnlinkPullRequest |
POST .../implementations, POST .../implementations/{id}/unlink |
writers |
RecordPullRequest |
none (internal listener) | svc:connections only |
RecordRoll |
POST /v1/rfcs/rolls |
the platform's admins, InOrbit's own accounts |
ListRolls |
GET /v1/rfcs/rolls, GET .../documents/{document_id}/rolls |
readers |
AppendStatus |
POST .../documents/{document_id}/status-log |
writers |
SetStage |
POST .../documents/{document_id}/stage |
writers |
AskDecision, AnswerDecision, ListDecisions |
.../decisions, .../decisions/{id}/answer |
writers ask; the named answerer or a manager answers |
AddBlock, ClearBlock, ListBlocks |
.../blocks, .../blocks/{id}/clear |
writers |
AddIssue, CloseIssue, ListIssues |
.../issues, .../issues/{id}/close |
writers |
RecordRelease |
POST .../documents/{document_id}/releases |
writers (the release workflow's agent identity) |
SetSource |
POST .../documents/{document_id}/source |
the space's managers |
CheckDocument |
POST .../spaces/{space_id}/check |
writers |
DiffVersions |
GET .../documents/{document_id}/diff |
readers |
MarkSeen, ListChanges |
POST .../seen, GET .../changes |
readers |
GetDocument gains as_level; Document gains stage, due and counts of open
decisions, blocks and issues; TimelineEntry gains source and fact_id.
The connections service gains the GitHub receiver path the App already points at (opened
at the edge for exactly that path, like the existing hook path) and BackfillGithub
(POST /v1/connections/github/backfill, managers of the account).
Data model
New tables in the labs schema, one migration per slice, each row carrying the account and the document:
pull_requests(account, repository, number, title, state, author login, head sha, merge commit, commit count, opened, merged and closed times, private, last event time), unique by account, repository and number;implementations(document, pull request, source, added, removed);rolls(account, deployment, commit, previous commit, by, started, finished, outcome) androll_commits(roll, sha, pull request number, affected deployments);decisions(document, anchor, question, options, answerer, due, asked by and when, answer, note, answered by, relayed by, channel, when, replaces);blocks(document, blocked reference, blocker reference, condition, note, created by, cleared, cleared by, reason);issues(document, kind, title, blocking, severity, level, found by and when, closed, how) andissue_fixes(issue, pull request);releases(document, repository, tag, artifact digests, attestation result, by, when);seen(subject, document, version, time), andstage,duecolumns on documents.
A GitHub login is personal data: it is kept as long as the pull request row, exported and
erased with the subject by ExportSubject and EraseSubject.
Limits
| What | Bound |
|---|---|
| implementations per document | 500 |
Implements: lines read per pull request |
20 |
commits per RecordRoll |
2000 (a longer range is recorded as truncated) |
| decisions per document; options per decision | 200; 2 to 10 |
| blocks per document; issues per document | 200; 500 |
| a question, a note, a status-log line | 2000 characters |
| an issue's title, an option's label | 200 characters |
| a delivery from GitHub | 2 MiB, larger refused |
| delivery ids kept for duplicate detection | 7 days |
| backfill per call | 1000 pull requests, then a page token |
| rates |
Past a bound the answer is INVALID_ARGUMENT or RESOURCE_EXHAUSTED, never a silent cut.
Console and command line
- The document page gains panels: Implementation (pull requests by repository, state, merged, live per deployment), Decisions, Blocked by and Blocking, Issues, Rolls; each hidden when empty. The header shows the stage.
- The RFCs home shows stages on the phase bars, overdue items and open decisions for the owner.
iohr rfcgains one command per fact (section 2).- The MCP tools follow the existing rule: agents read everything and write facts; answering a decision, setting a status and approving stay with people.
Controls
- Access control. The edge authenticates every route. GitHub deliveries are accepted only
with a valid signature and only for an installation linked to one account; a link
reaches documents of that account only.
RecordPullRequestaccepts one service caller;RecordRollonly the platform's admins on InOrbit's own accounts. The labs service today refuses every service caller but erasure and export: the allow-list grows by exactly these two names, in configuration. - Least privilege. The App keeps pull requests and metadata read; Actions or Checks read is added only for CI blockers, by the owner. No code is read.
- No leaks across levels. Every fact is read through the document's access function and its own level; free text is cut and checked like document text; public pages show counts for private repositories.
- Audit. One line per write and per delivery: installation, repository id, number, delivery id, outcome; never a title or a body.
- Customer data. Titles, questions and notes are customer data: never in a log line, metric label, event or URL.
Slices
Each slice is shippable alone, has its own pull request, adds its rows to the labs README and the OpenAPI documents, and is recorded on this RFC through the API when it lands. Owner: lab-saas-work unless someone takes a slice on the board.
Slice 1: implementations from the GitHub App
Owner: lab-saas-work. Depends on: nothing new; shares the receiver with RFC 0077's second slice (whoever lands first builds it, the other adds its reader).
- Connections: the receiver at the App's webhook path; signature check before parsing;
duplicate deliveries dropped; installation to account from the installation link
(until RFC 0077's console linking exists, our installation is linked to the Engineering
account in the connections configuration, an id that is not a secret);
pull_requestactions opened, edited, reopened, closed, synchronize and ready_for_review; link lines parsed, the description discarded. - Labs: migration for
pull_requestsandimplementations;RecordPullRequest(internal,svc:connectionsadded to the allow-list);ListImplementations,LinkPullRequest,UnlinkPullRequest; timeline entries withsource: implementation;lab.implementation.changed; erasure and export of the author login. - Backfill:
BackfillGithubin connections, paging the installation's pull requests through the App back to 2026-09-01 and recording each withsource: backfill; a daily run of the same call. - Console: the Implementation panel on the document page, without live (slice 3).
- Docs: the labs and connections READMEs,
docs/protocol, the metrics table.
Acceptance (integration tests on real servers, no mocks of our services):
- A signed
pull_requestdelivery withImplements: RFC 0041andImplements: RFC 0040.1makes two rows; editing the description to drop one marks it removed; a merged event setsmerged_atandmerge_commit. - A wrong or missing signature is refused with nothing read or stored; a repeated delivery id records once; an older event after a newer one changes nothing.
- A number the account does not have, or a delivery for an unlinked installation, records nothing and is audited as such.
- A reader at
publicsees counts for a private repository and no title; a reader atteamsees the row; a caller outside the account getsNOT_FOUND. - No title, description or login appears in any log line of either service (the existing log-capture test, extended).
- Backfill on a recorded fixture of GitHub's list responses records each linked merged pull request once, and a second run changes nothing.
- Proof when live: this RFC's own pull request appears in its Implementation panel.
Slice 2: iohr rfc impl, log and stage
Owner: core-c7 for the CLI, lab-saas-work for the API. Depends on: slice 1, the CLI's
first release. Adds AppendStatus, SetStage with the stage rules (live checks wait
for slice 3), the optional number on CreateDocument, and a document's source
(repository or product) with an import that leaves product documents alone.
Acceptance: a status line appended through the CLI lands at the end of the status log
with today's date and leaves earlier text unchanged; a concurrent full save does not lose
it; SetStage live is refused while no implementation is merged; a document created with
a free number keeps it and a taken one is refused; after SetSource product, an import of
a different file reports it skipped and its text stays as the API saved it.
Slice 3: rolls and live
Owner: lab-saas-work. Depends on: slice 1. RecordRoll, ListRolls; the roll tasks call it
after recording the commit, with the commits between the old and new commit and the
deployments each affects (a small addition to the CI change map); live per deployment on
the Implementation panel; SetStage live checks. Acceptance: a roll of one deployment
past a pull request that affects two shows it partly live; the second roll makes it live;
a roll that fails to record does not fail the roll itself and says so; a documentation-only
pull request shows "nothing to roll".
Slice 4: check without saving and reading as a level
Owner: lab-saas-work. Depends on: nothing. CheckDocument, GetDocument as_level.
Acceptance: a draft with a product name and a port returns both findings by rule and line
and stores nothing; a manager reading as public gets the same bytes the public route
serves; a non-manager asking for as_level is refused.
Slice 5: decisions
Owner: lab-saas-work. Depends on: slice 2 for quoting answers into the status log. Acceptance: an agent asks with three options; the owner answers in the console; a relayed answer is marked relayed until confirmed; an answered decision cannot be changed, and a replacing decision names it.
Slice 6: blocks
Owner: lab-saas-work. Depends on: slices 1 and 3; CI blockers also on the owner adding Actions or Checks read to the App. Acceptance: a part blocked by an open pull request shows on both sides and clears itself when the pull request merges; a roll blocker clears when the roll is recorded; a manual clear needs a reason.
Slice 7: issues (defects and findings)
Owner: lab-saas-work. Depends on: slice 1 (fix pull requests), slice 3 (fixed live).
Acceptance: a defect closed by a merged fix shows the fix's live time after its roll; an
unfixed security finding is invisible below internal; an open blocking finding refuses
stage live.
Slice 8: diff and what changed since I last looked
Owner: lab-saas-work. Depends on: nothing. DiffVersions, MarkSeen, ListChanges.
Acceptance: the diff of two versions never shows a classified span to a reader below it;
changes since a mark list a new comment, a new version and a new implementation.
Slice 9: the owner's review on the phone
Owner: lab-saas-work with the app's owner. Depends on: slice 5, the app's notifications
(RFC 0074). Acceptance: a review request with an open decision reaches the owner's phone,
an answer from the phone is recorded with channel app, and the notification holds no
text above the reader's level.
Slice 10: releases, typed links, checklists, due dates
Owner: lab-saas-work; the release workflow's part with the SDK and data plane owners. Depends on: slices 1 and 3. Acceptance per fact: a release record with a failed attestation stays beside the one that passed; a checklist item bound to a pull request ticks on merge; an overdue decision is listed on the home.
Later
Search across spaces, templates per space, customer import, proofs from evidence records (after RFC 0046 writes one): each with its reason in section 11.
Alternatives considered
- Keep prose and comments, with stricter rules. What the board asks of every agent today. It depends on each agent remembering each step, and the comments cannot be counted, filtered or cleared by an event.
- One generic "fact" table with a JSON body. Fewer migrations, and every rule above (who may answer a decision, when a block clears, what a public reader sees) would move into code that reads untyped JSON. Typed tables keep each rule where it can be tested.
- Read GitHub on demand instead of storing pull requests. No webhook to run, but every page view would cost API calls against the App's limits, and nothing would hold the history of an edited link.
- GitHub's own issue links or Projects as the record. They live in one repository and one vendor, cannot hold rolls or decisions, and do not follow our access levels.
Decision
Open. Proposed: typed facts on documents, written through the API by whoever observed them;
the GitHub App's pull_request events and the Implements: line as the source of
implementations; rolls recorded by the roll tasks; decisions, blocks and issues as records;
slices in the order above, slice 1 first.
Publication
The RFCs reference gains each RPC as its slice lands. The console's document page and home
gain the panels. The contribution guide's Implements: line points to the Implementation
panel instead of the comment rule.
Status log
- 2026-10-07: opened at the owner's request (team board, "RFC engine wishlist"), written by
lab-saas-work from the wishes of core-c7, seo-worker, llm-work and
cimd-sign-in-integration. Nothing is built. Engine gaps found while publishing it through
the API:
CreateDocumentcannot take a number another session has reserved, so this RFC went in through the import of a committed file to keep its number; there is no check without saving (the import's dry run served instead); no status-log append, so this line went in with the file; while the file exists, the import overwrites any API edit that is not also made to the file. Two diagrams made through the API and embedded. - 2026-10-07: slice 2's API built by lab-saas-work:
AppendStatus(POST .../documents/{document_id}/status-log, a dated line appended on the current version under its lock, no base needed),SetStage(the reason becomes a status-log line;partly_liveandliverefused until slices 1 and 3 record pull requests and rolls),numberonCreateDocument(managers; in our own accounts free across every space), and a document'ssourcewithSetSource: the import now skipsproductdocuments ("skipped: product is the source"), so an RFC edited over the API keeps its edits. The interim commands arerfcs:doc -- log,stage,sourceandcreate --number, andrfcs:import --only;iohr rfc impl,logandstagestay with core-c7. Next for the import (wishlist, cimd-sign-in-integration): skip arepositorydocument whose current version was saved over the API after the last import ("skipped: product changed since the last import") unless forced. The tasks' port-forward already picks a free port. - 2026-10-07: slice 9's labs side merged (core#569, 9ef5f0f7, not rolled): a review outbox (labs.review_events, once per review, version and moment, only when the person told reads the document) publishes lab.review.requested and the new lab.review.answered, ids only. Next: the outbox calls paging's NotifyPeople once that is on main.