@erclx/canon 5.39.0 → 5.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -22
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/auto-ship/REQUIREMENT.md +1 -0
- package/claude/skills/auto-ship/SKILL.md +6 -0
- package/claude/skills/auto-ship/references/fan-in.md +59 -0
- package/claude/skills/canvas-board/SKILL.md +1 -1
- package/claude/skills/create-skill/references/skill.md +1 -1
- package/claude/skills/decision-escalate/REQUIREMENT.md +1 -1
- package/claude/skills/decision-escalate/SKILL.md +1 -2
- package/claude/skills/draft-slides/SKILL.md +2 -3
- package/claude/skills/draft-slides/references/deck.md +183 -0
- package/claude/skills/git-branch/REQUIREMENT.md +17 -6
- package/claude/skills/git-branch/SKILL.md +63 -7
- package/claude/skills/git-pr/references/evidence.md +2 -2
- package/claude/skills/git-pr/references/final-command.md +1 -1
- package/claude/skills/git-pr/references/labels.md +1 -1
- package/claude/skills/git-pr/references/publish.md +1 -1
- package/claude/skills/plan-feature/references/batches.md +48 -1
- package/claude/skills/plan-feature/references/plan.md +2 -0
- package/claude/skills/plan-intake-answer/REQUIREMENT.md +1 -1
- package/claude/skills/plan-intake-answer/SKILL.md +1 -2
- package/claude/skills/review-address/references/rebase-conflicts.md +7 -0
- package/claude/skills/review-ui/SKILL.md +3 -0
- package/claude/skills/review-ui/references/close-out.md +47 -0
- package/claude/skills/review-ui/references/post.md +3 -1
- package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +1 -0
- package/claude/skills/role-orchestrator/references/orchestrator-handback.md +1 -1
- package/claude/skills/role-worker/REQUIREMENT.md +1 -0
- package/claude/skills/role-worker/SKILL.md +9 -0
- package/claude/skills/task-board/references/board.md +1 -1
- package/claude/skills/task-board/references/tasks.md +1 -1
- package/claude/skills/teach-workspace/REQUIREMENT.md +1 -1
- package/claude/skills/teach-workspace/SKILL.md +1 -2
- package/claude/skills/ux-measure/SKILL.md +1 -1
- package/docs/agents/audits.md +61 -60
- package/docs/agents/context-audit.md +40 -58
- package/docs/agents/index.md +5 -51
- package/docs/agents/install-and-sync.md +1 -0
- package/docs/agents/markdown-audit.md +53 -99
- package/docs/agents/records.md +37 -79
- package/docs/agents/sessions-transfer.md +26 -70
- package/docs/target/index.md +0 -1
- package/docs/target/migrations.md +57 -66
- package/docs/target/projects.md +36 -78
- package/docs/target/scenarios.md +9 -19
- package/docs/target/sync.md +27 -68
- package/docs/workflow/ai-workflow.md +22 -68
- package/docs/workflow/operating-model.md +32 -186
- package/docs/workflow/parallel-features.md +30 -66
- package/docs/workflow/skill-map-on-request.md +22 -24
- package/docs/workflow/skill-map.md +72 -76
- package/docs/workflow/visual-design-workflow.md +25 -118
- package/docs/workflow/zshrc-aliases.md +18 -37
- package/package.json +1 -1
- package/src/canvas/client/inspector/fields.css +4 -0
- package/src/canvas/index.html +6 -0
- package/src/claude/cases/git.ts +4 -0
- package/src/claude/skills-reach.ts +2 -2
- package/src/cli/ui.ts +3 -1
- package/src/commands/canvas.ts +23 -0
- package/src/commands/capture.ts +14 -0
- package/src/commands/claude.ts +13 -0
- package/src/commands/demo.ts +22 -0
- package/src/commands/deps.ts +6 -0
- package/src/commands/driver.ts +28 -2
- package/src/commands/gov.ts +52 -18
- package/src/commands/intake.ts +17 -0
- package/src/commands/labels.ts +38 -5
- package/src/commands/pr.ts +192 -52
- package/src/commands/records.ts +19 -3
- package/src/commands/secrets.ts +6 -0
- package/src/commands/sessions.ts +8 -0
- package/src/commands/tasks.ts +52 -0
- package/src/commands/teach.ts +13 -0
- package/src/commands/upstream.ts +25 -1
- package/src/commands/worktrees.ts +5 -0
- package/src/context/audit.ts +22 -4
- package/src/context/folders.ts +1 -1
- package/src/context/shape-gated.ts +5 -2
- package/src/counts/scan.ts +1 -1
- package/src/design/components.ts +1 -1
- package/src/design/document.ts +1 -1
- package/src/design/tokens.ts +1 -1
- package/src/gate/boundaries.ts +4 -1
- package/src/gate/measures.ts +1 -1
- package/src/gate/stages.ts +7 -7
- package/src/git/env.ts +6 -0
- package/src/markdown/scope.ts +11 -19
- package/src/pr/frames.ts +53 -9
- package/src/pr/lift.ts +153 -19
- package/src/pr/painted.ts +87 -0
- package/src/records/validate.ts +1 -0
- package/src/roots/record.ts +18 -1
- package/src/sandbox/census.ts +1 -1
- package/src/sandbox/headless/run.ts +3 -2
- package/src/sandbox/headless/watch.ts +3 -4
- package/src/slides/convert/master.ts +3 -0
- package/src/sync/format.ts +46 -0
- package/src/sync/stamp.ts +6 -0
- package/src/tasks/answers.ts +79 -2
- package/src/tasks/fan-in.ts +176 -0
- package/src/tasks/stack.ts +1 -1
- package/tooling/astro/reference.md +80 -39
- package/tooling/base/reference.md +63 -32
- package/tooling/base/seeds/canon/context/ci.md +7 -15
- package/tooling/base/seeds/canon/context/development.md +14 -14
- package/tooling/claude/reference.md +40 -22
- package/tooling/cloudflare/reference.md +31 -12
- package/tooling/go/reference.md +47 -23
- package/tooling/nextjs/reference.md +52 -19
- package/tooling/php/reference.md +35 -16
- package/tooling/python/reference.md +47 -30
- package/tooling/shell/reference.md +6 -5
- package/tooling/vite-react/reference.md +49 -21
- package/tooling/web/reference.md +131 -71
- package/docs/agents/canvas.md +0 -86
- package/docs/agents/capture.md +0 -65
- package/docs/agents/census.md +0 -23
- package/docs/agents/comments.md +0 -34
- package/docs/agents/context-audit-checks.md +0 -108
- package/docs/agents/context-classify.md +0 -101
- package/docs/agents/counts.md +0 -74
- package/docs/agents/demo.md +0 -140
- package/docs/agents/driver.md +0 -103
- package/docs/agents/gate.md +0 -90
- package/docs/agents/hooks.md +0 -78
- package/docs/agents/intake.md +0 -81
- package/docs/agents/key-changes.md +0 -116
- package/docs/agents/label-coverage.md +0 -86
- package/docs/agents/markdown-audit-density.md +0 -39
- package/docs/agents/markdown-audit-weight.md +0 -83
- package/docs/agents/pr-evidence-layout.md +0 -70
- package/docs/agents/pr-evidence.md +0 -273
- package/docs/agents/pr-frames.md +0 -131
- package/docs/agents/pr-lift.md +0 -132
- package/docs/agents/pr-local.md +0 -111
- package/docs/agents/pr-preview.md +0 -155
- package/docs/agents/pr-reads.md +0 -111
- package/docs/agents/pr-tick.md +0 -72
- package/docs/agents/records-push.md +0 -61
- package/docs/agents/records-stale.md +0 -40
- package/docs/agents/records-validate.md +0 -57
- package/docs/agents/restated.md +0 -83
- package/docs/agents/routing.md +0 -61
- package/docs/agents/rule-citations.md +0 -90
- package/docs/agents/sandbox.md +0 -126
- package/docs/agents/sessions.md +0 -128
- package/docs/agents/skills-audit.md +0 -120
- package/docs/agents/skills-reach.md +0 -64
- package/docs/agents/slides.md +0 -176
- package/docs/agents/state-scoped-risk.md +0 -105
- package/docs/agents/superseded.md +0 -85
- package/docs/agents/tasks-archive.md +0 -83
- package/docs/agents/tasks-plans.md +0 -152
- package/docs/agents/tasks-validate.md +0 -133
- package/docs/agents/tasks.md +0 -123
- package/docs/agents/teach-authoring.md +0 -118
- package/docs/agents/teach.md +0 -157
- package/docs/agents/test-order.md +0 -58
- package/docs/agents/upstream.md +0 -94
- package/docs/agents/worktrees.md +0 -118
- package/docs/target/standards-moved.md +0 -34
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Markdown audit weight
|
|
3
|
-
description: The advisory sections of the markdown audit, being bullet and paragraph weight, run depth, the two cadence numbers, and the length ceiling, with the samples behind each checkpoint and which of those numbers gate through density
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Markdown audit weight
|
|
7
|
-
|
|
8
|
-
## Bullets, paragraphs, and depth
|
|
9
|
-
|
|
10
|
-
Bullet weight and depth are the checks that moved off `canon context audit`, carrying what they measured at the time. A top-level bullet reports past roughly 200 characters with continuation lines folded in and nested items left out. A run reports past roughly 40 rendered lines, measured at 80 columns, where a heading breaks one and so does a bold section marker taking the whole line at column zero, either ending in a colon, or holding one whole code span at any width, or running to 20 characters or fewer, skipping fenced blocks and exempting a flat peer list averaging under 130 characters a bullet and a run that is entirely table rows. Each file reports its longest run alone, so a second run past the checkpoint in the same file is never named.
|
|
11
|
-
|
|
12
|
-
Every weight and depth measure counts the text a reader is shown. A link reduces to its anchor text and an autolink drops whole, since no reader is shown either destination. A backticked path stays counted, which is where these measures part from the ban scan `markdown-audit.md` describes: that one blanks a code span so a standard quoting its own banned character does not report itself, and discounting the same span here would under-report a paragraph carrying several. One file holds both span sets and each answers its own question.
|
|
13
|
-
|
|
14
|
-
A code span is walked around rather than through, so a path quoting link or angle-bracket syntax keeps the width the page gives it. Masking inside one takes back the decision to count it, and the placeholders this toolkit writes are where that shows.
|
|
15
|
-
|
|
16
|
-
The paragraph check measures both halves of one rule. `markdown.md` caps a paragraph at four sentences, and a sentence cap on its own is satisfied by writing fewer and longer ones: 15 paragraphs in this corpus sit inside four sentences and past the weight checkpoint, and the heaviest of those runs 886 characters. The standard therefore states a weight beside the sentence cap, and the verb reads it as its own checkpoint.
|
|
17
|
-
|
|
18
|
-
A sentence boundary closes on terminal punctuation ahead of a capital or a code span. The capital is what keeps a version pin and a decimal from each reading as two sentences, and the code span is admitted beside it because a command name opening a sentence carries no capital to find.
|
|
19
|
-
|
|
20
|
-
The paragraph weight sits at 350 and the bullet weight at 200, the two density lengths in `markdown-audit.md`, so this advisory warning and the density finding that gates read one number. Both shipped at 400 and have moved twice, each time against a sample of its own. They are separate checkpoints in the standard and separate patterns in the parser, so a read that moves one leaves the other where it is.
|
|
21
|
-
|
|
22
|
-
### The sample behind the paragraph number
|
|
23
|
-
|
|
24
|
-
The checkpoint shipped at 400 as a borrowed number and was decided against a read of the prose it reports. Thirty-six findings were sampled, six from each of six weight bands, drawn at even spacing through each band ordered by path and line, and each was classed as prose a reader wants split or prose the checkpoint should not have reported.
|
|
25
|
-
|
|
26
|
-
Every band below was measured before the scan stopped counting link syntax as prose, so a paragraph sitting in one of these bands is heavier than a paragraph reported at the same number today. The re-sample in the section below re-reads the same range against the corrected measure and reaches the opposite verdict on it, which is the measure moving rather than the reader.
|
|
27
|
-
|
|
28
|
-
| Band | Wants the split | Reads as written |
|
|
29
|
-
| --------- | --------------- | ---------------- |
|
|
30
|
-
| 400 - 425 | 1 | 5 |
|
|
31
|
-
| 425 - 450 | 2 | 4 |
|
|
32
|
-
| 450 - 500 | 2 | 4 |
|
|
33
|
-
| 500 - 600 | 2 | 4 |
|
|
34
|
-
| 600 - 750 | 6 | 0 |
|
|
35
|
-
| Past 750 | 6 | 0 |
|
|
36
|
-
|
|
37
|
-
Precision is what moved the number rather than the finding count. Below 600 the checkpoint was right about seven of twenty-four sampled paragraphs, and past 600 it was right about all twelve. A checkpoint is a prompt to look, and a prompt wrong three times in four teaches a reader to stop looking. The distribution offers no seam to place the number against, with a median of 487 and a seventy-fifth percentile of 563, so the read is the whole of the evidence.
|
|
38
|
-
|
|
39
|
-
Nothing inside the 500 to 600 band separated the two classes by length, which is the reason the number did not land there. The two paragraphs wanting a split ran 543 and 590 characters against four reading well at 515, 532, 555, and 569.
|
|
40
|
-
|
|
41
|
-
The sample is thirty-six paragraphs against a reported population in the hundreds, and one reader classed all of them. Treat a band's rate as the order of magnitude it is rather than as a measured precision, and re-sample before moving the number again.
|
|
42
|
-
|
|
43
|
-
### The re-sample that moved the number to 700
|
|
44
|
-
|
|
45
|
-
That re-sample ran once the scan stopped counting link syntax as prose. Findings at 604, 633, and 677 characters each read as an ordinary four-sentence paragraph on one topic, density arrived around 760 and was plain by 860, and the move cut the weight half of the report roughly in half while leaving the sentence cap untouched.
|
|
46
|
-
|
|
47
|
-
### The read that moved it to 350
|
|
48
|
-
|
|
49
|
-
The operator read sample rewrites at 400 and 350 side by side and picked 350, the length of the reference sample, in groundwork `154`. The bullet number moved to 200 in the same read, since no rewritten one-fact bullet passed 151. Both now gate as density limits, so the earlier verdict that a long paragraph reads well as written no longer holds.
|
|
50
|
-
|
|
51
|
-
A bullet, a heading, a table row, a blockquote, a blank line, and a fence each end a paragraph, so a heavy bullet is reported by the bullet check alone and never counted twice.
|
|
52
|
-
|
|
53
|
-
## Bullet stacks
|
|
54
|
-
|
|
55
|
-
A run of more than 5 plain bullets is one of the six density limits in `markdown-audit.md`, which reports and gates it. This section keeps what counts as a run. A run of consecutive top-level bullets reports past 5. A blank line, an indented continuation, and a nested item do not break the run, and a paragraph, a heading, or any other column-zero line does. A fenced line is skipped without breaking it. The count is of items rather than weight, so it catches a catalog of short bullets the 200-character checkpoint above passes.
|
|
56
|
-
|
|
57
|
-
Two shapes are exempt. A run whose every item opens with a bold label or a link names its own subject per item and reads as a table of entries, and a numbered list states an order, so numbered items never count. Governance rules and `REQUIREMENT.md` sit outside the density scope rather than being exempted here, since a rule is one imperative per bullet.
|
|
58
|
-
|
|
59
|
-
## Cadence
|
|
60
|
-
|
|
61
|
-
Uniform cadence is the failure a ban list cannot express. A ban set states negatives, and fragments, verbless clauses, and sentences that all run one length are each the absence of something, so no word added to a ban list reaches any of them. The shape layer already measured a bullet, a paragraph, and a run, and stopped one level above where that failure lives.
|
|
62
|
-
|
|
63
|
-
Cadence measures a paragraph on two numbers. The spread is the words between its longest and shortest sentence, and the opener count is the times one word opens a sentence in it. A spread of five words or under reads as one cadence, and a word opening more than two sentences is a pattern rather than a coincidence. Both come from `## Rhythm` in the `write-human` skill, which states them about prose a person reads, and this measures against that statement rather than setting a threshold of its own.
|
|
64
|
-
|
|
65
|
-
Words are counted off the text a reader is shown. A link contributes its anchor text, an autolink contributes nothing, and the sentence boundaries do not move under that masking, since the boundary pattern requires whitespace after the terminal punctuation and no destination carries any. An opening word is lowercased and stripped of punctuation, so a sentence opening on a backticked command name reports the command.
|
|
66
|
-
|
|
67
|
-
A paragraph carrying fewer than three sentences is skipped rather than scored. A two-sentence configuration note has no spread worth reading, and the opener rule is written about a third sentence turning a coincidence into a pattern, so neither number says anything before the floor. That is the cheap form of a wider exemption: a shape-aware one, exempting a short reference block by what it is rather than by how many sentences it holds, waits on a second case.
|
|
68
|
-
|
|
69
|
-
The unit is the paragraph and each file names its worst on each measure, which follows the depth check rather than setting a precedent. A file's flattest paragraph and its most repetitive one are named only when each crosses its checkpoint, so a file reading healthy names nothing rather than offering its least healthy paragraph as a finding.
|
|
70
|
-
|
|
71
|
-
Neither number gates and neither names a file wrong. This is a weaker claim than the one the weight checkpoints make, because a healthy range differs by surface: a catalog entry is several short sentences carrying one fact each, and a page arguing a decision is not, so one range applied across the corpus would report the surfaces that are correct. The run therefore states where the numbers came from beside them, and the counts are what a reader compares against.
|
|
72
|
-
|
|
73
|
-
A reading of that spread across the whole corpus is what backs the range above, taken once against this repository's own tracked markdown rather than against a target project's.
|
|
74
|
-
|
|
75
|
-
That reading travels with the command rather than staying here. `BASELINE` in `src/markdown/structure.ts` carries the overall share, the per-file range, and the ten-paragraph floor beneath which a file's own rate says nothing, and the run prints all four in the legend beside the rate it measured. A count with no range beside it reads as a finding, and naming that a healthy range differs by surface states that a range exists rather than what it looks like. This page is toolkit-internal, so a reader running the command in a project that installed no standards would otherwise have two counts and nothing to place them against.
|
|
76
|
-
|
|
77
|
-
Two of the rules `write-human` states are deliberately not implemented. A sentence's grammatical shape and whether it carries a finite verb each need a parse rather than a match, and an imperative would read as a defect under a pattern that approximated either. The verbless share is the measure closest to the reported symptom, which is exactly why shipping it wrong would discredit the two that hold.
|
|
78
|
-
|
|
79
|
-
The condition on that was something identifying a finite verb rather than guessing at one, and two parsers have now been run against it over 11,389 paragraph sentences. They disagree by a factor of four. `compromise` reports 2 percent and reads a fronted past participle as a finite verb, so `Measured at <sha> on <date>.` counts as carrying one. `wink-pos-tagger` reports 9 percent, fixes that class, and is still wrong on roughly three in four, because an imperative's verb tags as a proper noun and a noun-ambiguous predicate tags as a noun, which makes `Each maps to a skill.` read verbless. Separating those needs to know which token is the predicate, and that is syntax rather than a tag. The measure stays unimplemented, now against a mechanism rather than against the idea of one.
|
|
80
|
-
|
|
81
|
-
## Length
|
|
82
|
-
|
|
83
|
-
The Length step sums rendered lines over the whole source, frontmatter and fenced blocks included, and lists each document past the 300-line ceiling, longest first. A changelog and a document carrying a whole-line `<!-- canon-length-exempt: <reason> -->` outside a fence are counted in one line rather than listed. Each `--json` entry carries `renderedLines` and `exempt`, the stated reason or `null`, and `checkpoints` carries `ceiling`.
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: The pull request evidence layout
|
|
3
|
-
description: How canon pr evidence groups screenshots into one block per view with a row per width and a column per theme, when a base column appears, where a name outside the form lands, how the commit line links, and when the blocks open
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# The pull request evidence layout
|
|
7
|
-
|
|
8
|
-
`canon pr evidence` renders the screenshots of a pull request as blocks a
|
|
9
|
-
reviewer reads by view. The record behind them, and the reasons a run can
|
|
10
|
-
refuse, are in `canon docs pr-evidence`.
|
|
11
|
-
|
|
12
|
-
## One block per view
|
|
13
|
-
|
|
14
|
-
A case name that ends in `-dark-<width>` or `-light-<width>` belongs to the
|
|
15
|
-
view named by everything before that suffix, so `menu-open-light-1440` is the
|
|
16
|
-
`menu-open` view. The name is split from the right because a view may carry
|
|
17
|
-
hyphens of its own.
|
|
18
|
-
|
|
19
|
-
Each view is one `<details>` block. Its summary carries the view and its case
|
|
20
|
-
count, a row holds one width in ascending number order, and a column holds one
|
|
21
|
-
theme:
|
|
22
|
-
|
|
23
|
-
```markdown
|
|
24
|
-
| Width | Dark | Light |
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
A view with any case already at the base takes a base and a head column per
|
|
28
|
-
theme, and a case the pull request added shows `*(new)*` in its base cell:
|
|
29
|
-
|
|
30
|
-
```markdown
|
|
31
|
-
| Width | Dark base | Dark head | Light base | Light head |
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
A cell with no case in it stays empty. A theme no case of the view carries has
|
|
35
|
-
no column. A state under a named directory titles its blocks
|
|
36
|
-
`<state> / <view>`, so two states holding one view never repeat a name.
|
|
37
|
-
|
|
38
|
-
## Names outside the form
|
|
39
|
-
|
|
40
|
-
A case name that does not split into a view, a theme, and a width lands in a
|
|
41
|
-
flat `Case | Base | Head` block for its state, or `Case | Head` when every case
|
|
42
|
-
in it is new. Nothing is dropped, so `board.png` or a name with no width still
|
|
43
|
-
shows.
|
|
44
|
-
|
|
45
|
-
## The commit line
|
|
46
|
-
|
|
47
|
-
Under `## Evidence`, the Base and Head line names each commit as a short sha
|
|
48
|
-
that links to the full commit:
|
|
49
|
-
|
|
50
|
-
```markdown
|
|
51
|
-
**Base:** [`<base>`](https://github.com/<repo>/commit/<base-sha>) · **Head:** [`<head>`](https://github.com/<repo>/commit/<head-sha>)
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
A reader opens what the screenshots were taken against in one click. The base
|
|
55
|
-
is the merge base the compare endpoint returns, not trunk's tip.
|
|
56
|
-
|
|
57
|
-
## When the blocks open
|
|
58
|
-
|
|
59
|
-
Every block opens while the comment carries six images or fewer, counting one
|
|
60
|
-
per case for the head plus one per case that is not new. Past that every block
|
|
61
|
-
closes, so the whole comment is open or closed together.
|
|
62
|
-
|
|
63
|
-
## What reads the body back
|
|
64
|
-
|
|
65
|
-
The case count that `would-empty` compares is the number of head images in the
|
|
66
|
-
body. It holds for the grouped rows, where one row carries up to two cases, and
|
|
67
|
-
for every layout posted before, so a comment rendered under an older shape
|
|
68
|
-
still counts. The bold `**Base:**` label and the `<details>` blocks are
|
|
69
|
-
unchanged, which keeps the address reader and the review skills working on both
|
|
70
|
-
layouts. An older comment keeps its shape until the next run edits it in place.
|
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: The pull request evidence comparison
|
|
3
|
-
description: What canon pr evidence compares, the marker that lets it edit its own comment rather than duplicate it, the refusal reasons it names, what the --check read reports as owed, and why the comparison anchors at the merge base rather than the previous push
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# The pull request evidence comparison
|
|
7
|
-
|
|
8
|
-
`canon pr evidence` renders one comment naming every changed image under an
|
|
9
|
-
`evidence/` path segment, comparing each against the pull request's merge base.
|
|
10
|
-
`git-pr` posts it when a pull request opens or is edited, and `git-followup`
|
|
11
|
-
posts it again after every later push, so a reviewer never has to open Files
|
|
12
|
-
Changed to see what a case looked like before and after.
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
canon pr evidence
|
|
16
|
-
canon pr evidence 1341 --json
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Why the comparison anchors at the merge base
|
|
20
|
-
|
|
21
|
-
The comparison is always base against the current head, never the previous
|
|
22
|
-
push against the new one. A follow-up only ever moves the after side of the
|
|
23
|
-
comment, so what the comment claims can only grow to match what the branch
|
|
24
|
-
actually shows, and a reviewer who opens it midway through a review round
|
|
25
|
-
never reads a stale before image describing an intermediate commit nobody is
|
|
26
|
-
looking at anymore.
|
|
27
|
-
|
|
28
|
-
## What counts as evidence
|
|
29
|
-
|
|
30
|
-
A changed path qualifies when one of its segments is literally `evidence` and
|
|
31
|
-
its filename carries an image extension (`png`, `jpg`, `jpeg`, `gif`, `webp`,
|
|
32
|
-
`avif`, `svg`). The second half of that test exists because an `evidence/`
|
|
33
|
-
folder holds whatever else a project keeps beside its captures. This
|
|
34
|
-
repository's own tree carries eight `.md` files, two `.sh` scripts, a `.tsv`,
|
|
35
|
-
a `.json`, and an `.html` file against a single `.png`, and every one of them
|
|
36
|
-
would render as a broken image embed without the extension filter.
|
|
37
|
-
|
|
38
|
-
## What the record carries
|
|
39
|
-
|
|
40
|
-
The record groups every evidence path by state, the remainder of its
|
|
41
|
-
directory under the `evidence/` segment, and within a state by filename stem,
|
|
42
|
-
so a `before/hero.png` and an `after/hero.png` naming the same case group as
|
|
43
|
-
one entry, not two files. Each entry carries whether it existed at the base
|
|
44
|
-
commit, so the comment shows a base image or marks it new. Each `<img>` takes
|
|
45
|
-
its PNG width, at most 1000. `canon docs pr-evidence-layout` covers how the body
|
|
46
|
-
groups those entries by view.
|
|
47
|
-
|
|
48
|
-
`reason` on the record is what a caller branches on, not the exit code:
|
|
49
|
-
|
|
50
|
-
| Reason | What it means |
|
|
51
|
-
| ---------------------- | --------------------------------------------------------------------------------------- |
|
|
52
|
-
| `ok` | A body was rendered. `commentId` is set when a marked comment already exists. |
|
|
53
|
-
| `no-evidence` | No `evidence/` segment in the diff and no `--checklist` or `--preview`. A silent no-op. |
|
|
54
|
-
| `unreadable-checklist` | `--checklist` named a path that could not be read, or one holding nothing. |
|
|
55
|
-
| `gh-missing` | `gh` is not on the path, so no pull request could be resolved. |
|
|
56
|
-
| `gh-failed` | `gh` could not answer for this repository or branch, or read its comments. |
|
|
57
|
-
| `no-branch` | The pull request carries no head branch name. |
|
|
58
|
-
| `no-object-head` | The pull request object reported no head commit. |
|
|
59
|
-
| `no-base` | GitHub reported no merge base for the pull request. |
|
|
60
|
-
| `unreadable-changes` | GitHub could not list what the pull request changed. |
|
|
61
|
-
| `would-empty` | The render holds no cases and the marked comment holds some. No body. |
|
|
62
|
-
| `check-writes` | `--check` was passed with `--preview`, `--local`, or `--checklist`. |
|
|
63
|
-
|
|
64
|
-
`no-evidence` is not a refusal a caller reports. A project on a stack that
|
|
65
|
-
carries no evidence path, such as `base` or `python`, hits this reason on
|
|
66
|
-
every pull request and posts nothing, which is the correct behavior rather
|
|
67
|
-
than a gap.
|
|
68
|
-
|
|
69
|
-
Both `ok` and `no-evidence` also report what the marked comment already
|
|
70
|
-
shows a reviewer, each field present only when that comment holds it:
|
|
71
|
-
|
|
72
|
-
| Field | What it carries |
|
|
73
|
-
| ----------- | ----------------------------------------------------------------- |
|
|
74
|
-
| `preview` | The hosted `**Preview:**` address on the comment's address line. |
|
|
75
|
-
| `local` | The `**Local preview:**` address beside it. |
|
|
76
|
-
| `checklist` | The checklist between its delimiters, with any ticked boxes kept. |
|
|
77
|
-
| `boxes` | Each box's `number`, `text`, tick, `stamp`, and `isTaste`. |
|
|
78
|
-
|
|
79
|
-
These come from the comment already posted, never from the flags the call
|
|
80
|
-
passed, so a skill driving a review reads which address and which checklist a
|
|
81
|
-
reviewer has without parsing the comment itself. A checklist posted raw, which
|
|
82
|
-
only the fallback for a refused render does now, carries no marker, so the
|
|
83
|
-
record reports none of the three for it. Reading
|
|
84
|
-
them means the thread is read before the `no-evidence` answer too, so an
|
|
85
|
-
unreadable thread refuses as `gh-failed` on both reasons rather than
|
|
86
|
-
reporting the fields absent.
|
|
87
|
-
|
|
88
|
-
`ok` also carries `states`, the comparison the body renders as data: each
|
|
89
|
-
state's items with `path`, `stem`, `added`, and `width` and `baseWidth` when
|
|
90
|
-
read. `review-ui` matches a frame against it so it publishes no image the
|
|
91
|
-
worker's evidence already shows. `canon docs pr-frames` covers that store.
|
|
92
|
-
`widthUnread` lists a failed read as `head:<path>` or `base:<path>`.
|
|
93
|
-
|
|
94
|
-
## What `[number]` selects, and what it does not
|
|
95
|
-
|
|
96
|
-
Naming a number picks the pull request the whole record describes: its head
|
|
97
|
-
commit, its merge base, its changed set, and the marked comment to edit in
|
|
98
|
-
place. The changed paths and whether each was added or modified come from the
|
|
99
|
-
pull request's files endpoint, paged to the end, and the merge base comes from
|
|
100
|
-
the compare endpoint, so the record is the same from any checkout. A run from
|
|
101
|
-
the main worktree against a branch built elsewhere renders that branch's
|
|
102
|
-
comparison.
|
|
103
|
-
|
|
104
|
-
The trade is that the verb no longer sees evidence that is uncommitted or
|
|
105
|
-
unpushed, which the comment's head-pinned image links could not show anyway.
|
|
106
|
-
A path the pull request renamed or copied counts as added, since the new path
|
|
107
|
-
has no counterpart at the merge base, so a rename loses its before image and
|
|
108
|
-
reads as new. A path the pull request removed is dropped, since it has no
|
|
109
|
-
head image to show. A failed files read refuses as `unreadable-changes` rather
|
|
110
|
-
than rendering a short set, and a missing merge base refuses as `no-base`.
|
|
111
|
-
|
|
112
|
-
## A render never empties a comment that carries cases
|
|
113
|
-
|
|
114
|
-
When the render holds no cases and the marked comment holds some, the verb
|
|
115
|
-
refuses `would-empty` and prints no body. A render with no cases cannot tell a
|
|
116
|
-
case removed on purpose from a short read, so the destructive direction needs a
|
|
117
|
-
person: they edit the comment directly. The record keeps `commentId` and the
|
|
118
|
-
carried fields, so the caller can still find the comment. A comment holding
|
|
119
|
-
only a preview or a checklist has no cases to lose and still re-renders `ok`.
|
|
120
|
-
`no-evidence` without a flag returns before any render, so the guard touches
|
|
121
|
-
only `--preview`, `--local`, and `--checklist` calls.
|
|
122
|
-
|
|
123
|
-
## One comment, found by its own marker
|
|
124
|
-
|
|
125
|
-
Every body this verb renders ends with a trailing marker naming the head it
|
|
126
|
-
describes:
|
|
127
|
-
|
|
128
|
-
```markdown
|
|
129
|
-
<!-- pr-evidence: head=<sha> -->
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
`canon pr evidence` reads that marker back off every comment on the pull
|
|
133
|
-
request, the same way `canon pr review-state` reads its own marker off a
|
|
134
|
-
review body, and reports the REST id of whichever comment carries it as
|
|
135
|
-
`commentId`. A caller with no `commentId` posts a new comment. A caller
|
|
136
|
-
holding one edits that comment in place with a `PATCH` rather than posting a
|
|
137
|
-
second one.
|
|
138
|
-
|
|
139
|
-
Putting the lookup here, in the one place both `git-pr` and `git-followup`
|
|
140
|
-
call, is what keeps two close-out comments from landing beside each other the
|
|
141
|
-
way `review-pr` once posted, before that skill's own guard existed. It is
|
|
142
|
-
also why this verb renders the whole comment body rather than handing each
|
|
143
|
-
skill a record to format on its own: a fix to the table shape or the
|
|
144
|
-
details wrapper lands once, not twice.
|
|
145
|
-
|
|
146
|
-
## The preview line
|
|
147
|
-
|
|
148
|
-
Every body opens with `## Evidence`. Under it sits one address line carrying
|
|
149
|
-
whichever previews apply, joined by a middle dot:
|
|
150
|
-
|
|
151
|
-
```plaintext
|
|
152
|
-
## Evidence
|
|
153
|
-
|
|
154
|
-
**Preview:** <url> · **Local preview:** <url>
|
|
155
|
-
|
|
156
|
-
**Base:** [`<base>`](<base-commit-url>) · **Head:** [`<head>`](<head-commit-url>)
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
The Base and Head line follows only when the comment carries screenshots.
|
|
160
|
-
|
|
161
|
-
`--preview <url>` puts the branch's hosted address on that line, and a run
|
|
162
|
-
without it carries forward the address the marked comment already holds. With
|
|
163
|
-
no evidence in the diff and an address in hand, the body is the heading, the
|
|
164
|
-
address line, and the marker alone, reported as `ok`. `canon docs pr-preview`
|
|
165
|
-
covers where the address comes from.
|
|
166
|
-
|
|
167
|
-
A carried hosted address is dropped when a deploy workflow resolves and its
|
|
168
|
-
push path filter matches no path the pull request changed, since the site it
|
|
169
|
-
links shows none of the change. An explicit `--preview` is always kept.
|
|
170
|
-
|
|
171
|
-
The carry-forward reads every line above the commit line, the checklist, and
|
|
172
|
-
the comparison for each prefix, wherever it sits. A comment posted before the
|
|
173
|
-
heading opened the body, with each address on a line of its own at the top,
|
|
174
|
-
reads the same way, so an open pull request keeps its links on its first
|
|
175
|
-
re-render.
|
|
176
|
-
|
|
177
|
-
## The checklist line
|
|
178
|
-
|
|
179
|
-
`--checklist <path>` closes the body with a visual checklist, below the
|
|
180
|
-
comparison it annotates, so one comment carries the preview address, the
|
|
181
|
-
screenshots, and what a reviewer has to look at. The file is what
|
|
182
|
-
`canon:ui-checklist` writes to `.canon/tmp/handoff/ui-checklist/<slug>.md`, and
|
|
183
|
-
`git-pr` passes it here rather than posting it as a second comment.
|
|
184
|
-
|
|
185
|
-
A run without the option carries forward whatever checklist the marked comment
|
|
186
|
-
already holds, the same way the preview address is carried. That is what keeps
|
|
187
|
-
`git-followup`'s re-render after a push from dropping the checklist, since
|
|
188
|
-
`git-pr` deletes the handoff once the first post reports success and no later
|
|
189
|
-
call has a file to pass. `canon docs pr-tick` covers what a tick carries.
|
|
190
|
-
|
|
191
|
-
The option decides `no-evidence` on its own. A branch with a checklist and no
|
|
192
|
-
changed evidence image renders `ok` with a marked body holding the checklist,
|
|
193
|
-
so the checklist always lands in the one comment a later call finds and edits.
|
|
194
|
-
The raw post survives only as the caller's fallback when the render is refused.
|
|
195
|
-
A path that cannot be read, or one holding nothing, refuses as
|
|
196
|
-
`unreadable-checklist` rather than rendering without it: the caller deletes the
|
|
197
|
-
handoff once a post succeeds, so a silently dropped checklist is the only copy
|
|
198
|
-
gone.
|
|
199
|
-
|
|
200
|
-
## The local preview line
|
|
201
|
-
|
|
202
|
-
`--local <url>` adds `**Local preview:** <url>` to the address line, after the
|
|
203
|
-
hosted segment when there is one and alone when there is not. A run without the
|
|
204
|
-
option carries forward the local address the marked comment already holds, the
|
|
205
|
-
same as the other two.
|
|
206
|
-
|
|
207
|
-
The option does not turn `no-evidence` into `ok` on its own. A branch with a
|
|
208
|
-
dev server running and no rendered change would otherwise get a comment holding
|
|
209
|
-
a link and nothing else. Together with `--checklist` the link and the
|
|
210
|
-
checklist land in one comment.
|
|
211
|
-
`canon docs pr-local` covers where the address comes from and how the line is
|
|
212
|
-
removed at close.
|
|
213
|
-
|
|
214
|
-
## What a pull request is still owed
|
|
215
|
-
|
|
216
|
-
`--check` reads the same changed set and the same thread, renders no body, and
|
|
217
|
-
reports which steps of the ship chain that run after the pull request opens
|
|
218
|
-
never landed on it. It reads the pull request rather than any session's account
|
|
219
|
-
of what it ran, so a session that stopped after opening the pull request leaves
|
|
220
|
-
a branch the check can tell apart from one that needed neither step.
|
|
221
|
-
|
|
222
|
-
```bash
|
|
223
|
-
canon pr evidence 1341 --check --json
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
| Reason | What it means |
|
|
227
|
-
| --------- | ------------------------------------------------------------------ |
|
|
228
|
-
| `settled` | Nothing is owed. `owed` is empty. |
|
|
229
|
-
| `owed` | `owed` lists `evidence`, `preview`, or both, always in that order. |
|
|
230
|
-
|
|
231
|
-
- `evidence` is owed when the changed set carries an evidence image and no
|
|
232
|
-
comment carries the marker.
|
|
233
|
-
- `preview` is owed when the pull request has a marked comment or an evidence
|
|
234
|
-
change, a deploy workflow resolves in the checkout the verb runs from, its
|
|
235
|
-
push path filter matches a path the pull request changed, and the marked
|
|
236
|
-
comment carries no `**Preview:**` address. A `**Local preview:**` address
|
|
237
|
-
does not satisfy it. A project deploying nothing is never owed a preview,
|
|
238
|
-
and neither is a branch its deploy does not build from.
|
|
239
|
-
|
|
240
|
-
The record carries `owed`, `commentId` when a marked comment exists, and the
|
|
241
|
-
same `preview`, `local`, and `checklist` fields the other reasons carry, so a
|
|
242
|
-
caller reads one shape. It never carries `body`, so a writer branching on `ok`
|
|
243
|
-
and posting `body` cannot act on a check record. Passing `--preview`, `--local`,
|
|
244
|
-
or `--checklist` with it refuses as `check-writes` before any `gh` call, since
|
|
245
|
-
those ask a read to write.
|
|
246
|
-
|
|
247
|
-
The thread cannot separate a skipped preview step from a failed one. A pull
|
|
248
|
-
request whose deploy failed or timed out reads as owing a preview, and the
|
|
249
|
-
session that ran it holds the cause. A checklist-only branch posts a marked
|
|
250
|
-
comment, so it reads as owing a preview once that comment exists and a deploy
|
|
251
|
-
workflow resolves. The deploy workflow is read from the checkout rather than
|
|
252
|
-
the pull request's head, so one adding or removing its own reads trunk's.
|
|
253
|
-
|
|
254
|
-
An unreadable thread refuses as `gh-failed` rather than reporting `settled` off
|
|
255
|
-
a thread it never read. The check skips the merge base read, which only the
|
|
256
|
-
render needs, so it never refuses `no-base`. The orchestrator's draft lift is
|
|
257
|
-
the caller, and lifts only on `settled`, so a refusal holds it the same as
|
|
258
|
-
`owed` does.
|
|
259
|
-
|
|
260
|
-
## When the comment opens
|
|
261
|
-
|
|
262
|
-
The comment opens every block while it carries six images or fewer and closes
|
|
263
|
-
every block past that. A line under `## Evidence` names the compared base and
|
|
264
|
-
head as linked short shas, which tells a reader whether the images match the
|
|
265
|
-
latest push. `canon docs pr-evidence-layout` covers the count and the blocks.
|
|
266
|
-
|
|
267
|
-
## What the comment still leaves to GitHub
|
|
268
|
-
|
|
269
|
-
GitHub already draws its own before-and-after comparison on the Files Changed
|
|
270
|
-
tab for any tracked image that changed. This comment does not make that view
|
|
271
|
-
redundant. The diff view shows what moved between two commits a reader has
|
|
272
|
-
already opened, and the comment is what lets a reader see the same comparison
|
|
273
|
-
without opening it at all.
|
package/docs/agents/pr-frames.md
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: The pull request frame store
|
|
3
|
-
description: How canon pr frames pushes a UI review frame to a never-merged branch through the GitHub API and returns a branch-path link, which ref it writes, the pass segment that keeps an earlier image fixed, the refusal reasons it names, and how --drop and --prune rewrite the branch so a dropped frame leaves history
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# The pull request frame store
|
|
7
|
-
|
|
8
|
-
`canon pr frames` gives a review comment an image it can embed. `review-ui`
|
|
9
|
-
drives a pull request's checklist and captures a frame per box, and a frame
|
|
10
|
-
on the reviewer's disk resolves for nobody else. The verb pushes one frame to
|
|
11
|
-
the `canon/frames` branch and returns a link to its path there.
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
canon pr frames 1341 --add frames/3.png --box 3 --head <sha> --pass 20261002T154450Z --json
|
|
15
|
-
canon pr frames 1341 --add frames/3-dark.png --box 3 --theme dark --head <sha> --pass 20261002T154450Z --json
|
|
16
|
-
canon pr frames 1341 --drop --json
|
|
17
|
-
canon pr frames --prune 30 --json
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## What it writes
|
|
21
|
-
|
|
22
|
-
An add writes `refs/heads/canon/frames` and no other ref. Every call goes
|
|
23
|
-
through the GitHub git data API, being blobs, trees, commits, and that one ref,
|
|
24
|
-
so nothing is checked out, no worktree is entered, and neither `main` nor any
|
|
25
|
-
branch a pull request holds is touched. The branch never merges.
|
|
26
|
-
|
|
27
|
-
A frame lands at `pr-<number>/<short-head>/<pass>/box-<n>.png`, or at
|
|
28
|
-
`box-<n>-<theme>.png` when `--theme` names `dark` or `light`, so two shots of
|
|
29
|
-
one box in one pass never take the same path. A frame without `--theme` keeps
|
|
30
|
-
the plain form. `--head` names
|
|
31
|
-
the commit the pass drove, 7 to 40 lowercase hex characters, and defaults to
|
|
32
|
-
the head the pull request object reports. `--pass` is the instant the pass
|
|
33
|
-
started, in compact UTC as `date -u +%Y%m%dT%H%M%SZ` prints it, which
|
|
34
|
-
`review-ui` records once at its first step. A second pass at the same head and
|
|
35
|
-
box therefore writes a new file rather than replacing the image an earlier
|
|
36
|
-
comment shows, which matters when a preview is minted again at one head.
|
|
37
|
-
|
|
38
|
-
`link` uses the same `blob/<ref>/<path>?raw=true` form as the evidence comment,
|
|
39
|
-
naming the `canon/frames` branch rather than a commit. Every drop rewrites the
|
|
40
|
-
branch, and a link pinned to a commit would stop resolving for every other pull
|
|
41
|
-
request's frames once GitHub collects the commit it names. A path link lives
|
|
42
|
-
exactly as long as its file, so it survives every rewrite that drops another
|
|
43
|
-
pull request and ends only when its own is dropped.
|
|
44
|
-
|
|
45
|
-
The first `--add` creates the branch with a root commit holding the
|
|
46
|
-
frame, so a project needs no setup. An add only fast-forwards the ref. When
|
|
47
|
-
another writer moved it between the read and the move, the add rebuilds on the
|
|
48
|
-
new tip, up to three times, before refusing as `ref-conflict`.
|
|
49
|
-
|
|
50
|
-
Only a frame of the address the pass drove belongs here. The branch is as
|
|
51
|
-
public as the repository, so a frame of a private or pre-release state would
|
|
52
|
-
be published with it.
|
|
53
|
-
|
|
54
|
-
## What the record carries
|
|
55
|
-
|
|
56
|
-
`reason` on the record is what a caller branches on, not the exit code:
|
|
57
|
-
|
|
58
|
-
| Reason | What it means |
|
|
59
|
-
| ------------------ | -------------------------------------------------------------------------------- |
|
|
60
|
-
| `ok` | An add pushed, or a drop or prune finished, including one that removed nothing. |
|
|
61
|
-
| `bad-mode` | Not exactly one of `--add`, `--drop`, `--prune`, or a number with `--prune`. |
|
|
62
|
-
| `no-number` | `--add` or `--drop` named no pull request. |
|
|
63
|
-
| `bad-box` | `--add` carried no positive `--box`. |
|
|
64
|
-
| `bad-head` | `--head`, or the head the pull request reported, is not a 7 to 40 character sha. |
|
|
65
|
-
| `bad-pass` | `--add` carried no `--pass` stamp in compact UTC. |
|
|
66
|
-
| `bad-theme` | `--theme` is neither `dark` nor `light`, or came without `--add`. |
|
|
67
|
-
| `bad-days` | `--prune` carried no positive number of days. |
|
|
68
|
-
| `unreadable-frame` | The `--add` file is missing, empty, or not a PNG. Nothing is called. |
|
|
69
|
-
| `read-only` | GitHub refused a write with 403 or 404, which is what a fork's token gets. |
|
|
70
|
-
| `unreadable-tip` | The branch exists and could not be read. |
|
|
71
|
-
| `push-failed` | A write failed partway and the ref did not move. |
|
|
72
|
-
| `ref-conflict` | Another writer kept moving the ref through every attempt. |
|
|
73
|
-
| `no-object-head` | No `--head` and the pull request reported none. |
|
|
74
|
-
| `gh-missing` | `gh` is not on the path. |
|
|
75
|
-
| `gh-failed` | `gh` could not name the repository or read the pull request. |
|
|
76
|
-
|
|
77
|
-
An add's `ok` record carries `link`, `commit`, `path`, `box`, `theme` when one was passed, `head`, `pass`,
|
|
78
|
-
and `created`, which is true when the add made the branch. A drop's carries
|
|
79
|
-
`removed`, the pull requests whose folders went, plus `commit` for the rewrite
|
|
80
|
-
or `deleted` when it emptied the branch. A prune adds `kept` and `unread`.
|
|
81
|
-
|
|
82
|
-
`review-ui` reads every reason but `ok` as a cue to describe the frame in words
|
|
83
|
-
and name the reason, so a refused push never fails the pass.
|
|
84
|
-
|
|
85
|
-
## Dropping frames
|
|
86
|
-
|
|
87
|
-
A plain delete commit would keep every image reachable through history, so
|
|
88
|
-
`--drop` and `--prune` write one root commit holding everything else and
|
|
89
|
-
force-move the ref to it. A rewrite that leaves the branch empty deletes it,
|
|
90
|
-
and the next add recreates it. Dropping a pull request with no frames, or on a
|
|
91
|
-
missing branch, reports `ok` with nothing removed, so a scheduled run never
|
|
92
|
-
fails on an empty branch.
|
|
93
|
-
|
|
94
|
-
`--prune <days>` reads every `pr-<n>/` folder, asks GitHub for each pull
|
|
95
|
-
request's state, and drops every one reading closed with a close date more
|
|
96
|
-
than that many days ago, in a single rewrite. It keeps one still open, one
|
|
97
|
-
reopened after closing, one closed exactly the given days ago, and one whose
|
|
98
|
-
state could not be read, listing that last kind under `unread`.
|
|
99
|
-
|
|
100
|
-
## The legacy branch
|
|
101
|
-
|
|
102
|
-
Frames lived on `canon-frames` before the rename to `canon/frames`. An add
|
|
103
|
-
never writes it. `--drop` and `--prune` also run against it after the
|
|
104
|
-
current branch, remove only, and delete it once empty. `--prune` drains it
|
|
105
|
-
as its pull requests expire, and `--drop` clears one pull request at once.
|
|
106
|
-
The record carries `legacy: true` when that
|
|
107
|
-
pass changed the ref, and its `removed` list folds both branches in, naming
|
|
108
|
-
a pull request once. A missing or unreadable legacy ref never fails a run
|
|
109
|
-
the current branch finished.
|
|
110
|
-
|
|
111
|
-
A link minted before the rename points at `blob/canon-frames/...` and keeps
|
|
112
|
-
resolving until its pull request has been closed 30 days or `--drop` runs.
|
|
113
|
-
|
|
114
|
-
This repository runs `--prune 30` daily from
|
|
115
|
-
`.github/workflows/pr-frames-cleanup.yml`. A frame's file stays on the branch
|
|
116
|
-
until its own pull request has been closed for 30 days, so a link in a review
|
|
117
|
-
comment keeps resolving for about a month after its pull request closes,
|
|
118
|
-
whatever other pull requests the branch drops in between. A target project
|
|
119
|
-
carries no such workflow yet and keeps its frames until someone runs `--drop`.
|
|
120
|
-
|
|
121
|
-
## What a rewrite does not do
|
|
122
|
-
|
|
123
|
-
A force-move leaves the old commits unreachable without purging them. GitHub
|
|
124
|
-
serves an unreachable commit by sha until it collects it, so a dropped frame
|
|
125
|
-
stays reachable to anyone holding a sha from an earlier record, and a frame
|
|
126
|
-
holding sensitive content needs a purge request to GitHub. Its path link stops
|
|
127
|
-
resolving at the drop, since the branch no longer carries the file.
|
|
128
|
-
|
|
129
|
-
A drop racing an add can lose the add's frame, since GitHub's ref update has no
|
|
130
|
-
compare-and-swap for a force-move. The drop builds from the tip it reads, and
|
|
131
|
-
the window is the length of one rewrite.
|