@erclx/canon 5.73.0 → 5.74.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/api-design/references/adopted.md +5 -3
  4. package/claude/skills/build-in-slices/references/adopted.md +4 -2
  5. package/claude/skills/code-craft/references/adopted.md +9 -7
  6. package/claude/skills/codebase-layout/references/adopted.md +8 -6
  7. package/claude/skills/create-skill/references/skill-practice.md +5 -0
  8. package/claude/skills/deprecation-migration/references/adopted.md +5 -3
  9. package/claude/skills/design-pick/references/board.md +2 -2
  10. package/claude/skills/plan-feature/SKILL.md +2 -1
  11. package/claude/skills/plan-groundwork/SKILL.md +2 -0
  12. package/claude/skills/pr-evidence/REQUIREMENT.md +1 -0
  13. package/claude/skills/pr-evidence/SKILL.md +2 -0
  14. package/claude/skills/pr-evidence/references/evidence.md +11 -4
  15. package/claude/skills/{ui-film/references/pr-clip.md → pr-evidence/references/reel.md} +21 -21
  16. package/claude/skills/proposal-critique/REQUIREMENT.md +34 -0
  17. package/claude/skills/proposal-critique/SKILL.md +126 -0
  18. package/claude/skills/review-craft/references/adopted.md +4 -4
  19. package/claude/skills/search-craft/references/adopted.md +9 -7
  20. package/claude/skills/systematic-debugging/references/adopted.md +4 -2
  21. package/claude/skills/teach-craft/references/adopted.md +8 -6
  22. package/claude/skills/test-craft/references/adopted.md +14 -12
  23. package/claude/skills/test-first/SKILL.md +1 -1
  24. package/claude/skills/test-first/references/adopted.md +9 -5
  25. package/claude/skills/ui-film/REQUIREMENT.md +4 -5
  26. package/claude/skills/ui-film/SKILL.md +13 -12
  27. package/claude/skills/ui-film/references/compose-craft.md +2 -2
  28. package/claude/skills/ui-film/references/handoff.md +2 -7
  29. package/claude/skills/write-human/references/adopted.md +8 -3
  30. package/docs/target/index.md +1 -0
  31. package/docs/target/outside-tools.md +39 -0
  32. package/docs/workflow/skill-map.md +1 -0
  33. package/governance/ledger/skills/build-in-slices/SKILL.md +55 -0
  34. package/governance/ledger/skills/proposal-critique/SKILL.md +66 -0
  35. package/governance/ledger/skills/search-craft/SKILL.md +54 -0
  36. package/governance/ledger/skills/systematic-debugging/SKILL.md +64 -0
  37. package/governance/ledger/skills/test-first/SKILL.md +28 -0
  38. package/governance/ledger/skills/write-human/SKILL.md +62 -0
  39. package/governance/ledger/skills/write-human/density.md +36 -0
  40. package/governance/ledger/skills/write-human/machine-tells.md +30 -0
  41. package/package.json +1 -1
  42. package/scripts/ci/docs-only.sh +24 -0
  43. package/src/claude/cases/misc.ts +14 -0
  44. package/src/claude/skills-audit.ts +89 -8
  45. package/src/commands/pr.ts +110 -13
  46. package/src/gate/measures.ts +1 -1
  47. package/src/gate/sequencer.ts +7 -1
  48. package/src/gate/stages.ts +36 -24
  49. package/src/markdown/scope.ts +2 -0
  50. package/src/pr/checks.ts +75 -3
  51. package/src/pr/evidence.ts +62 -1
  52. package/src/pr/lift.ts +23 -2
  53. package/src/pr/merge.ts +13 -3
  54. package/src/targets/pulls.ts +42 -0
package/src/pr/merge.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ChecksGate } from '@/pr/lift'
1
+ import { advisoryOf, type ChecksGate } from '@/pr/lift'
2
2
  import { readSection } from '@/pr/paths'
3
3
  import { UI_PASS_MARKER } from '@/pr/tick'
4
4
 
@@ -67,6 +67,8 @@ export interface MergeRecord {
67
67
  readonly description?: string
68
68
  /** The squash commit, present only on a merge. */
69
69
  readonly sha?: string
70
+ /** Failing checks the base does not require, which the merge went past. */
71
+ readonly advisory?: readonly string[]
70
72
  }
71
73
 
72
74
  export type Composed =
@@ -230,8 +232,15 @@ export async function merge(
230
232
  )
231
233
  }
232
234
 
233
- if (opts.isDryRun)
234
- return { reason: 'dry-run', isOk: true, number, ...message }
235
+ if (opts.isDryRun) {
236
+ return {
237
+ reason: 'dry-run',
238
+ isOk: true,
239
+ number,
240
+ ...message,
241
+ ...advisoryOf(checks),
242
+ }
243
+ }
235
244
 
236
245
  const outcome = await api.putMerge({ ...message, sha: pull.head })
237
246
  if (outcome.kind === 'merged') {
@@ -241,6 +250,7 @@ export async function merge(
241
250
  number,
242
251
  ...message,
243
252
  sha: outcome.sha,
253
+ ...advisoryOf(checks),
244
254
  }
245
255
  }
246
256
  return refused(
@@ -94,6 +94,8 @@ interface RawPull {
94
94
  * rather than writing a second collapse beside `rollup`.
95
95
  */
96
96
  export interface RawCheck {
97
+ /** The check-run name, which a ruleset's required context matches. */
98
+ readonly name?: string
97
99
  readonly status?: string
98
100
  readonly conclusion?: string
99
101
  readonly state?: string
@@ -137,6 +139,46 @@ export function rollup(checks: readonly RawCheck[]): ChecksState | null {
137
139
  return running ? 'pending' : 'passing'
138
140
  }
139
141
 
142
+ /** A head's state over the checks the base requires, with failing others named apart. */
143
+ export interface RequiredRollup {
144
+ readonly state: ChecksState | null
145
+ /** Names of checks outside the required set that failed, which never gate. */
146
+ readonly advisory: readonly string[]
147
+ }
148
+
149
+ /**
150
+ * Collapses a head's checks over the set the base branch's rules require.
151
+ *
152
+ * An unread or empty set gates by every check, which is `rollup` itself and
153
+ * the safe default for a repository whose rules list nothing. A required name
154
+ * with no run on the head reads pending rather than passing, since a run not
155
+ * yet created has not cleared anything.
156
+ */
157
+ export function rollupRequired(
158
+ checks: readonly RawCheck[],
159
+ required: ReadonlySet<string> | undefined,
160
+ ): RequiredRollup {
161
+ if (required === undefined || required.size === 0) {
162
+ return { state: rollup(checks), advisory: [] }
163
+ }
164
+
165
+ const isRequired = (check: RawCheck): boolean =>
166
+ check.name !== undefined && required.has(check.name)
167
+ const gating = checks.filter(isRequired)
168
+ const advisory = checks
169
+ .filter((check) => !isRequired(check) && rollup([check]) === 'failing')
170
+ .map((check) => check.name ?? '')
171
+
172
+ const state = rollup(gating)
173
+ const isMissing = [...required].some(
174
+ (name) => !gating.some((check) => check.name === name),
175
+ )
176
+ return {
177
+ state: state !== 'failing' && isMissing ? 'pending' : state,
178
+ advisory,
179
+ }
180
+ }
181
+
140
182
  /**
141
183
  * Reads the heading of the newest pass carrying one, matching on the first line
142
184
  * alone the way `poll.ts` does.