Questions are headings and resolved ones are kept
- Created
- Decided
- Versions
- History
Abstract
Open questions becomes an optional section that holds each open question as a level three heading, with any detail as prose beneath it. An optional Resolved questions section holds answered questions in the same form, each ending on a blockquote that holds its answer, so a question answered before acceptance moves there rather than being deleted. A new rule, L20, checks both sections, and the export publishes questions and answers as structured data in place of the sections in the document's contents.
Motivation
Open questions has no defined shape. It may hold prose, a list, or both, and the tool reads it only to check that it is present, in order, and empty before a document is accepted. Because accepting requires it to be empty, an answered question is deleted. Its answer may reach the Proposal or the Changelog, but the question itself is gone, and nothing ties the answer to what was asked. RFC-0007 resolved three open questions while proposed: two of their answers are in its Proposal, all three are named in one Changelog entry, and the questions are no longer in the document.
Reviewing a document means reading what is still open and checking what was answered against what was asked. The export carries each document's headings and prose in contents, which gives a reviewing consumer no way to tell a question from any other heading, or an answer from the prose around it.
Proposal
Concepts
| Concept | Meaning |
|---|---|
| Question sections | Open questions and Resolved questions |
| Question | A level three heading in a question section. Its text is the question |
| Blockquote | Within a question section, a run of consecutive lines each beginning with > at the start of the line, outside a fenced code block and an HTML comment |
| Ends with a blockquote | A question ends with a blockquote when its last blockquote is followed by nothing but blank lines and HTML comments before the next heading or the end of the document |
| Answer | The blockquote a question in Resolved questions ends with |
| Detail | The lines from a question's heading to its answer, or to the next heading or the end of the document where it has none |
Components
| Component | Responsibility |
|---|---|
internal/repo |
An RFC's required sections no longer include Open questions. Reads a document's open and resolved questions, their detail and answers, and the faults in their shape. L20, the lifecycle gate and the export all read these. Reads a link reference definition written behind > in a question section, so L17 checks it |
internal/lint |
L20, which reports those faults. L14 no longer exempts Open questions |
internal/lifecycle |
accept and reject refuse a document with any of those faults, and the refusal for a non-empty Open questions names Resolved questions |
internal/export |
The questions object on each document, contents without the question sections unless every heading is asked for, schema: 3 with its schema published beside the earlier ones, and the package's and the schema's own descriptions of its stability |
cmd/archdoc |
archdoc export --all-headings, and dropping question and answer bodies from index.json under --out, copying the nested values before it does, as it copies contents |
internal/template |
The RFC template's comment in Open questions, which says the section is optional; in PROCESS.md, the list of RFC sections, the accept and reject sentence and the list of what lint enforces; the same sentence in the authoring and working guides, and in the authoring guide its list of RFC sections and its account of the sections exempt from emptiness; and in the triage guide, the L09 remedy, the list of rules whose findings soften once frozen, and a new L20 row. The copies archdoc update writes, and the plugin's skills regenerated by go test ./internal/template -update-plugin, follow from these |
| Published schemas | v3.json is added. v1.json and v2.json stay published, with the description each gives of its stability changed to say that the promise starts at 1.0 |
| Specification pages | markdown.md: the RFC's required sections, blockquotes, and the question sections. lint.md: L14's exemptions, L20, and the rules whose findings soften. lifecycle.md: the gate. export.md: the flags, the shape and its stability |
| Documentation | The rule count in README.md; in docs/DECISIONS.md, the list of softened rules and the description of what accept and reject refuse; and the flags, the shape and its stability in docs/EXPORT.md |
Open questions is optional
An RFC no longer requires Open questions. Its required sections are Abstract, Motivation, Proposal, Alternatives considered, Backwards compatibility and Changelog, in that order. Both question sections are then optional for every type. The RFC template keeps the heading, with a comment saying the section is optional and is deleted once nothing in it is open.
L08 no longer checks its presence or its order, and L14 no longer needs to exempt it. Accepting a document requires it to be absent or empty. Every accepted RFC carries an empty one, which breaks no rule.
Headings and blockquotes
Questions are headings, which the tool already recognises under ADR-0006. Answers are blockquotes, which join the constructs the tool recognises under that ADR's provision that the set grows when something needs more: an answer has to be told from the detail before it without a heading of its own. Blockquotes are read only within the question sections; elsewhere they remain text. Their grammar is the one rule in Concepts, against the markers, indentation and nesting a list grammar needs.
A blockquote in a question section holds no heading, no fenced code block and no HTML comment. The tool finds headings, fences and comments before it knows a line is quoted, and does not see a fence inside a blockquote at all, so a comment marker inside one would hide the rest of the document from it. L20 reports any of the three at the line that opens it, rather than reading it some other way. A link reference definition an answer uses is written inside its blockquote, and so belongs to the answer. Fenced code blocks and HTML comments outside a blockquote are recognised within detail as everywhere else, and lists, tables and other Markdown in detail and answers are text.
Headings and blockquotes are read here as they are everywhere else in the tool, which differs from rendering in places. The known cases:
- A setext heading, text underlined with
===or---, renders as a heading and is read as prose. - A heading inside a blockquote, or on a list item's first line, renders as one and is read as prose, and GitHub gives it an anchor that shifts the suffixes of later headings. One on a list item's continuation line, indented up to three spaces, is read as a heading.
- A line inside an HTML block, other than a comment, is read as written and renders as HTML.
- A backtick fence whose opening line holds another backtick is read as a fence and renders as text, hiding what follows it from the tool.
- A fence inside a blockquote is not read as one, so a comment marker inside it opens a comment for the tool.
- A comment opened after other text on a line, where a blank line comes before it closes, hides the lines after it from the tool, though they render.
- A line without
>directly after a blockquote's text renders inside it, and is read as prose after it. - A blockquote indented up to three spaces renders as one and is not read as one.
Each question has the anchor its heading is given everywhere, and an answer is linked through its question. Anchors are suffixed in document order where headings collide, so a question whose text produces the same anchor as another heading's can have its anchor taken. L20 reports a question whose text produces the same anchor as any other heading in the document.
Open questions
## Open questions
### Should `index.json` carry the questions?
Raised in review. The alternative is each document's own
file only.
### Does a withdrawn document's question survive into the export?
The section is empty, or it holds one or more questions and nothing before the first. A question may have detail and has no headings beneath it. A blockquote in an open question's detail is detail, but the question does not end with one, so moving it to Resolved questions cannot turn a quote into its answer. An open question has no answer: answers are reached outside the document, and the next change the document sees is an edit to the question or its move to Resolved questions.
Accepting a document requires the section to be absent or empty, as lint L09 and the accept command enforce. An answered question is moved, not deleted: its heading and detail go to Resolved questions and its answer is added after them. A question handed to a follow-up document is resolved once that document exists, and its answer links to it. Once nothing in the section is open, it is deleted or left empty. An edit made while the document is proposed takes a Changelog line, as any other does.
Resolved questions
## Resolved questions
### Should `index.json` carry the questions?
Raised in review. The alternative is each document's own
file only.
> Yes, without the bodies of detail and answers, as
> `index.json` carries contents without bodies.
A document carries at most one. Where the document has an Open questions section, Resolved questions is the next heading of level two or higher after one. It holds one or more questions and nothing before the first. Every question has no headings beneath it and ends with its answer, which is not empty. Detail before the answer is optional, and a blockquote within the detail is detail, but the detail does not end with one, which would make two answers of one. An answer is any amount of prose, so a question with several parts has them answered in one place. Its paragraphs are joined by lines holding only >, because a blank line ends a blockquote.
L20
L20 checks every question section a document carries, whatever its type, as L09 is keyed on the section rather than the type. It does not check the Open questions section of an accepted document, which L09 already reports when it holds anything. It does not check a withdrawn document, as L14 does not: a withdrawn document is abandoned, and withdraw performs no content checks, so a fault in one would stand once it is frozen.
L20 takes its severity from the same function as L16 and L17: an error while the document is editable, whatever its status, and a warning once it is frozen. A document with no terminal status, such as a spec page or a ref, is never frozen, so a finding on one is always an error. A question section is part of the document's own body, which is what ADR-0009 makes a warning of once no permitted edit could clear the fault.
| Finding | Section | Line |
|---|---|---|
| The section holds something before its first question, or holds something and no question | Either | The first line that is not blank or a comment |
| A question's heading produces no anchor | Either | The question |
| A question's heading produces the same anchor as another heading in the document | Either | The question, or the later of two questions |
| A question has a heading beneath it | Either | That heading |
| A blockquote holds a heading, a fenced code block or an HTML comment | Either | The line that opens it |
| An open question ends with a blockquote | Open questions |
The blockquote's first line |
| The section is empty | Resolved questions |
The section's heading |
| A question has no heading beneath it and does not end with a blockquote | Resolved questions |
The question |
| An answer has another blockquote before it, with only blank lines and HTML comments between them | Resolved questions |
The answer's first line |
| An answer is empty | Resolved questions |
The answer's first line |
The section is not the next heading of level two or higher after an Open questions section, in a document that has one |
Resolved questions |
The section's heading |
The document carries more than one Resolved questions section |
Resolved questions |
Each heading after the first |
Anchors are compared before any suffix is added, so headings differing only in formatting share one, and a heading producing no anchor before any suffix is reported by its own row alone. A Resolved questions section after the first is reported by the last row alone at its heading, and the rows about the section itself do not apply to it; its questions are checked as the first section's are. A section, or an answer, is empty when it holds nothing but whitespace, HTML comments and, for an answer, its > markers.
Lifecycle
accept and reject refuse a document with any fault L20 reports, as they already refuse a missing or mismatched H1, a missing, misordered or empty required section, and an unresolved [[...]] link. A terminal document is never modified under ADR-0001, and once it is terminal on the configured branch lint treats it as frozen, so a fault let through could never be cleared.
accept checks that Open questions is absent or empty before it checks the shape of Resolved questions, so a document with open questions is refused for those and not for their shape. reject checks both sections. withdraw performs no content checks, unchanged.
Export
Under ADR-0020, the question sections are published as structured data and left out of contents. The Changelog will be too, under a design of its own released with this one so the export breaks once. The document object described by RFC-0004 and RFC-0006 gains questions, an object with open and resolved arrays. Each question carries text, anchor, line and body, its detail. A resolved question also carries answer, an object with line and body.
"questions": {
"open": [
{
"text": "Does a withdrawn document's question survive into the export?",
"anchor": "does-a-withdrawn-documents-question-survive-into-the-export",
"line": 98,
"body": ""
}
],
"resolved": [
{
"text": "Should `index.json` carry the questions?",
"anchor": "should-indexjson-carry-the-questions",
"line": 102,
"body": "\nRaised in review. The alternative is each document's own\nfile only.\n",
"answer": {
"line": 107,
"body": "Yes, without the bodies of detail and answers, as\n`index.json` carries contents without bodies."
}
}
]
}
| Rule | Detail |
|---|---|
contents |
Leaves out every question section: its heading and every heading beneath it, with their bodies. An RFC's required_sections no longer names Open questions |
--all-headings |
contents carries every heading as written, the question sections included. questions is unchanged |
| Presence | questions is written on every document, with empty arrays where there are none. answer is written on every resolved question that ends with a blockquote, and is absent where one does not |
| Sections | open holds the questions of every Open questions section, and resolved those of every Resolved questions section, each in document order |
| Bodies | A question's body is its detail, the lines as written, as a contents entry's is. An answer's body is its lines with the leading > and one column of the whitespace after it removed from each, as CommonMark removes them, so it is Markdown without the quote. A GitHub alert keeps its [!NOTE] line. An answer's line is its first line, where its body starts. A body is absent wherever contents bodies are: under --no-bodies and in index.json |
| What it holds | What was parsed, whatever L20 reports. Anything in a question section that belongs to no question or answer appears only in source, and in contents under --all-headings |
| Schema | schema moves to 3 under ADR-0019, because contents no longer holds every heading and an RFC's required_sections changes. Three definitions are added: an open question, requiring text, anchor and line; a resolved question, requiring the same, with answer optional; and an answer, requiring line. body is optional on each, as on a contents entry. A document requires questions, and questions requires open and resolved |
This amends RFC-0006, under which contents is every heading in document order. It is every heading outside the question sections, and every heading under --all-headings, where a question's prose is published in both places. It amends the document object RFC-0004 describes, which gains questions.
Errors
| Condition | Result |
|---|---|
accept on a document whose Open questions is not empty |
refusal naming the section, and that each question moves to Resolved questions with its answer and anything else in it is removed |
accept or reject on a document with a fault L20 reports |
refusal naming the line and the fault |
| An L20 finding | the document, the line from the findings table, and the fault |
Out of scope
- A command that resolves a question. Moving a heading and its detail between two sections and adding an answer after them is an ordinary edit.
- Identifiers for questions beyond their anchors. A label that survives rewording the question would need its own uniqueness and reuse rules, and nothing yet refers to a question other than by link.
- The
Changelog's structured form. ADR-0020 names it with the questions. Its shape, and whether it stays a required section once it leavescontents, are a design of its own, released with this one so the export breaks once.
Alternatives considered
The design rests on ADR-0001, whose freeze is why accept and reject refuse a document L20 reports; on ADR-0006, whose set of recognised constructs is why questions are headings, and whose provision for growth admits blockquotes; on ADR-0009, which sets L20's severity on a frozen document; on ADR-0019, under which leaving headings out of contents moves schema to 3; and on ADR-0020, which takes the question sections out of contents and records the alternatives to that.
- Lists. Questions as list items, answers as items nested beneath them. Weighed in three forms: any marker with items that wrap, chosen on ; a strict subset of CommonMark list syntax that reports anything outside it, chosen on over the full CommonMark list rules, which lost on the size of the parser and of the specification they need; and numbered questions and detail with bulleted answers, so that detail items could be answered too, proposed on . Within the first,
-only, with and without items that wrap, and nested detail under an open question were also weighed. Lost on to headings. A list item has no anchor, so a question could not be linked to; list numbering cannot identify a question, because a rendered ordered list numbers from its first item whatever the rest are written as; and the two grammars written each read some lists differently from how they render. - Answers in
Open questions. Candidate answers recorded under an open question, with the final one moved toResolved questions. Lost because answers are reached outside the document, and the history of a question's edits is already in version control and, while proposed, the Changelog. - An
Answerheading beneath the question. A level four heading readingAnswer, with the answer beneath it.Chosen on over a bold paragraph, on a reason later found false, and kept on because a heading gives each answer an anchor.Struck on : everyAnswerheading shares one anchor text, so they takeanswer,answer-1and so on in document order, and a link to one points at another once a question is resolved ahead of it. Lost because its anchor cannot identify an answer, and each answer adds anAnswerentry to the document's outline. - An answer marked by a bold
Answer:paragraph. Lighter to read than a heading.Lost because recognising it needs paragraphs as a construct.Struck on : paragraphs are already read, for L15.Lost because a heading gives each answer an anchor.Struck on with theAnswerheading. Lost because a blockquote sets an answer apart when rendered without a label. - Answers as bullets beneath the question. Lost because it brings back a list grammar for the answers.
- Several answers per question. Lost because one answer holds any amount of prose.
- An answer's body with its
>markers. The lines exactly as written. Lost because every consumer would remove them. - Duplicate questions compared by heading text as written. Lost because headings differing only in formatting share an anchor, and a shared anchor is what makes a link to either unreliable.
- Prose before the first question.
Chosen, as section text that costs nothing to allow.Struck on , when the question sections leftcontents: such prose would then appear in the export only insource. Open questionsas a required section. As it was. Lost because it guaranteed only that the section existed, which nothing reads once a document is accepted, and a required section left out ofcontentswould read to a consumer as missing.- Keeping the question sections' headings in
contents, or recording their presence inquestions. Either would have let a consumer find a requiredOpen questionsabsent fromcontents. Lost to making the section optional, which leaves nothing required to find. - Dropping
Open questionsfrom the RFC template. Lost because the heading in the template shows an author where questions go. - Severity as L14's. No finding on a draft and a warning on a proposed document. Lost because a fault in either section is a quick edit for the document's author, so a document is told at once.
- A new ADR adding L20 to the list of rules in ADR-0009. Lost because that list names the rules of its time, and lint the lint page carries the current list.
- Accepting with prose left in
Open questions. The gate would require no questions rather than an empty section, so a line such as "All questions were resolved in review." could remain. Lost because it loosens L09 and theacceptgate to permit something theResolved questionssection now records. - An option for the question sections alone. Restoring only them to
contents. Lost because ADR-0020 takes theChangelogout ofcontentsas well, and one option named for what it restores covers both.
No other alternatives were weighed.
Backwards compatibility
Nothing checks the shape of either question section today. L09 tests only that an accepted document's Open questions is empty, and is unchanged. The accept and reject gates gain the refusals described under Lifecycle, and accept's refusal for open questions names Resolved questions where it named a follow-up RFC. Making Open questions optional only loosens: an RFC without it was reported by L08 and refused by the gate, and no longer is, and every RFC that has one still passes.
In this repository, every RFC's Open questions is empty and no document has Resolved questions, so spec/ reports nothing. The tests do not hold:
- Three RFCs in
testdata/repo, two in draft and one proposed, have prose inOpen questions, and that fixture is required to produce no errors, so their questions are rewritten as headings. One of them,testdata/repo/rfc/0007-scheduling.md, has its exact headings asserted byTestHeadingsIgnoreFencedCodeBlocks, whose expectation gains the question. - The lint fixtures gain an L20 case, and the registered rule count rises from nineteen to twenty.
TestRequiredSectionsSurviveTheirAbsenceexpects at least seven RFC sections, and there are six.- The export's tests assert
schemais2, and its schema is compared against its types, which gain the three definitions. TestThePublishedSchemaMatchesTheEmbeddedOnecompares the embedded schema withv2.jsonand checks its identifier names that file. It moves tov3.json, so that regenerating the published copy writesv3.jsonand leavesv2.jsonas released.
The export breaks, and schema moves to 3. A consumer of schema: 2 that renders contents stops receiving the Open questions heading of every RFC, and any question or answer, unless the export is run with --all-headings, and finds Open questions gone from an RFC's required_sections. A consumer validating against v2.json rejects the new output, which names another schema. v2.json stays published, and v3.json is published beside it.
In a repository that upgrades:
- An accepted document's
Open questionsis left to L09. AResolved questionssection of another shape is reported, as a warning once the document is frozen. - A rejected document whose
Open questionsholds anything before its first question, a heading beneath a question, a heading, fence or comment inside a blockquote, a question with no anchor or sharing one with another heading, or a question ending with a blockquote, is reported with a warning once frozen, and with an error while it is terminal but not yet on the configured branch. - A withdrawn document is not checked.
- A draft or proposed document in the same state is reported with an error, and the edit that clears it is one its author may make.
- A spec page or ref carrying either section is never frozen, so anything L20 reports there is an error.
- A level three heading already under
Open questionsis read as a question, and a heading beneath it is reported. - Blockquotes outside the question sections are not read, and nothing about them changes.
- A link reference definition written behind
>in a question section is checked by L17, which did not read it before. acceptandrejectrefuse a document they previously moved, where L20 would report it.
Source rfc/0008-questions.md · commit aa43057 · exported