proctolog 0.1.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +23 -0
- data/README.md +178 -0
- data/app/controllers/proctolog/acceptances_controller.rb +29 -0
- data/app/controllers/proctolog/application_controller.rb +32 -0
- data/app/controllers/proctolog/bursts_controller.rb +34 -0
- data/app/controllers/proctolog/choices_controller.rb +30 -0
- data/app/controllers/proctolog/code_reviews_controller.rb +26 -0
- data/app/controllers/proctolog/decisions_controller.rb +33 -0
- data/app/controllers/proctolog/entries_controller.rb +14 -0
- data/app/controllers/proctolog/evidence_controller.rb +23 -0
- data/app/controllers/proctolog/freshness_controller.rb +27 -0
- data/app/controllers/proctolog/good_to_go_controller.rb +29 -0
- data/app/controllers/proctolog/memberships_controller.rb +20 -0
- data/app/controllers/proctolog/mentions_controller.rb +16 -0
- data/app/controllers/proctolog/moments_controller.rb +26 -0
- data/app/controllers/proctolog/note_params.rb +24 -0
- data/app/controllers/proctolog/notes_controller.rb +56 -0
- data/app/controllers/proctolog/open_pull_requests_controller.rb +59 -0
- data/app/controllers/proctolog/pictures_controller.rb +27 -0
- data/app/controllers/proctolog/prompts_controller.rb +28 -0
- data/app/controllers/proctolog/pull_request_scoped.rb +21 -0
- data/app/controllers/proctolog/pull_requests_controller.rb +34 -0
- data/app/controllers/proctolog/put_away_controller.rb +19 -0
- data/app/controllers/proctolog/recordings_controller.rb +28 -0
- data/app/controllers/proctolog/rendered_pieces_controller.rb +11 -0
- data/app/controllers/proctolog/review_data_controller.rb +12 -0
- data/app/controllers/proctolog/rules_controller.rb +20 -0
- data/app/controllers/proctolog/scenario_notes_controller.rb +26 -0
- data/app/controllers/proctolog/scenario_scoped.rb +21 -0
- data/app/controllers/proctolog/scenarios_controller.rb +67 -0
- data/app/controllers/proctolog/sitting_servers_controller.rb +30 -0
- data/app/controllers/proctolog/waiting_controller.rb +14 -0
- data/app/controllers/proctolog/with_decisions.rb +28 -0
- data/app/helpers/proctolog/bursts_helper.rb +52 -0
- data/app/helpers/proctolog/decisions_helper.rb +102 -0
- data/app/helpers/proctolog/desk_helper.rb +61 -0
- data/app/helpers/proctolog/mentions_helper.rb +27 -0
- data/app/helpers/proctolog/open_pull_requests_helper.rb +31 -0
- data/app/helpers/proctolog/prompts_helper.rb +21 -0
- data/app/helpers/proctolog/pull_requests_helper.rb +67 -0
- data/app/helpers/proctolog/recordings_helper.rb +30 -0
- data/app/helpers/proctolog/rounds_helper.rb +27 -0
- data/app/helpers/proctolog/scenarios_helper.rb +123 -0
- data/app/helpers/proctolog/standings_helper.rb +80 -0
- data/app/jobs/proctolog/application_job.rb +8 -0
- data/app/jobs/proctolog/ask_for_release_job.rb +9 -0
- data/app/jobs/proctolog/fetch_pictures_ahead_job.rb +36 -0
- data/app/jobs/proctolog/prune_fresh_profiles_job.rb +9 -0
- data/app/jobs/proctolog/read_mentions_ahead_job.rb +12 -0
- data/app/models/proctolog/acceptance.rb +47 -0
- data/app/models/proctolog/app.rb +92 -0
- data/app/models/proctolog/browser.rb +42 -0
- data/app/models/proctolog/burst.rb +268 -0
- data/app/models/proctolog/burst_notices.rb +143 -0
- data/app/models/proctolog/chapters.rb +42 -0
- data/app/models/proctolog/check.rb +122 -0
- data/app/models/proctolog/choices.rb +112 -0
- data/app/models/proctolog/code_review.rb +251 -0
- data/app/models/proctolog/decision_record.rb +12 -0
- data/app/models/proctolog/decisions.rb +199 -0
- data/app/models/proctolog/description.rb +165 -0
- data/app/models/proctolog/difference.rb +138 -0
- data/app/models/proctolog/doctor.rb +127 -0
- data/app/models/proctolog/evidence.rb +29 -0
- data/app/models/proctolog/failure.rb +7 -0
- data/app/models/proctolog/focus.rb +48 -0
- data/app/models/proctolog/fresh_sitting.rb +35 -0
- data/app/models/proctolog/github.rb +353 -0
- data/app/models/proctolog/handover/brief.rb +138 -0
- data/app/models/proctolog/handover/layers.rb +128 -0
- data/app/models/proctolog/handover/places.rb +98 -0
- data/app/models/proctolog/handover/taken.rb +41 -0
- data/app/models/proctolog/handover/worklist.rb +35 -0
- data/app/models/proctolog/handover.rb +123 -0
- data/app/models/proctolog/housekeeping.rb +23 -0
- data/app/models/proctolog/kit.rb +36 -0
- data/app/models/proctolog/marks.rb +130 -0
- data/app/models/proctolog/membership.rb +91 -0
- data/app/models/proctolog/mentions.rb +117 -0
- data/app/models/proctolog/note.rb +94 -0
- data/app/models/proctolog/outside.rb +45 -0
- data/app/models/proctolog/overlay/brief.rb +52 -0
- data/app/models/proctolog/overlay/written.rb +33 -0
- data/app/models/proctolog/overlay.rb +87 -0
- data/app/models/proctolog/owner.rb +16 -0
- data/app/models/proctolog/pick.rb +47 -0
- data/app/models/proctolog/picture.rb +138 -0
- data/app/models/proctolog/pieces_rendering.rb +40 -0
- data/app/models/proctolog/project.rb +118 -0
- data/app/models/proctolog/pull_request.rb +89 -0
- data/app/models/proctolog/recording.rb +194 -0
- data/app/models/proctolog/release.rb +59 -0
- data/app/models/proctolog/rendering.rb +303 -0
- data/app/models/proctolog/reports.rb +66 -0
- data/app/models/proctolog/response_files.rb +55 -0
- data/app/models/proctolog/rounds.rb +305 -0
- data/app/models/proctolog/route.rb +151 -0
- data/app/models/proctolog/rules.rb +121 -0
- data/app/models/proctolog/scenario.rb +126 -0
- data/app/models/proctolog/server.rb +273 -0
- data/app/models/proctolog/since.rb +108 -0
- data/app/models/proctolog/size.rb +30 -0
- data/app/models/proctolog/standing.rb +132 -0
- data/app/models/proctolog/theme.rb +40 -0
- data/app/models/proctolog/unopened/numbers.rb +48 -0
- data/app/models/proctolog/unopened/opening.rb +88 -0
- data/app/models/proctolog/unopened.rb +203 -0
- data/app/models/proctolog/visit.rb +26 -0
- data/app/views/layouts/proctolog/application.html.erb +58 -0
- data/app/views/proctolog/acceptances/new.html.erb +34 -0
- data/app/views/proctolog/bursts/_line.html.erb +28 -0
- data/app/views/proctolog/bursts/_merged.html.erb +23 -0
- data/app/views/proctolog/bursts/_moved.html.erb +16 -0
- data/app/views/proctolog/bursts/_notices.html.erb +39 -0
- data/app/views/proctolog/bursts/_put_away.html.erb +11 -0
- data/app/views/proctolog/bursts/_rules.html.erb +27 -0
- data/app/views/proctolog/bursts/_side.html.erb +49 -0
- data/app/views/proctolog/bursts/_side_stop.html.erb +10 -0
- data/app/views/proctolog/bursts/show.html.erb +54 -0
- data/app/views/proctolog/code_reviews/show.html.erb +33 -0
- data/app/views/proctolog/decisions/_alternative.html.erb +5 -0
- data/app/views/proctolog/decisions/_beneath.html.erb +21 -0
- data/app/views/proctolog/decisions/_box.html.erb +27 -0
- data/app/views/proctolog/decisions/_choices.html.erb +9 -0
- data/app/views/proctolog/decisions/_draft_tools.html.erb +47 -0
- data/app/views/proctolog/decisions/_part.html.erb +61 -0
- data/app/views/proctolog/decisions/_round_data.html.erb +1 -0
- data/app/views/proctolog/decisions/_theme.html.erb +13 -0
- data/app/views/proctolog/decisions/index.html.erb +75 -0
- data/app/views/proctolog/notes/_card.html.erb +19 -0
- data/app/views/proctolog/notes/_template.html.erb +41 -0
- data/app/views/proctolog/open_pull_requests/_side.html.erb +30 -0
- data/app/views/proctolog/open_pull_requests/index.html.erb +106 -0
- data/app/views/proctolog/prompts/show.html.erb +41 -0
- data/app/views/proctolog/pull_requests/_connections.html.erb +65 -0
- data/app/views/proctolog/pull_requests/_finish.html.erb +42 -0
- data/app/views/proctolog/pull_requests/_margin.html.erb +33 -0
- data/app/views/proctolog/pull_requests/_note.html.erb +4 -0
- data/app/views/proctolog/pull_requests/_outline.html.erb +26 -0
- data/app/views/proctolog/pull_requests/_paragraphs.html.erb +9 -0
- data/app/views/proctolog/pull_requests/_scenarios.html.erb +16 -0
- data/app/views/proctolog/pull_requests/_since.html.erb +42 -0
- data/app/views/proctolog/pull_requests/_standing.html.erb +51 -0
- data/app/views/proctolog/pull_requests/_status.html.erb +5 -0
- data/app/views/proctolog/pull_requests/_try.html.erb +122 -0
- data/app/views/proctolog/pull_requests/show.html.erb +145 -0
- data/app/views/proctolog/recordings/_dialog.html.erb +26 -0
- data/app/views/proctolog/recordings/_list.html.erb +8 -0
- data/app/views/proctolog/recordings/_note.html.erb +22 -0
- data/app/views/proctolog/recordings/index.html.erb +33 -0
- data/app/views/proctolog/recordings/show.html.erb +118 -0
- data/app/views/proctolog/scenarios/_dialog.html.erb +22 -0
- data/app/views/proctolog/scenarios/_note.html.erb +18 -0
- data/app/views/proctolog/scenarios/_open.html.erb +9 -0
- data/app/views/proctolog/scenarios/_scenario.html.erb +48 -0
- data/app/views/proctolog/scenarios/_server.html.erb +20 -0
- data/app/views/proctolog/scenarios/index.html.erb +62 -0
- data/bin/proctolog +330 -0
- data/completions/_proctolog +143 -0
- data/config/application.rb +94 -0
- data/config/database.yml +16 -0
- data/config/environment.rb +6 -0
- data/config/initializers/grouse.rb +113 -0
- data/config/initializers/grouse_notes.rb +9 -0
- data/config/keys.yml +6 -0
- data/config/routes.rb +71 -0
- data/config/storage.yml +4 -0
- data/db/migrate/20261019213542_create_grouse_tables.grouse.rb +128 -0
- data/db/migrate/20261019213550_create_active_storage_tables.active_storage.rb +58 -0
- data/docs/manual/app.md +157 -0
- data/docs/manual/bursts.md +129 -0
- data/docs/manual/deciding.md +89 -0
- data/docs/manual/desk.png +0 -0
- data/docs/manual/films.md +20 -0
- data/docs/manual/handover.md +93 -0
- data/docs/manual/pr-format.md +75 -0
- data/docs/manual/reading.md +233 -0
- data/docs/manual/unopened.md +80 -0
- data/docs/manual/updates.md +55 -0
- data/lib/proctolog/installation.rb +125 -0
- data/lib/proctolog/version.rb +7 -0
- data/public/asking.js +50 -0
- data/public/code-review.js +40 -0
- data/public/cursor.js +292 -0
- data/public/decision-screenshots.js +97 -0
- data/public/decisions.css +949 -0
- data/public/decisions.js +1289 -0
- data/public/desk.css +582 -0
- data/public/desk.js +126 -0
- data/public/favicon.png +0 -0
- data/public/keys.js +228 -0
- data/public/mentions.js +389 -0
- data/public/messages.js +103 -0
- data/public/notes.js +731 -0
- data/public/pick.css +99 -0
- data/public/plaque.png +0 -0
- data/public/pr-number.js +11 -0
- data/public/prompt.css +46 -0
- data/public/prompt.js +16 -0
- data/public/pull_request.css +805 -0
- data/public/recording.css +379 -0
- data/public/recording.js +394 -0
- data/public/release.js +25 -0
- data/public/respond.css +260 -0
- data/public/respond.js +95 -0
- data/public/review-drafts.js +949 -0
- data/public/review-rounds.js +1447 -0
- data/public/scenarios.css +253 -0
- data/public/scenarios.js +36 -0
- data/public/schemas/proctolog-response-v1.json +101 -0
- data/public/side.js +133 -0
- data/public/standing.css +478 -0
- data/public/terminal-apl.svg +6 -0
- data/public/terminal-cuneiform.svg +3 -0
- data/public/terminal-grain-dots.svg +6 -0
- data/public/terminal-grain-weave.svg +6 -0
- data/public/terminal-grain-wedges.svg +6 -0
- data/public/terminal-shades.svg +3 -0
- data/public/terminal.css +4426 -0
- data/public/toast.js +26 -0
- data/public/try.js +124 -0
- data/public/viewer.js +808 -0
- data/public/words.js +81 -0
- data/skills/proctolog-handover/SKILL.md +77 -0
- data/skills/proctolog-pr-writing/SKILL.md +228 -0
- data/skills/proctolog-pr-writing/references/example-description.md +33 -0
- metadata +366 -0
data/public/words.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// The words of a description, as the desk and the server count them.
|
|
2
|
+
//
|
|
3
|
+
// A section's text is that of GitHub's nodes alone, and a note quotes it with
|
|
4
|
+
// a little before and after. What the desk puts inside a section is marked
|
|
5
|
+
// data-desk and left out here as Rendering leaves it out there: the + beside
|
|
6
|
+
// a block, the form of a note, the notes under a box. So a note quotes the
|
|
7
|
+
// same words whether or not the desk has added anything.
|
|
8
|
+
|
|
9
|
+
const NEAR = 64;
|
|
10
|
+
|
|
11
|
+
// What a note can be pinned to without selecting anything: a paragraph, a
|
|
12
|
+
// list item, a heading, a table row, a code block, a caption, a picture.
|
|
13
|
+
export const BLOCKS =
|
|
14
|
+
"p, li, h3, h4, h5, h6, pre, tr, dt, dd, figcaption, figure.picture";
|
|
15
|
+
|
|
16
|
+
export const elementOf = (node) =>
|
|
17
|
+
node.nodeType === Node.TEXT_NODE ? node.parentElement : node;
|
|
18
|
+
|
|
19
|
+
export const inDesk = (node) => elementOf(node).closest("[data-desk]") !== null;
|
|
20
|
+
|
|
21
|
+
// The block of the description that holds a node, if it is GitHub's.
|
|
22
|
+
export const blockOf = (node) => {
|
|
23
|
+
const block = elementOf(node).closest(BLOCKS);
|
|
24
|
+
return block && !inDesk(block) ? block : null;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const blocksIn = (node) =>
|
|
28
|
+
[...node.querySelectorAll(BLOCKS)].filter((block) => !inDesk(block));
|
|
29
|
+
|
|
30
|
+
// The text of a copy, without the desk's own elements.
|
|
31
|
+
export const measured = (copy) => {
|
|
32
|
+
for (const own of copy.querySelectorAll("[data-desk]")) own.remove();
|
|
33
|
+
return copy.textContent;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// A block's own sentence: its words up to the first block inside it, so that
|
|
37
|
+
// a list item with a list under it is noted for what it says itself.
|
|
38
|
+
export const ownWords = (block) => {
|
|
39
|
+
const range = document.createRange();
|
|
40
|
+
range.selectNodeContents(block);
|
|
41
|
+
const [inner] = blocksIn(block);
|
|
42
|
+
if (inner) range.setEndBefore(inner);
|
|
43
|
+
return range;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const hasWords = (block) =>
|
|
47
|
+
measured(ownWords(block).cloneContents()).trim() !== "";
|
|
48
|
+
|
|
49
|
+
// Stops a quote's edges from cutting a character in two.
|
|
50
|
+
const clean = (text) => text.replace(/^[\uDC00-\uDFFF]|[\uD800-\uDBFF]$/g, "");
|
|
51
|
+
|
|
52
|
+
// The words a range covers, as a note holds them: the words themselves, and
|
|
53
|
+
// the text around them in their section. The offset is a count of characters
|
|
54
|
+
// of the section's own text, so it is the same however the page is laid out.
|
|
55
|
+
// Null when the range is not within one section, or touches the desk's own.
|
|
56
|
+
export const quoteOf = (range) => {
|
|
57
|
+
if (inDesk(range.startContainer) || inDesk(range.endContainer)) return null;
|
|
58
|
+
const body = elementOf(range.commonAncestorContainer).closest(
|
|
59
|
+
"[data-quotable]",
|
|
60
|
+
);
|
|
61
|
+
if (!body) return null;
|
|
62
|
+
|
|
63
|
+
const lead = document.createRange();
|
|
64
|
+
lead.selectNodeContents(body);
|
|
65
|
+
lead.setEnd(range.startContainer, range.startOffset);
|
|
66
|
+
|
|
67
|
+
const picked = measured(range.cloneContents());
|
|
68
|
+
const start =
|
|
69
|
+
measured(lead.cloneContents()).length +
|
|
70
|
+
(picked.length - picked.trimStart().length);
|
|
71
|
+
const exact = picked.trim();
|
|
72
|
+
const text = measured(body.cloneNode(true));
|
|
73
|
+
if (!exact || text.slice(start, start + exact.length) !== exact) return null;
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
exact,
|
|
77
|
+
before: clean(text.slice(Math.max(0, start - NEAR), start)),
|
|
78
|
+
after: clean(text.slice(start + exact.length, start + exact.length + NEAR)),
|
|
79
|
+
section: body.dataset.section,
|
|
80
|
+
};
|
|
81
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: proctolog-handover
|
|
3
|
+
description: Take the owner's review from PRoctolog, the review desk on their Mac, and carry it out - their notes, their choices on the decisions and their code comments, handed over with `proctolog handover` from the checkout under review, even halfway through the review, and answered in the one file the desk reads back. Use when the owner names PRoctolog or its desk - "check my proctolog comments", "check my proctolog notes", "do what I decided in proctolog", "pick up my proctolog review" - when they say "check again" after an earlier pass of this skill, or when they give you a PRoctolog handover folder or its handover.md. Not for review comments on GitHub alone.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Taking the owner's review from PRoctolog
|
|
7
|
+
|
|
8
|
+
The owner reviews pull requests on PRoctolog, a desk on their Mac. What they
|
|
9
|
+
decide there (a change, a question, a task for later, a rule) waits for an
|
|
10
|
+
agent. You take it yourself; nobody needs to press anything.
|
|
11
|
+
|
|
12
|
+
## Take a pass
|
|
13
|
+
|
|
14
|
+
From the checkout of the repository under review:
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
proctolog handover
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
It hands over everything the owner decided that no agent has yet, writes it as
|
|
21
|
+
a folder where the desk keeps handovers, and prints what went in and where the
|
|
22
|
+
brief is. `proctolog burst list` names the bursts when there are several:
|
|
23
|
+
`proctolog handover first-run`. `--part 1055` takes one part of a burst alone,
|
|
24
|
+
when the owner names one.
|
|
25
|
+
|
|
26
|
+
When it says nothing waits, tell the owner so, and stop. When it says the
|
|
27
|
+
checkout has no burst, or is no checkout at all, PRoctolog is not used here:
|
|
28
|
+
say so, and stop.
|
|
29
|
+
|
|
30
|
+
## Work through it
|
|
31
|
+
|
|
32
|
+
Read the brief, `handover.md`, whole. Its rules are the owner's and bind you,
|
|
33
|
+
beside the repository's own. Then read one pull request's file under `prs/` at
|
|
34
|
+
a time, from the bottom of the stack up. `worklist.json` holds the same
|
|
35
|
+
requests as data.
|
|
36
|
+
|
|
37
|
+
The owner may be halfway through their review, and may go on while you work.
|
|
38
|
+
Change nothing the worklist does not name: not a description's other
|
|
39
|
+
decisions, their keys or their pictures. A decision they have not reached yet
|
|
40
|
+
is no instruction.
|
|
41
|
+
|
|
42
|
+
Writing a description goes by the `proctolog-pr-writing` skill. Every write to
|
|
43
|
+
GitHub waits for the owner's word, as the brief's rules say. A pull request
|
|
44
|
+
nobody has opened yet is described in a file on this Mac, which its layer's
|
|
45
|
+
file names: rewrite that file in place, front matter kept, and open nothing.
|
|
46
|
+
|
|
47
|
+
## Answer
|
|
48
|
+
|
|
49
|
+
Write the one file the brief names, under the burst's `responses/` folder, in
|
|
50
|
+
the format `proctolog-response/v1`. Write it even when you cannot finish: give
|
|
51
|
+
what you could not do as blocked, and say why. Until an answer comes back, the
|
|
52
|
+
desk holds that pass's requests back from every later one. Write nothing else
|
|
53
|
+
under the desk's folders: the marks and choices are the owner's.
|
|
54
|
+
|
|
55
|
+
To correct an answer, after a restack or a fix, write the same file again with
|
|
56
|
+
the time of writing as its `createdAt`. The desk shows the new version and
|
|
57
|
+
keeps the one before.
|
|
58
|
+
|
|
59
|
+
The desk shows your answers to the owner, who confirms each one or replies.
|
|
60
|
+
|
|
61
|
+
## Held back
|
|
62
|
+
|
|
63
|
+
The command may say that requests an earlier pass handed over are still with an
|
|
64
|
+
agent that has not answered. They are held back so that two agents never do the
|
|
65
|
+
same work. Take them only when the owner says no agent is at them, or tells you
|
|
66
|
+
to take everything they decided:
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
proctolog handover --again
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
When you cannot ask, leave them, and say so in your last message.
|
|
73
|
+
|
|
74
|
+
## Check again
|
|
75
|
+
|
|
76
|
+
When the owner says to check again, run `proctolog handover` once more. It
|
|
77
|
+
carries only what they decided since, and their replies to your answers.
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: proctolog-pr-writing
|
|
3
|
+
description: Write, rewrite or regrade pull request descriptions for PRoctolog, the review tool - decisions for the owner graded blocking or non-blocking, each with a theme, at most five blocking, checked with `proctolog check` before the owner publishes them - including for branches nobody has opened yet, which the desk reviews from a folder on this Mac. Use whenever asked to "write these PRs for PRoctolog", "rewrite this PR's description for PRoctolog", make PRs reviewable in PRoctolog, review work on PRoctolog "without opening PRs" or "before opening PRs", grade a description's decisions or prepare one for review on PRoctolog, or open on GitHub what was reviewed unopened. Every GitHub write waits for the owner's word. Working through the owner's review is the proctolog-handover skill.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Writing a pull request for PRoctolog
|
|
7
|
+
|
|
8
|
+
The owner reviews this work on PRoctolog, a desk that reads each description,
|
|
9
|
+
lists its decisions, asks the owner about each, and hands the answers back to
|
|
10
|
+
an agent. A description is written for that reading: what was built, what the
|
|
11
|
+
owner must decide, and how to see it. The diff is on GitHub already; say what
|
|
12
|
+
it cannot.
|
|
13
|
+
|
|
14
|
+
Start from compound-engineering's guide to PR descriptions
|
|
15
|
+
(`ce-commit-push-pr/references/pr-description-writing.md`): lead with what is
|
|
16
|
+
now possible or fixed, never with what files moved, and size the description
|
|
17
|
+
by what it costs the owner to decide, not by the size of the diff. What
|
|
18
|
+
follows is what the desk adds to that.
|
|
19
|
+
|
|
20
|
+
A complete example is in `references/example-description.md`.
|
|
21
|
+
|
|
22
|
+
## The sections
|
|
23
|
+
|
|
24
|
+
Keep the project's own template (Summary, Changes, Verification) and add these,
|
|
25
|
+
with exactly these second-level headings:
|
|
26
|
+
|
|
27
|
+
- `## How to test locally`: a **bold scenario name** over numbered steps, each
|
|
28
|
+
step one line: "Do this. Expect that." The desk opens each scenario from the
|
|
29
|
+
bold name.
|
|
30
|
+
- `## Decisions for the owner`: what the owner decides. Each decision is one
|
|
31
|
+
task item on one line.
|
|
32
|
+
|
|
33
|
+
## What is a decision
|
|
34
|
+
|
|
35
|
+
Use the feedback ladder (Netlify's):
|
|
36
|
+
|
|
37
|
+
- **Mountains and boulders are blocking.** A choice that loses data, changes
|
|
38
|
+
who can do what, costs money, breaks an agreed rule, or cannot be undone
|
|
39
|
+
cheaply; or one the owner should settle before the work goes. These stay at
|
|
40
|
+
the top of the section.
|
|
41
|
+
- **Pebbles are non-blocking.** A choice a sensible default settles, which the
|
|
42
|
+
owner may still want to see: a wording, a spacing, a fold. They go under a
|
|
43
|
+
`### Non-blocking` heading, after every blocking decision.
|
|
44
|
+
- **Sand and dust are no decisions.** Implementation facts belong in Changes;
|
|
45
|
+
test gaps in Verification under "Not verified"; the rest nowhere.
|
|
46
|
+
|
|
47
|
+
**At most five blocking decisions.** More than five asks too much of one owner
|
|
48
|
+
at once: grade the ones a default can settle non-blocking, split the work, or
|
|
49
|
+
settle what a rule already settles (below). The desk warns past five.
|
|
50
|
+
|
|
51
|
+
The desk asks the blocking decisions one by one. The owner can leave every
|
|
52
|
+
non-blocking decision that waits for nothing as it is, in one gesture, so a
|
|
53
|
+
non-blocking decision must be one the owner could leave and not regret.
|
|
54
|
+
|
|
55
|
+
## The decisions section
|
|
56
|
+
|
|
57
|
+
```markdown
|
|
58
|
+
## Decisions for the owner
|
|
59
|
+
|
|
60
|
+
- [ ] **Verifying can delete an account row.** Why it was built so, and who it affects. See [the row](#screenshot-account-row). Alternative: refuse instead, at the cost of a stuck account. <!-- proctolog:theme accounts -->
|
|
61
|
+
|
|
62
|
+
### Non-blocking
|
|
63
|
+
|
|
64
|
+
- [ ] **"Skip for now" sits under a 664px fold.** Why. Alternative: tighten the step. <!-- proctolog:theme fit -->
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Each decision:
|
|
68
|
+
|
|
69
|
+
- is one line, a top-level task item: `- [ ] ` and nothing indented under it;
|
|
70
|
+
- opens with what was built, in **bold**: a distinct lead, which is how the
|
|
71
|
+
desk knows the decision again after an edit;
|
|
72
|
+
- says why, and who it affects;
|
|
73
|
+
- links the pictures that show it, beside the claim: `[a label](#screenshot-NAME)`,
|
|
74
|
+
where NAME is one picture's exact, unique `alt` text in this description;
|
|
75
|
+
- names the alternative last in its words: `Alternative: …`, with its cost, or
|
|
76
|
+
`Alternative: none.` when there is none worth offering;
|
|
77
|
+
- ends with its theme: `<!-- proctolog:theme NAME -->`.
|
|
78
|
+
|
|
79
|
+
The heading `### Non-blocking` is visible on GitHub on purpose: the grade
|
|
80
|
+
matters to anyone reading the pull request there.
|
|
81
|
+
|
|
82
|
+
## Themes
|
|
83
|
+
|
|
84
|
+
A theme says what kind of question a decision asks, so the owner can answer one
|
|
85
|
+
kind across the burst at once. Use one of the project's: `proctolog themes`
|
|
86
|
+
prints them with what each means. The desk's own list, which a project may
|
|
87
|
+
replace in `.proctolog/project.yml`:
|
|
88
|
+
|
|
89
|
+
| Theme | What it covers |
|
|
90
|
+
|---|---|
|
|
91
|
+
| `copy` | What the words on a screen say, and how |
|
|
92
|
+
| `fit` | How a screen holds what is on it: wrapping, folds, sizes |
|
|
93
|
+
| `errors` | What happens when something fails, and what the member is told |
|
|
94
|
+
| `accounts` | Who a member is: signing up, signing in, their account |
|
|
95
|
+
| `data` | What is kept, moved or deleted, and who may see it |
|
|
96
|
+
| `plan` | What was built against what was planned |
|
|
97
|
+
| `build` | How the code is made: its parts, its dependencies, its tools |
|
|
98
|
+
| `limits` | Bounds: sizes, counts, rates and time |
|
|
99
|
+
|
|
100
|
+
The marker is hidden on GitHub and is no part of the decision's words: adding
|
|
101
|
+
or mending a theme never reopens a choice the owner made.
|
|
102
|
+
|
|
103
|
+
## References: keep them, never invent them
|
|
104
|
+
|
|
105
|
+
A new decision carries no reference. When you rewrite a decision the owner
|
|
106
|
+
already answered, keep its handover's `source.decision.key` as a hidden marker
|
|
107
|
+
right after the bold lead, `<!-- proctolog:decision KEY -->`, so the owner's
|
|
108
|
+
choice follows it. Never give a reference to a new decision, and never reuse
|
|
109
|
+
one for another. Drop a decision the owner settled from the active list when
|
|
110
|
+
the work no longer needs it; its history stays on the desk.
|
|
111
|
+
|
|
112
|
+
## Rules already made
|
|
113
|
+
|
|
114
|
+
When a rule the owner already made settles a choice (in the project's
|
|
115
|
+
`CLAUDE.md`, a decision record, or a burst's rules), do not list it as a
|
|
116
|
+
decision. Say in Changes which rule settled it: "Dates are the member's own day
|
|
117
|
+
(CLAUDE.md, Dates)." A decision that contradicts a rule is blocking, and says
|
|
118
|
+
which rule.
|
|
119
|
+
|
|
120
|
+
## Evidence: fewer pictures, each one linked
|
|
121
|
+
|
|
122
|
+
A picture is evidence for a claim, so it belongs beside the claim it shows.
|
|
123
|
+
|
|
124
|
+
- **Take a change as a pair.** Shoot the same screen before the change and
|
|
125
|
+
after it, named `NAME-before` and `NAME-after` (the capture kit's `before
|
|
126
|
+
"NAME"` and `after "NAME"`, with `integrations/sartoria/compare.rb` required
|
|
127
|
+
after `kit.rb`). Upload both halves as they are, never composed side by side:
|
|
128
|
+
the desk joins them into one picture with its own compare views, and a
|
|
129
|
+
decision links the pair as `#screenshot-NAME`.
|
|
130
|
+
- **Compare before uploading.** `Capture.compare(names, out:)` drops a pair
|
|
131
|
+
whose pixels did not change, groups pairs of one size that show the same
|
|
132
|
+
change, and writes `compare.json`. Upload only what its `upload` list names:
|
|
133
|
+
one pair of a group stands for the others, which the description need not
|
|
134
|
+
show.
|
|
135
|
+
- **Link every picture** from a decision or a step of a scenario. The desk
|
|
136
|
+
folds a run of pictures nothing links under "More pictures (N)"; one that
|
|
137
|
+
matters is linked.
|
|
138
|
+
- Uploading is a write to GitHub: it goes in the owner's authorized batch, with
|
|
139
|
+
the rest.
|
|
140
|
+
|
|
141
|
+
## Check before asking
|
|
142
|
+
|
|
143
|
+
Write the description to a file and check it with the desk's own parser:
|
|
144
|
+
|
|
145
|
+
```sh
|
|
146
|
+
proctolog check --file body.md
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
It exits 0 when the desk reads it well, 1 with faults (each on its line), and 2
|
|
150
|
+
when GitHub could not be asked. GitHub renders the file for the check and keeps
|
|
151
|
+
nothing of it. Mend every fault; weigh every warning. A picture link resolves
|
|
152
|
+
only to a picture already uploaded to GitHub, so check again once pictures are
|
|
153
|
+
in place.
|
|
154
|
+
|
|
155
|
+
A published description can be checked as GitHub holds it: `proctolog check 1062`.
|
|
156
|
+
|
|
157
|
+
## GitHub writes wait for the owner
|
|
158
|
+
|
|
159
|
+
Every write to GitHub waits for the owner's word in that session: an edit of a
|
|
160
|
+
description, an upload of a picture, a push, a comment, a label. Prepare the
|
|
161
|
+
description, check it, show it, and wait. Never edit a description the owner
|
|
162
|
+
marks as another session's (the burst file's `hands_off`).
|
|
163
|
+
|
|
164
|
+
## Not opened yet
|
|
165
|
+
|
|
166
|
+
When the owner wants the work reviewed before any pull request is opened,
|
|
167
|
+
write each one where the desk reads it instead of on GitHub. One branch, one
|
|
168
|
+
pull request, as `gh pr create` would be told it, in the folder
|
|
169
|
+
`proctolog unopened folder BRANCH` prints:
|
|
170
|
+
|
|
171
|
+
```markdown
|
|
172
|
+
---
|
|
173
|
+
title: A reset mail says which account it is for
|
|
174
|
+
base: recovery/fields
|
|
175
|
+
---
|
|
176
|
+
## Summary
|
|
177
|
+
…
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
- `pull_request.md` holds the title and the base as front matter, then the
|
|
181
|
+
description, written as everything above says. The base is the branch it
|
|
182
|
+
goes into: `main`, or the branch of the layer under it. Layers may be built
|
|
183
|
+
with `gh stack init` and `gh stack add`; never `gh stack submit` until the
|
|
184
|
+
owner says to open them.
|
|
185
|
+
- Pictures go beside it, named as their alt text and linked by their file
|
|
186
|
+
names: ``. Pairs are
|
|
187
|
+
`NAME-before.png` and `NAME-after.png`, compared as above. Nothing is
|
|
188
|
+
uploaded.
|
|
189
|
+
- Check each with `proctolog check BRANCH`: it reads the folder, pictures and
|
|
190
|
+
all. `proctolog unopened` lists those the desk reads, each with its number,
|
|
191
|
+
01, 02, which the desk gives them.
|
|
192
|
+
- A burst names them by their branch, so it still holds them once they are
|
|
193
|
+
opened. Make it yourself, as part of the work: `proctolog burst new NAME
|
|
194
|
+
--top BRANCH` for a chain, `--pr BRANCH` for one alone. Never hand the
|
|
195
|
+
owner that step. They run `proctolog serve` in the repository or any of its
|
|
196
|
+
worktrees, which share the store, and find the burst on the desk.
|
|
197
|
+
|
|
198
|
+
Writing these files is no write to GitHub: rewrite them as a handover asks
|
|
199
|
+
without waiting for the owner's word. Keep the front matter as it is.
|
|
200
|
+
|
|
201
|
+
## Opening what was reviewed
|
|
202
|
+
|
|
203
|
+
Only when the owner says to. Opening is a GitHub write, in the owner's
|
|
204
|
+
authorized batch:
|
|
205
|
+
|
|
206
|
+
1. Push the branches.
|
|
207
|
+
2. Upload the pictures, and change each link to the uploaded address, its alt
|
|
208
|
+
text as it was.
|
|
209
|
+
3. Open each from the bottom up, with its own title, base and description:
|
|
210
|
+
`gh pr create --head BRANCH --base BASE --title TITLE --body-file FILE`,
|
|
211
|
+
the file being `pull_request.md` without its front matter. Or
|
|
212
|
+
`gh stack submit`, then `gh pr edit NUMBER --body-file FILE` for each.
|
|
213
|
+
4. `proctolog check NUMBER` each.
|
|
214
|
+
|
|
215
|
+
The desk notices each opened branch on its next reading, and carries the
|
|
216
|
+
owner's review over to the new number. Decision keys must survive the move
|
|
217
|
+
unchanged, or the owner's choices do not follow them. Leave the folders as
|
|
218
|
+
they are: the desk no longer reads them once their branch is opened.
|
|
219
|
+
|
|
220
|
+
## Answering a handover
|
|
221
|
+
|
|
222
|
+
The owner's answers come back to you as a handover, which the
|
|
223
|
+
`proctolog-handover` skill takes and answers: `proctolog handover` hands over
|
|
224
|
+
what they decided, even halfway through. The answer is one
|
|
225
|
+
`proctolog-response/v1` JSON file, in the folder the brief names. Its schema is
|
|
226
|
+
`../../public/schemas/proctolog-response-v1.json` from this skill's folder.
|
|
227
|
+
Answer only the request ids the handover gives; the desk refuses invented ones.
|
|
228
|
+
A rewritten description goes through everything above again, references kept.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
A member who signs in with a passkey now lands where they were going, not on the home page. Before, every passkey sign-in dropped the page they had asked for; a member who followed a link to a house had to find it again.
|
|
4
|
+
|
|
5
|
+
## How to test locally
|
|
6
|
+
|
|
7
|
+
**Back to the page asked for.**
|
|
8
|
+
1. Sign out, then open a house's page. Expect the sign-in page.
|
|
9
|
+
2. Sign in with a passkey. Expect the house's page, not the home page.
|
|
10
|
+
|
|
11
|
+
**No page asked for.**
|
|
12
|
+
1. Sign out, then open the sign-in page itself. Expect the sign-in page.
|
|
13
|
+
2. Sign in with a passkey. Expect the home page.
|
|
14
|
+
|
|
15
|
+
## Changes
|
|
16
|
+
|
|
17
|
+
- The passkey sign-in keeps the page asked for, as the password sign-in already did.
|
|
18
|
+
- A page asked for is kept for ten minutes, as the password sign-in keeps it (CLAUDE.md, Sessions), so it is no decision here.
|
|
19
|
+
|
|
20
|
+
## Decisions for the owner
|
|
21
|
+
|
|
22
|
+
- [ ] **A page asked for on another site is dropped, and the member lands on the home page.** A link from outside cannot send a member anywhere after they sign in; it affects members who follow links from email. Alternative: keep such a page when it is on this site's own domain, at the cost of a check that can be got wrong. <!-- proctolog:theme accounts -->
|
|
23
|
+
- [ ] **A member who signs in on a second device keeps the page asked for on that device alone.** Each device keeps its own; a member who starts on a phone and signs in on a laptop lands on the laptop's home page. Alternative: keep it with the account, which needs a column and a migration. <!-- proctolog:theme data -->
|
|
24
|
+
|
|
25
|
+
### Non-blocking
|
|
26
|
+
|
|
27
|
+
- [ ] **The sign-in page says "Continue with a passkey".** As the password button's "Continue" does. Alternative: "Sign in with a passkey". <!-- proctolog:theme copy -->
|
|
28
|
+
|
|
29
|
+
## Verification
|
|
30
|
+
|
|
31
|
+
- `bin/rails test test/controllers/passkey_sessions_controller_test.rb`: 9 runs, 0 failures.
|
|
32
|
+
|
|
33
|
+
Not verified: a passkey on a second device, by hand.
|