@erclx/canon 5.40.0 → 5.42.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 +34 -17
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/api-design/references/adopted.md +34 -14
- package/claude/skills/auto-ship/REQUIREMENT.md +2 -0
- package/claude/skills/auto-ship/SKILL.md +28 -2
- package/claude/skills/auto-ship/references/draft-mark.md +32 -6
- package/claude/skills/auto-ship/references/failure-recovery.md +15 -13
- package/claude/skills/auto-ship/references/fan-in.md +59 -0
- package/claude/skills/auto-ship/references/tier-failures.md +31 -10
- package/claude/skills/auto-ship/references/ui-checklist.md +9 -4
- package/claude/skills/auto-ship/references/worktree-name.md +9 -3
- package/claude/skills/build-in-slices/references/adopted.md +35 -21
- package/claude/skills/canvas-board/references/canvas.md +17 -6
- package/claude/skills/canvas-board/references/design.md +26 -7
- package/claude/skills/code-craft/references/adopted.md +58 -20
- package/claude/skills/codebase-layout/references/adopted.md +49 -16
- package/claude/skills/codebase-layout/references/frontend.md +11 -4
- package/claude/skills/codebase-layout/references/tests.md +4 -2
- package/claude/skills/context-fold/references/classify.md +10 -15
- package/claude/skills/context-fold/references/completion-report.md +11 -9
- package/claude/skills/context-fold/references/context-refresh.md +26 -9
- package/claude/skills/context-fold/references/unusable-baseline.md +5 -3
- package/claude/skills/create-rule/REQUIREMENT.md +5 -0
- package/claude/skills/create-rule/SKILL.md +9 -1
- package/claude/skills/create-rule/references/checklist.md +26 -0
- package/claude/skills/create-rule/references/rule.md +98 -20
- package/claude/skills/create-skill/SKILL.md +1 -0
- package/claude/skills/create-skill/references/skill-disclosure.md +10 -2
- package/claude/skills/create-skill/references/skill-frontmatter.md +43 -0
- package/claude/skills/create-skill/references/skill-paths.md +7 -4
- package/claude/skills/create-skill/references/skill-practice.md +6 -3
- package/claude/skills/create-skill/references/skill-requirement.md +4 -2
- package/claude/skills/create-skill/references/skill.md +67 -44
- package/claude/skills/decision-escalate/REQUIREMENT.md +1 -1
- package/claude/skills/decision-escalate/SKILL.md +1 -2
- package/claude/skills/deploy-app/references/vercel.md +2 -1
- package/claude/skills/deprecation-migration/references/adopted.md +44 -25
- package/claude/skills/design-taste/references/adopted.md +9 -1
- package/claude/skills/design-taste/references/craft.md +3 -1
- package/claude/skills/design-taste/references/kinds.md +8 -7
- package/claude/skills/design-taste/references/preflight.md +12 -0
- package/claude/skills/design-taste/references/systems.md +7 -6
- package/claude/skills/design-taste/references/tells.md +24 -25
- package/claude/skills/design-taste/references/vocabulary.md +7 -5
- package/claude/skills/document-health/references/axes.md +54 -30
- package/claude/skills/draft-and-pick/references/live-arms.md +2 -2
- package/claude/skills/draft-doc/references/context.md +4 -3
- package/claude/skills/draft-doc/references/docs.md +6 -3
- package/claude/skills/draft-doc/references/readme/agent-facing.md +6 -0
- package/claude/skills/draft-doc/references/readme/application.md +8 -2
- package/claude/skills/draft-doc/references/readme/cli.md +5 -1
- package/claude/skills/draft-doc/references/readme/library.md +4 -0
- package/claude/skills/draft-doc/references/readme/plugin.md +9 -1
- package/claude/skills/draft-doc/references/readme.md +30 -13
- package/claude/skills/draft-doc/references/requirements.md +17 -4
- package/claude/skills/draft-doc/references/wiki-kind.md +20 -10
- package/claude/skills/draft-figure/references/architecture-set.md +7 -3
- package/claude/skills/draft-figure/references/figures.md +8 -6
- package/claude/skills/draft-figure/references/hand-drawn.md +3 -1
- package/claude/skills/draft-figure/references/mermaid-path.md +19 -9
- package/claude/skills/draft-figure/references/mermaid.md +10 -5
- package/claude/skills/draft-ready/references/ready.md +22 -15
- package/claude/skills/git-branch/REQUIREMENT.md +17 -6
- package/claude/skills/git-branch/SKILL.md +63 -7
- package/claude/skills/git-branch/references/branch.md +11 -1
- package/claude/skills/git-branch/references/slug.md +17 -5
- package/claude/skills/git-commit/references/commit.md +8 -0
- package/claude/skills/git-commit/references/versioning.md +23 -17
- package/claude/skills/git-followup/REQUIREMENT.md +1 -1
- package/claude/skills/git-followup/SKILL.md +5 -6
- package/claude/skills/git-issue/references/issue.md +29 -16
- package/claude/skills/git-pr/REQUIREMENT.md +1 -5
- package/claude/skills/git-pr/SKILL.md +11 -22
- package/claude/skills/git-pr/references/final-command.md +21 -8
- package/claude/skills/git-pr/references/labels.md +45 -28
- package/claude/skills/git-pr/references/pr.md +28 -9
- package/claude/skills/git-pr/references/publish.md +42 -28
- package/claude/skills/git-pr/references/task-number.md +20 -8
- package/claude/skills/git-ship/SKILL.md +1 -1
- package/claude/skills/plan-feature/references/batches.md +48 -1
- package/claude/skills/plan-feature/references/plan-lifecycle.md +10 -3
- package/claude/skills/plan-feature/references/plan.md +59 -20
- package/claude/skills/plan-groundwork/references/groundwork-spikes.md +4 -1
- package/claude/skills/plan-groundwork/references/groundwork.md +14 -16
- package/claude/skills/plan-intake/references/intake.md +29 -24
- package/claude/skills/plan-intake-answer/REQUIREMENT.md +1 -1
- package/claude/skills/plan-intake-answer/SKILL.md +1 -2
- package/claude/skills/pr-evidence/REQUIREMENT.md +40 -0
- package/claude/skills/pr-evidence/SKILL.md +53 -0
- package/claude/skills/pr-evidence/references/evidence.md +150 -0
- package/claude/skills/review-address/references/post-review-findings.md +10 -3
- package/claude/skills/review-address/references/rebase-conflicts.md +22 -7
- package/claude/skills/review-address/references/rest-reads.md +3 -1
- package/claude/skills/review-craft/references/adopted.md +35 -18
- package/claude/skills/review-craft/references/security.md +42 -7
- package/claude/skills/review-craft/references/ui.md +23 -8
- package/claude/skills/review-pr/SKILL.md +6 -6
- package/claude/skills/review-pr/references/body-variants.md +29 -9
- package/claude/skills/review-pr/references/close-out.md +20 -5
- package/claude/skills/review-pr/references/key-changes.md +27 -3
- package/claude/skills/review-pr/references/post.md +83 -31
- package/claude/skills/review-pr/references/scope.md +54 -19
- package/claude/skills/review-ui/SKILL.md +2 -0
- package/claude/skills/review-ui/references/close-out.md +49 -0
- package/claude/skills/review-ui/references/driving.md +24 -4
- package/claude/skills/review-ui/references/post.md +43 -13
- package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +67 -17
- package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +81 -40
- package/claude/skills/role-orchestrator/references/orchestrator-handback.md +52 -15
- package/claude/skills/role-orchestrator/references/orchestrator-handoff.md +48 -26
- package/claude/skills/role-orchestrator/references/orchestrator-inbound.md +12 -13
- package/claude/skills/role-orchestrator/references/orchestrator-launch.md +72 -36
- package/claude/skills/role-orchestrator/references/orchestrator-output.md +12 -4
- package/claude/skills/role-orchestrator/references/orchestrator-parked.md +64 -24
- package/claude/skills/role-orchestrator/references/orchestrator-poll.md +80 -26
- package/claude/skills/role-orchestrator/references/orchestrator-refill.md +41 -18
- package/claude/skills/role-orchestrator/references/orchestrator-resume.md +19 -7
- package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +22 -12
- package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +15 -6
- package/claude/skills/role-orchestrator/references/orchestrator-sweep.md +25 -7
- package/claude/skills/role-orchestrator/references/orchestrator-watch.md +34 -8
- package/claude/skills/role-orchestrator/scripts/poll.ts +16 -24
- package/claude/skills/role-worker/REQUIREMENT.md +2 -0
- package/claude/skills/role-worker/SKILL.md +17 -0
- package/claude/skills/search-craft/references/adopted.md +18 -6
- package/claude/skills/session-map/references/session.md +26 -7
- package/claude/skills/session-worktree/references/main-root-writes.md +25 -8
- package/claude/skills/systematic-debugging/references/adopted.md +30 -16
- package/claude/skills/target-check/references/domains.md +39 -11
- package/claude/skills/target-setup/references/detect.md +80 -65
- package/claude/skills/target-setup/references/indexes.md +8 -6
- package/claude/skills/task-board/references/board.md +86 -30
- package/claude/skills/task-board/references/decline.md +29 -13
- package/claude/skills/task-board/references/tasks-decline.md +12 -5
- package/claude/skills/task-board/references/tasks.md +65 -33
- package/claude/skills/task-complete/references/archive.md +41 -17
- package/claude/skills/task-complete/references/receipt-sweep.md +23 -9
- package/claude/skills/task-complete/references/unusable-baseline.md +10 -3
- package/claude/skills/teach-workspace/REQUIREMENT.md +1 -1
- package/claude/skills/teach-workspace/SKILL.md +1 -2
- package/claude/skills/teach-workspace/references/glossary.md +6 -2
- package/claude/skills/teach-workspace/references/lesson-build.md +44 -16
- package/claude/skills/teach-workspace/references/lesson-craft.md +12 -7
- package/claude/skills/teach-workspace/references/pedagogy.md +6 -3
- package/claude/skills/teach-workspace/references/promotion-fold.md +17 -11
- package/claude/skills/teach-workspace/references/promotion.md +31 -8
- package/claude/skills/teach-workspace/references/revisit.md +8 -2
- package/claude/skills/teach-workspace/references/teach.md +17 -9
- package/claude/skills/test-craft/references/adopted.md +48 -14
- package/claude/skills/test-craft/references/component.md +7 -4
- package/claude/skills/test-craft/references/e2e.md +25 -7
- package/claude/skills/test-craft/references/unit.md +3 -1
- package/claude/skills/test-first/references/adopted.md +12 -4
- package/claude/skills/ui-checklist/REQUIREMENT.md +1 -1
- package/claude/skills/ui-checklist/SKILL.md +1 -1
- package/claude/skills/video-craft/references/adopted.md +62 -18
- package/claude/skills/write-human/references/adopted.md +21 -8
- package/docs/workflow/parallel-features.md +2 -1
- package/docs/workflow/skill-map.md +2 -1
- package/package.json +1 -1
- package/src/claude/cases/git.ts +4 -0
- package/src/claude/cases/workflow.ts +5 -0
- package/src/commands/pr.ts +174 -37
- package/src/commands/records.ts +11 -3
- package/src/context/shape-gated.ts +1 -0
- package/src/markdown/scope.ts +150 -2
- package/src/pr/frames.ts +53 -9
- package/src/pr/lift.ts +6 -3
- package/src/pr/review-state.ts +182 -0
- package/src/records/validate.ts +1 -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 +130 -70
- package/claude/skills/git-pr/references/evidence.md +0 -124
package/src/commands/records.ts
CHANGED
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
plural,
|
|
45
45
|
} from '@/cli/ui'
|
|
46
46
|
import { currentWorktreeRoot, mainWorktreeRoot } from '@/git/worktree'
|
|
47
|
+
import { fanInFindings } from '@/tasks/fan-in'
|
|
47
48
|
import { readLivePlans, stackFindings } from '@/tasks/stack'
|
|
48
49
|
|
|
49
50
|
/** Returned when a record carries a finding, which is the gating result. */
|
|
@@ -742,7 +743,7 @@ async function runValidate(
|
|
|
742
743
|
}
|
|
743
744
|
|
|
744
745
|
/**
|
|
745
|
-
* Appends the
|
|
746
|
+
* Appends the plans findings that read across files. They sit in the command
|
|
746
747
|
* layer because `src/records/` sits below `src/tasks/`.
|
|
747
748
|
*/
|
|
748
749
|
async function validateWithStacks(
|
|
@@ -752,9 +753,16 @@ async function validateWithStacks(
|
|
|
752
753
|
const outcome = await validateRecords(root, kind)
|
|
753
754
|
if (!outcome.ok || kind !== 'plans') return outcome
|
|
754
755
|
|
|
755
|
-
const
|
|
756
|
+
const live = await readLivePlans(root)
|
|
756
757
|
|
|
757
|
-
return {
|
|
758
|
+
return {
|
|
759
|
+
...outcome,
|
|
760
|
+
findings: [
|
|
761
|
+
...outcome.findings,
|
|
762
|
+
...stackFindings(live),
|
|
763
|
+
...fanInFindings(live),
|
|
764
|
+
],
|
|
765
|
+
}
|
|
758
766
|
}
|
|
759
767
|
|
|
760
768
|
function report(
|
package/src/markdown/scope.ts
CHANGED
|
@@ -42,41 +42,113 @@ export const GATED_PATHS: readonly string[] = [
|
|
|
42
42
|
'canon/context/context-model.md',
|
|
43
43
|
'canon/context/index.md',
|
|
44
44
|
'claude/skills/api-design/SKILL.md',
|
|
45
|
+
'claude/skills/api-design/references/adopted.md',
|
|
45
46
|
'claude/skills/auto-ship/SKILL.md',
|
|
47
|
+
'claude/skills/auto-ship/references/draft-mark.md',
|
|
48
|
+
'claude/skills/auto-ship/references/failure-recovery.md',
|
|
49
|
+
'claude/skills/auto-ship/references/fan-in.md',
|
|
50
|
+
'claude/skills/auto-ship/references/tier-failures.md',
|
|
51
|
+
'claude/skills/auto-ship/references/ui-checklist.md',
|
|
52
|
+
'claude/skills/auto-ship/references/verb-absent.md',
|
|
53
|
+
'claude/skills/auto-ship/references/worktree-name.md',
|
|
46
54
|
'claude/skills/backlog-triage/SKILL.md',
|
|
47
55
|
'claude/skills/backlog-triage/references/apply.md',
|
|
48
56
|
'claude/skills/build-in-slices/SKILL.md',
|
|
57
|
+
'claude/skills/build-in-slices/references/adopted.md',
|
|
49
58
|
'claude/skills/canon-cli/SKILL.md',
|
|
50
59
|
'claude/skills/canon-feedback-triage/SKILL.md',
|
|
51
60
|
'claude/skills/canon-feedback/SKILL.md',
|
|
61
|
+
'claude/skills/canon-feedback/references/template.md',
|
|
52
62
|
'claude/skills/canvas-board/SKILL.md',
|
|
63
|
+
'claude/skills/canvas-board/references/canvas.md',
|
|
64
|
+
'claude/skills/canvas-board/references/design.md',
|
|
53
65
|
'claude/skills/ci-workflow/SKILL.md',
|
|
66
|
+
'claude/skills/ci-workflow/references/workflows.md',
|
|
54
67
|
'claude/skills/code-craft/SKILL.md',
|
|
68
|
+
'claude/skills/code-craft/references/adopted.md',
|
|
55
69
|
'claude/skills/codebase-layout/SKILL.md',
|
|
70
|
+
'claude/skills/codebase-layout/references/adopted.md',
|
|
71
|
+
'claude/skills/codebase-layout/references/frontend.md',
|
|
72
|
+
'claude/skills/codebase-layout/references/tests.md',
|
|
56
73
|
'claude/skills/context-fold/SKILL.md',
|
|
74
|
+
'claude/skills/context-fold/references/classify.md',
|
|
75
|
+
'claude/skills/context-fold/references/completion-report.md',
|
|
76
|
+
'claude/skills/context-fold/references/context-refresh.md',
|
|
77
|
+
'claude/skills/context-fold/references/context.md',
|
|
78
|
+
'claude/skills/context-fold/references/unusable-baseline.md',
|
|
57
79
|
'claude/skills/create-rule/SKILL.md',
|
|
80
|
+
'claude/skills/create-rule/references/rule.md',
|
|
58
81
|
'claude/skills/create-skill/SKILL.md',
|
|
82
|
+
'claude/skills/create-skill/references/skill-disclosure.md',
|
|
83
|
+
'claude/skills/create-skill/references/skill-frontmatter.md',
|
|
84
|
+
'claude/skills/create-skill/references/skill-paths.md',
|
|
85
|
+
'claude/skills/create-skill/references/skill-practice.md',
|
|
86
|
+
'claude/skills/create-skill/references/skill-reference.md',
|
|
87
|
+
'claude/skills/create-skill/references/skill-requirement.md',
|
|
88
|
+
'claude/skills/create-skill/references/skill.md',
|
|
59
89
|
'claude/skills/decision-escalate/SKILL.md',
|
|
60
90
|
'claude/skills/deploy-app/SKILL.md',
|
|
91
|
+
'claude/skills/deploy-app/references/cloudflare.md',
|
|
92
|
+
'claude/skills/deploy-app/references/vercel.md',
|
|
61
93
|
'claude/skills/deprecation-migration/SKILL.md',
|
|
94
|
+
'claude/skills/deprecation-migration/references/adopted.md',
|
|
62
95
|
'claude/skills/design-taste/SKILL.md',
|
|
96
|
+
'claude/skills/design-taste/references/adopted.md',
|
|
97
|
+
'claude/skills/design-taste/references/craft.md',
|
|
98
|
+
'claude/skills/design-taste/references/kinds.md',
|
|
99
|
+
'claude/skills/design-taste/references/preflight.md',
|
|
100
|
+
'claude/skills/design-taste/references/systems.md',
|
|
101
|
+
'claude/skills/design-taste/references/tells.md',
|
|
102
|
+
'claude/skills/design-taste/references/vocabulary.md',
|
|
63
103
|
'claude/skills/docs-sync/SKILL.md',
|
|
104
|
+
'claude/skills/docs-sync/references/docs.md',
|
|
105
|
+
'claude/skills/docs-sync/references/readme.md',
|
|
64
106
|
'claude/skills/document-health/SKILL.md',
|
|
107
|
+
'claude/skills/document-health/references/axes.md',
|
|
65
108
|
'claude/skills/draft-and-pick/SKILL.md',
|
|
109
|
+
'claude/skills/draft-and-pick/references/live-arms.md',
|
|
66
110
|
'claude/skills/draft-doc/SKILL.md',
|
|
111
|
+
'claude/skills/draft-doc/references/context.md',
|
|
112
|
+
'claude/skills/draft-doc/references/docs.md',
|
|
113
|
+
'claude/skills/draft-doc/references/readme.md',
|
|
114
|
+
'claude/skills/draft-doc/references/readme/agent-facing.md',
|
|
115
|
+
'claude/skills/draft-doc/references/readme/application.md',
|
|
116
|
+
'claude/skills/draft-doc/references/readme/cli.md',
|
|
117
|
+
'claude/skills/draft-doc/references/readme/library.md',
|
|
118
|
+
'claude/skills/draft-doc/references/readme/plugin.md',
|
|
119
|
+
'claude/skills/draft-doc/references/requirements.md',
|
|
120
|
+
'claude/skills/draft-doc/references/wiki-kind.md',
|
|
121
|
+
'claude/skills/draft-doc/references/wiki.md',
|
|
67
122
|
'claude/skills/draft-figure/SKILL.md',
|
|
123
|
+
'claude/skills/draft-figure/references/architecture-set.md',
|
|
124
|
+
'claude/skills/draft-figure/references/figures.md',
|
|
125
|
+
'claude/skills/draft-figure/references/hand-drawn.md',
|
|
126
|
+
'claude/skills/draft-figure/references/mermaid-path.md',
|
|
127
|
+
'claude/skills/draft-figure/references/mermaid.md',
|
|
68
128
|
'claude/skills/draft-identity/SKILL.md',
|
|
69
129
|
'claude/skills/draft-identity/references/card-route.md',
|
|
70
130
|
'claude/skills/draft-ready/SKILL.md',
|
|
131
|
+
'claude/skills/draft-ready/references/assembly.md',
|
|
132
|
+
'claude/skills/draft-ready/references/ready.md',
|
|
71
133
|
'claude/skills/draft-screencast/SKILL.md',
|
|
72
134
|
'claude/skills/draft-screencast/references/beats-template.md',
|
|
73
135
|
'claude/skills/draft-slides/SKILL.md',
|
|
74
136
|
'claude/skills/draft-slides/references/deck.md',
|
|
75
137
|
'claude/skills/git-branch/SKILL.md',
|
|
138
|
+
'claude/skills/git-branch/references/branch.md',
|
|
139
|
+
'claude/skills/git-branch/references/slug.md',
|
|
76
140
|
'claude/skills/git-commit/SKILL.md',
|
|
141
|
+
'claude/skills/git-commit/references/commit.md',
|
|
142
|
+
'claude/skills/git-commit/references/versioning.md',
|
|
77
143
|
'claude/skills/git-followup/SKILL.md',
|
|
78
144
|
'claude/skills/git-issue/SKILL.md',
|
|
145
|
+
'claude/skills/git-issue/references/issue.md',
|
|
79
146
|
'claude/skills/git-pr/SKILL.md',
|
|
147
|
+
'claude/skills/git-pr/references/final-command.md',
|
|
148
|
+
'claude/skills/git-pr/references/labels.md',
|
|
149
|
+
'claude/skills/git-pr/references/pr.md',
|
|
150
|
+
'claude/skills/git-pr/references/publish.md',
|
|
151
|
+
'claude/skills/git-pr/references/task-number.md',
|
|
80
152
|
'claude/skills/git-ship/SKILL.md',
|
|
81
153
|
'claude/skills/git-ship/references/ci-watch.md',
|
|
82
154
|
'claude/skills/git-split/SKILL.md',
|
|
@@ -86,48 +158,124 @@ export const GATED_PATHS: readonly string[] = [
|
|
|
86
158
|
'claude/skills/git-worktree/SKILL.md',
|
|
87
159
|
'claude/skills/git-worktree/references/cleanup.md',
|
|
88
160
|
'claude/skills/markdown-craft/SKILL.md',
|
|
161
|
+
'claude/skills/markdown-craft/references/markdown.md',
|
|
89
162
|
'claude/skills/plan-feature/SKILL.md',
|
|
90
163
|
'claude/skills/plan-feature/references/batches.md',
|
|
164
|
+
'claude/skills/plan-feature/references/plan-lifecycle.md',
|
|
165
|
+
'claude/skills/plan-feature/references/plan.md',
|
|
91
166
|
'claude/skills/plan-groundwork/SKILL.md',
|
|
167
|
+
'claude/skills/plan-groundwork/references/groundwork-spikes.md',
|
|
168
|
+
'claude/skills/plan-groundwork/references/groundwork.md',
|
|
92
169
|
'claude/skills/plan-groundwork/references/output.md',
|
|
93
170
|
'claude/skills/plan-intake-answer/SKILL.md',
|
|
94
171
|
'claude/skills/plan-intake/SKILL.md',
|
|
172
|
+
'claude/skills/plan-intake/references/intake.md',
|
|
173
|
+
'claude/skills/pr-evidence/SKILL.md',
|
|
174
|
+
'claude/skills/pr-evidence/references/evidence.md',
|
|
95
175
|
'claude/skills/read-frames/SKILL.md',
|
|
96
176
|
'claude/skills/record-screencast/SKILL.md',
|
|
97
177
|
'claude/skills/review-address/SKILL.md',
|
|
178
|
+
'claude/skills/review-address/references/post-review-findings.md',
|
|
179
|
+
'claude/skills/review-address/references/rebase-conflicts.md',
|
|
98
180
|
'claude/skills/review-address/references/rebase-only.md',
|
|
181
|
+
'claude/skills/review-address/references/rest-reads.md',
|
|
99
182
|
'claude/skills/review-craft/SKILL.md',
|
|
183
|
+
'claude/skills/review-craft/references/adopted.md',
|
|
184
|
+
'claude/skills/review-craft/references/security.md',
|
|
185
|
+
'claude/skills/review-craft/references/ui.md',
|
|
100
186
|
'claude/skills/review-pr/SKILL.md',
|
|
187
|
+
'claude/skills/review-pr/references/body-variants.md',
|
|
188
|
+
'claude/skills/review-pr/references/close-out.md',
|
|
189
|
+
'claude/skills/review-pr/references/key-changes.md',
|
|
190
|
+
'claude/skills/review-pr/references/post.md',
|
|
191
|
+
'claude/skills/review-pr/references/scope.md',
|
|
101
192
|
'claude/skills/review-ui/SKILL.md',
|
|
193
|
+
'claude/skills/review-ui/references/close-out.md',
|
|
194
|
+
'claude/skills/review-ui/references/driving.md',
|
|
102
195
|
'claude/skills/review-ui/references/hosted-preview.md',
|
|
196
|
+
'claude/skills/review-ui/references/post.md',
|
|
197
|
+
'claude/skills/review-ui/references/tick.md',
|
|
103
198
|
'claude/skills/role-orchestrator/SKILL.md',
|
|
199
|
+
'claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md',
|
|
200
|
+
'claude/skills/role-orchestrator/references/orchestrator-dispatch.md',
|
|
104
201
|
'claude/skills/role-orchestrator/references/orchestrator-filing.md',
|
|
202
|
+
'claude/skills/role-orchestrator/references/orchestrator-handback.md',
|
|
203
|
+
'claude/skills/role-orchestrator/references/orchestrator-handoff.md',
|
|
204
|
+
'claude/skills/role-orchestrator/references/orchestrator-inbound.md',
|
|
205
|
+
'claude/skills/role-orchestrator/references/orchestrator-launch.md',
|
|
206
|
+
'claude/skills/role-orchestrator/references/orchestrator-output.md',
|
|
207
|
+
'claude/skills/role-orchestrator/references/orchestrator-parked.md',
|
|
208
|
+
'claude/skills/role-orchestrator/references/orchestrator-poll.md',
|
|
209
|
+
'claude/skills/role-orchestrator/references/orchestrator-refill.md',
|
|
210
|
+
'claude/skills/role-orchestrator/references/orchestrator-resume.md',
|
|
211
|
+
'claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md',
|
|
212
|
+
'claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md',
|
|
213
|
+
'claude/skills/role-orchestrator/references/orchestrator-sweep.md',
|
|
214
|
+
'claude/skills/role-orchestrator/references/orchestrator-watch.md',
|
|
105
215
|
'claude/skills/role-planner/SKILL.md',
|
|
106
216
|
'claude/skills/role-reviewer/SKILL.md',
|
|
107
217
|
'claude/skills/role-worker/SKILL.md',
|
|
108
218
|
'claude/skills/search-craft/SKILL.md',
|
|
219
|
+
'claude/skills/search-craft/references/adopted.md',
|
|
109
220
|
'claude/skills/session-compact/SKILL.md',
|
|
221
|
+
'claude/skills/session-compact/references/handoff-note.md',
|
|
110
222
|
'claude/skills/session-map/SKILL.md',
|
|
223
|
+
'claude/skills/session-map/references/session.md',
|
|
111
224
|
'claude/skills/session-relay/SKILL.md',
|
|
112
225
|
'claude/skills/session-resume/SKILL.md',
|
|
113
226
|
'claude/skills/session-worktree/SKILL.md',
|
|
227
|
+
'claude/skills/session-worktree/references/install-command.md',
|
|
228
|
+
'claude/skills/session-worktree/references/main-root-writes.md',
|
|
114
229
|
'claude/skills/systematic-debugging/SKILL.md',
|
|
230
|
+
'claude/skills/systematic-debugging/references/adopted.md',
|
|
115
231
|
'claude/skills/target-check/SKILL.md',
|
|
232
|
+
'claude/skills/target-check/references/domains.md',
|
|
116
233
|
'claude/skills/target-setup/SKILL.md',
|
|
234
|
+
'claude/skills/target-setup/references/detect.md',
|
|
235
|
+
'claude/skills/target-setup/references/indexes.md',
|
|
236
|
+
'claude/skills/target-setup/references/verify.md',
|
|
117
237
|
'claude/skills/task-board/SKILL.md',
|
|
238
|
+
'claude/skills/task-board/references/board.md',
|
|
118
239
|
'claude/skills/task-board/references/create-report.md',
|
|
240
|
+
'claude/skills/task-board/references/decline.md',
|
|
241
|
+
'claude/skills/task-board/references/tasks-decline.md',
|
|
242
|
+
'claude/skills/task-board/references/tasks.md',
|
|
119
243
|
'claude/skills/task-complete/SKILL.md',
|
|
244
|
+
'claude/skills/task-complete/references/archive.md',
|
|
245
|
+
'claude/skills/task-complete/references/receipt-sweep.md',
|
|
246
|
+
'claude/skills/task-complete/references/unusable-baseline.md',
|
|
120
247
|
'claude/skills/teach-workspace/SKILL.md',
|
|
248
|
+
'claude/skills/teach-workspace/references/glossary.md',
|
|
249
|
+
'claude/skills/teach-workspace/references/lesson-build.md',
|
|
250
|
+
'claude/skills/teach-workspace/references/lesson-craft.md',
|
|
251
|
+
'claude/skills/teach-workspace/references/pedagogy.md',
|
|
252
|
+
'claude/skills/teach-workspace/references/promotion-fold.md',
|
|
253
|
+
'claude/skills/teach-workspace/references/promotion.md',
|
|
254
|
+
'claude/skills/teach-workspace/references/revisit.md',
|
|
255
|
+
'claude/skills/teach-workspace/references/teach.md',
|
|
121
256
|
'claude/skills/test-craft/SKILL.md',
|
|
257
|
+
'claude/skills/test-craft/references/adopted.md',
|
|
258
|
+
'claude/skills/test-craft/references/component.md',
|
|
259
|
+
'claude/skills/test-craft/references/e2e.md',
|
|
260
|
+
'claude/skills/test-craft/references/unit.md',
|
|
122
261
|
'claude/skills/test-first/SKILL.md',
|
|
262
|
+
'claude/skills/test-first/references/adopted.md',
|
|
123
263
|
'claude/skills/ui-checklist/SKILL.md',
|
|
124
264
|
'claude/skills/ux-audit/SKILL.md',
|
|
125
265
|
'claude/skills/ux-measure/SKILL.md',
|
|
126
266
|
'claude/skills/video-craft/SKILL.md',
|
|
267
|
+
'claude/skills/video-craft/references/adopted.md',
|
|
127
268
|
'claude/skills/write-human/SKILL.md',
|
|
269
|
+
'claude/skills/write-human/references/adopted.md',
|
|
270
|
+
'claude/skills/write-human/references/density.md',
|
|
271
|
+
'claude/skills/write-human/references/machine-tells.md',
|
|
128
272
|
'claude/skills/youtube-transcripts/SKILL.md',
|
|
129
273
|
'.claude/skills/internal-',
|
|
130
274
|
'docs/',
|
|
275
|
+
'tooling/',
|
|
276
|
+
'wiki/',
|
|
277
|
+
'README.md',
|
|
278
|
+
'CONTRIBUTING.md',
|
|
131
279
|
]
|
|
132
280
|
|
|
133
281
|
/**
|
|
@@ -136,8 +284,8 @@ export const GATED_PATHS: readonly string[] = [
|
|
|
136
284
|
* entries, the docs pages, and the skill bodies and references through a stage
|
|
137
285
|
* of its own before this measure existed, and waiting on `GATED_PATHS` would
|
|
138
286
|
* reopen that hole. The seeds, the stack references, the wiki, and the root
|
|
139
|
-
* guides were never held to it,
|
|
140
|
-
*
|
|
287
|
+
* guides were never held to it, so they joined `GATED_PATHS` only once their
|
|
288
|
+
* rewrite brought them to zero.
|
|
141
289
|
*/
|
|
142
290
|
const ALWAYS_GATED: readonly DensityKind[] = ['bullet-run']
|
|
143
291
|
|
package/src/pr/frames.ts
CHANGED
|
@@ -19,6 +19,9 @@ const PASS_PATTERN = /^\d{8}T\d{6}Z$/
|
|
|
19
19
|
/** How many times an add rebuilds on a tip another writer moved. */
|
|
20
20
|
const ADD_ATTEMPTS = 3
|
|
21
21
|
|
|
22
|
+
/** One half of a reference address. It opens on a letter or digit and holds no separator, so `..` and `/` cannot survive it. */
|
|
23
|
+
const REFERENCE_PART = /^[A-Za-z0-9][A-Za-z0-9._-]*$/
|
|
24
|
+
|
|
22
25
|
const FOLDER_PATTERN = /^pr-(\d+)$/
|
|
23
26
|
|
|
24
27
|
const DAY_MS = 86_400_000
|
|
@@ -77,7 +80,8 @@ export interface FrameInput {
|
|
|
77
80
|
readonly number: number
|
|
78
81
|
readonly head: string
|
|
79
82
|
readonly pass: string
|
|
80
|
-
readonly box
|
|
83
|
+
readonly box?: number
|
|
84
|
+
readonly reference?: string
|
|
81
85
|
readonly theme?: FrameTheme
|
|
82
86
|
readonly bytes: Uint8Array
|
|
83
87
|
}
|
|
@@ -158,6 +162,39 @@ export function frameLink(repo: string, path: string): string {
|
|
|
158
162
|
return `https://github.com/${repo}/blob/${FRAMES_BRANCH}/${path}?raw=true`
|
|
159
163
|
}
|
|
160
164
|
|
|
165
|
+
/**
|
|
166
|
+
* The file-name slug of a `<page>/<frame>` address, or undefined when the
|
|
167
|
+
* address would not round-trip. Each half must open on a letter or digit and
|
|
168
|
+
* hold only letters, digits, dots, underscores, and dashes, and neither may
|
|
169
|
+
* carry `--`, so the joined slug reads back as the same two names and a path
|
|
170
|
+
* never gains a directory or escapes the pass folder.
|
|
171
|
+
*/
|
|
172
|
+
export function referenceSlug(address: string): string | undefined {
|
|
173
|
+
const parts = address.split('/')
|
|
174
|
+
if (parts.length !== 2) return undefined
|
|
175
|
+
const [page, frame] = parts as [string, string]
|
|
176
|
+
const valid = [page, frame].every(
|
|
177
|
+
(part) => REFERENCE_PART.test(part) && !part.includes('--'),
|
|
178
|
+
)
|
|
179
|
+
return valid ? `${page}--${frame}` : undefined
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Where a design reference capture lands, beside the evidence frames of one
|
|
184
|
+
* pass. The slug repeats for one reference, so a second capture in a pass
|
|
185
|
+
* overwrites only itself. Undefined when the address has no valid slug.
|
|
186
|
+
*/
|
|
187
|
+
export function referencePath(
|
|
188
|
+
number: number,
|
|
189
|
+
head: string,
|
|
190
|
+
pass: string,
|
|
191
|
+
address: string,
|
|
192
|
+
): string | undefined {
|
|
193
|
+
const slug = referenceSlug(address)
|
|
194
|
+
if (slug === undefined) return undefined
|
|
195
|
+
return `pr-${number}/${head.slice(0, SHORT_HEAD_LENGTH)}/${pass}/ref-${slug}.png`
|
|
196
|
+
}
|
|
197
|
+
|
|
161
198
|
/** The frame's bytes, or undefined when the file is absent, empty, or not a PNG. */
|
|
162
199
|
export async function readFrame(path: string): Promise<Uint8Array | undefined> {
|
|
163
200
|
const bytes = await readFile(path).catch(() => undefined)
|
|
@@ -179,17 +216,24 @@ export async function pushFrame(
|
|
|
179
216
|
api: FramesApi,
|
|
180
217
|
input: FrameInput,
|
|
181
218
|
): Promise<PushResult> {
|
|
182
|
-
const path =
|
|
183
|
-
input.
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
219
|
+
const path =
|
|
220
|
+
input.reference === undefined
|
|
221
|
+
? framePath(
|
|
222
|
+
input.number,
|
|
223
|
+
input.head,
|
|
224
|
+
input.pass,
|
|
225
|
+
input.box ?? 0,
|
|
226
|
+
input.theme,
|
|
227
|
+
)
|
|
228
|
+
: referencePath(input.number, input.head, input.pass, input.reference)
|
|
229
|
+
if (path === undefined) return { kind: 'refused', reason: 'push-failed' }
|
|
189
230
|
const blob = await api.createBlob(Buffer.from(input.bytes).toString('base64'))
|
|
190
231
|
if (blob === undefined) return { kind: 'refused', reason: 'push-failed' }
|
|
191
232
|
const entry: TreeEntry = { path, mode: '100644', type: 'blob', sha: blob }
|
|
192
|
-
const message =
|
|
233
|
+
const message =
|
|
234
|
+
input.reference === undefined
|
|
235
|
+
? `chore(frames): add box ${input.box} of #${input.number}`
|
|
236
|
+
: `chore(frames): add reference ${input.reference} of #${input.number}`
|
|
193
237
|
|
|
194
238
|
for (let attempt = 0; attempt < ADD_ATTEMPTS; attempt += 1) {
|
|
195
239
|
const tip = await api.readTip()
|
package/src/pr/lift.ts
CHANGED
|
@@ -144,7 +144,10 @@ function fail(gate: GateName, reason: LiftRefusal): GateResult {
|
|
|
144
144
|
* since the commit it covers is a stamp GitHub wrote at submission, which the
|
|
145
145
|
* marker exists to replace.
|
|
146
146
|
*/
|
|
147
|
-
function reviewGate(
|
|
147
|
+
export function reviewGate(
|
|
148
|
+
reviews: readonly ReviewRow[],
|
|
149
|
+
head: string,
|
|
150
|
+
): GateResult {
|
|
148
151
|
const scope = resolveReviewScope({ reviews })
|
|
149
152
|
if (scope.state === 'none') return fail('review', 'review-missing')
|
|
150
153
|
if (scope.state === 'open') return fail('review', 'review-open')
|
|
@@ -175,8 +178,8 @@ function carried(gates: readonly GateResult[]): {
|
|
|
175
178
|
* checklist the reviewer drove as true as it was. A close that is not an
|
|
176
179
|
* ancestor, which a force-push or a rebase leaves, never carries.
|
|
177
180
|
*/
|
|
178
|
-
async function uiGate(
|
|
179
|
-
api: LiftApi,
|
|
181
|
+
export async function uiGate(
|
|
182
|
+
api: Pick<LiftApi, 'readChanged'>,
|
|
180
183
|
painted: PaintedPatterns,
|
|
181
184
|
reviews: readonly ReviewRow[],
|
|
182
185
|
head: string,
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CHECKS_POLL_MS,
|
|
3
|
+
type GateResult,
|
|
4
|
+
type LiftApi,
|
|
5
|
+
type LiftRefusal,
|
|
6
|
+
reviewGate,
|
|
7
|
+
uiGate,
|
|
8
|
+
} from '@/pr/lift'
|
|
9
|
+
import { DEFAULT_PAINTED, type PaintedPatterns } from '@/pr/painted'
|
|
10
|
+
import {
|
|
11
|
+
coversHead,
|
|
12
|
+
type ReviewRow,
|
|
13
|
+
type ReviewScope,
|
|
14
|
+
resolveReviewScope,
|
|
15
|
+
resolveUiScope,
|
|
16
|
+
type UiScope,
|
|
17
|
+
} from '@/pr/review-scope'
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The reads the verb makes, a subset of the lift's so a worker waiting here and
|
|
21
|
+
* a reviewer lifting read one answer. A read that failed returns undefined, and
|
|
22
|
+
* the verb refuses `gh-failed` rather than reading absence as no pass.
|
|
23
|
+
*/
|
|
24
|
+
export type ReviewStateApi = Pick<
|
|
25
|
+
LiftApi,
|
|
26
|
+
'readReviews' | 'readEvidence' | 'readChanged' | 'sleep' | 'now'
|
|
27
|
+
> & {
|
|
28
|
+
/** The branch tip from the remote, which is what a pass has to cover. */
|
|
29
|
+
readTip(): Promise<string | undefined>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** One family's standing at the tip. */
|
|
33
|
+
export interface FamilyState {
|
|
34
|
+
/** The lift's refusal for this family, absent when its gate passes. */
|
|
35
|
+
readonly reason?: LiftRefusal
|
|
36
|
+
/**
|
|
37
|
+
* Whether a pass covers the tip, which is what a waiting worker reads. True
|
|
38
|
+
* when the gate passes, or when the newest pass, open or unmarked, names the
|
|
39
|
+
* tip. The reason alone cannot answer it, since the lift reads an open pass
|
|
40
|
+
* before it reads currency.
|
|
41
|
+
*/
|
|
42
|
+
readonly isCovered: boolean
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface UiState extends UiScope, FamilyState {
|
|
46
|
+
/** Whether the evidence comment carries a checklist, which binds the family. */
|
|
47
|
+
readonly isBound: boolean
|
|
48
|
+
readonly carriedFrom?: string
|
|
49
|
+
readonly paintedPaths?: readonly string[]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface ReviewStateRecord {
|
|
53
|
+
readonly head: string
|
|
54
|
+
readonly scope: ReviewScope
|
|
55
|
+
readonly review: FamilyState
|
|
56
|
+
readonly ui: UiState
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export type ReviewStateRead =
|
|
60
|
+
| { readonly kind: 'read'; readonly record: ReviewStateRecord }
|
|
61
|
+
| { readonly kind: 'refused'; readonly reason: 'gh-failed' }
|
|
62
|
+
|
|
63
|
+
export type ReviewWait =
|
|
64
|
+
| {
|
|
65
|
+
readonly kind: 'read'
|
|
66
|
+
readonly reason: 'covered' | 'timeout'
|
|
67
|
+
readonly record: ReviewStateRecord
|
|
68
|
+
readonly waitedSeconds: number
|
|
69
|
+
}
|
|
70
|
+
| {
|
|
71
|
+
readonly kind: 'refused'
|
|
72
|
+
readonly reason: 'gh-failed'
|
|
73
|
+
readonly waitedSeconds: number
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface WaitOptions {
|
|
77
|
+
readonly waitSeconds: number
|
|
78
|
+
readonly pollMs?: number
|
|
79
|
+
readonly painted?: PaintedPatterns
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function familyOf(gate: GateResult, commit: string | undefined, tip: string) {
|
|
83
|
+
return {
|
|
84
|
+
...(gate.reason !== undefined && { reason: gate.reason }),
|
|
85
|
+
isCovered: gate.isOk || (commit !== undefined && coversHead(commit, tip)),
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Both families at the tip through the lift's own gates, so a worker and the
|
|
91
|
+
* lift never disagree on a reason. The evidence is read by the caller, since a
|
|
92
|
+
* wait reads it once rather than once per poll.
|
|
93
|
+
*/
|
|
94
|
+
async function readAt(
|
|
95
|
+
api: ReviewStateApi,
|
|
96
|
+
hasChecklist: boolean,
|
|
97
|
+
painted: PaintedPatterns,
|
|
98
|
+
): Promise<ReviewStateRead> {
|
|
99
|
+
const [tip, reviews] = await Promise.all([api.readTip(), api.readReviews()])
|
|
100
|
+
if (tip === undefined || reviews === undefined) {
|
|
101
|
+
return { kind: 'refused', reason: 'gh-failed' }
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const listing: { reviews: readonly ReviewRow[] } = { reviews }
|
|
105
|
+
const scope = resolveReviewScope(listing)
|
|
106
|
+
const uiScope = resolveUiScope(listing)
|
|
107
|
+
const ui = await uiGate(api, painted, reviews, tip, hasChecklist)
|
|
108
|
+
if (ui.reason === 'gh-failed') return { kind: 'refused', reason: 'gh-failed' }
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
kind: 'read',
|
|
112
|
+
record: {
|
|
113
|
+
head: tip,
|
|
114
|
+
scope,
|
|
115
|
+
review: familyOf(reviewGate(reviews, tip), scope.commit, tip),
|
|
116
|
+
ui: {
|
|
117
|
+
...uiScope,
|
|
118
|
+
...familyOf(ui, uiScope.commit, tip),
|
|
119
|
+
isBound: hasChecklist,
|
|
120
|
+
...(ui.carriedFrom !== undefined && { carriedFrom: ui.carriedFrom }),
|
|
121
|
+
...(ui.paintedPaths !== undefined && { paintedPaths: ui.paintedPaths }),
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export async function readReviewState(
|
|
128
|
+
api: ReviewStateApi,
|
|
129
|
+
painted: PaintedPatterns = DEFAULT_PAINTED,
|
|
130
|
+
): Promise<ReviewStateRead> {
|
|
131
|
+
const evidence = await api.readEvidence()
|
|
132
|
+
if (evidence === undefined) return { kind: 'refused', reason: 'gh-failed' }
|
|
133
|
+
return readAt(api, evidence.hasChecklist, painted)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Holds until every bound family has a pass covering the tip, or the deadline
|
|
138
|
+
* passes. The tip is read again every poll, so a push during the wait moves
|
|
139
|
+
* what a pass has to cover. The evidence is read once, since a checklist
|
|
140
|
+
* appearing mid-wait is a ship-chain write the waiting worker made before it
|
|
141
|
+
* started.
|
|
142
|
+
*/
|
|
143
|
+
export async function waitForReviews(
|
|
144
|
+
api: ReviewStateApi,
|
|
145
|
+
opts: WaitOptions,
|
|
146
|
+
): Promise<ReviewWait> {
|
|
147
|
+
const pollMs = opts.pollMs ?? CHECKS_POLL_MS
|
|
148
|
+
const painted = opts.painted ?? DEFAULT_PAINTED
|
|
149
|
+
const started = api.now()
|
|
150
|
+
const deadline = started + opts.waitSeconds * 1000
|
|
151
|
+
const waited = () => Math.round((api.now() - started) / 1000)
|
|
152
|
+
|
|
153
|
+
const evidence = await api.readEvidence()
|
|
154
|
+
if (evidence === undefined) {
|
|
155
|
+
return { kind: 'refused', reason: 'gh-failed', waitedSeconds: waited() }
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
for (;;) {
|
|
159
|
+
const read = await readAt(api, evidence.hasChecklist, painted)
|
|
160
|
+
if (read.kind === 'refused') {
|
|
161
|
+
return { ...read, waitedSeconds: waited() }
|
|
162
|
+
}
|
|
163
|
+
const { record } = read
|
|
164
|
+
if (record.review.isCovered && record.ui.isCovered) {
|
|
165
|
+
return {
|
|
166
|
+
kind: 'read',
|
|
167
|
+
reason: 'covered',
|
|
168
|
+
record,
|
|
169
|
+
waitedSeconds: waited(),
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (api.now() + pollMs > deadline) {
|
|
173
|
+
return {
|
|
174
|
+
kind: 'read',
|
|
175
|
+
reason: 'timeout',
|
|
176
|
+
record,
|
|
177
|
+
waitedSeconds: waited(),
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
await api.sleep(pollMs)
|
|
181
|
+
}
|
|
182
|
+
}
|