@erclx/canon 5.37.0 → 5.39.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 +1 -1
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/api-design/SKILL.md +12 -9
- package/claude/skills/auto-ship/SKILL.md +43 -23
- package/claude/skills/backlog-triage/SKILL.md +62 -53
- package/claude/skills/backlog-triage/references/apply.md +69 -0
- package/claude/skills/build-in-slices/SKILL.md +8 -4
- package/claude/skills/canon-cli/SKILL.md +5 -1
- package/claude/skills/canon-feedback/SKILL.md +18 -8
- package/claude/skills/canon-feedback-triage/SKILL.md +10 -3
- package/claude/skills/canvas-board/SKILL.md +36 -17
- package/claude/skills/ci-workflow/SKILL.md +5 -4
- package/claude/skills/code-craft/SKILL.md +10 -6
- package/claude/skills/codebase-layout/SKILL.md +3 -5
- package/claude/skills/context-fold/REQUIREMENT.md +4 -4
- package/claude/skills/context-fold/SKILL.md +42 -23
- package/claude/skills/context-fold/references/context-refresh.md +4 -3
- package/claude/skills/context-fold/references/context.md +79 -64
- package/claude/skills/create-rule/SKILL.md +7 -3
- package/claude/skills/create-skill/SKILL.md +27 -7
- package/claude/skills/create-skill/references/skill-reference.md +41 -17
- package/claude/skills/decision-escalate/SKILL.md +8 -5
- package/claude/skills/deploy-app/SKILL.md +1 -1
- package/claude/skills/deprecation-migration/SKILL.md +12 -4
- package/claude/skills/design-taste/SKILL.md +17 -11
- package/claude/skills/docs-sync/REQUIREMENT.md +1 -0
- package/claude/skills/docs-sync/SKILL.md +17 -6
- package/claude/skills/docs-sync/references/docs.md +54 -21
- package/claude/skills/docs-sync/references/readme.md +32 -8
- package/claude/skills/document-health/SKILL.md +3 -4
- package/claude/skills/draft-and-pick/SKILL.md +73 -47
- package/claude/skills/draft-doc/SKILL.md +9 -4
- package/claude/skills/draft-doc/references/context.md +4 -4
- package/claude/skills/draft-doc/references/docs.md +1 -0
- package/claude/skills/draft-doc/references/wiki.md +3 -2
- package/claude/skills/draft-figure/SKILL.md +9 -7
- package/claude/skills/draft-identity/SKILL.md +24 -52
- package/claude/skills/draft-identity/references/card-route.md +46 -0
- package/claude/skills/draft-ready/SKILL.md +19 -7
- package/claude/skills/draft-screencast/SKILL.md +6 -112
- package/claude/skills/draft-screencast/references/beats-template.md +119 -0
- package/claude/skills/draft-slides/SKILL.md +7 -4
- package/claude/skills/git-branch/SKILL.md +3 -3
- package/claude/skills/git-commit/SKILL.md +5 -3
- package/claude/skills/git-followup/SKILL.md +16 -9
- package/claude/skills/git-issue/SKILL.md +6 -5
- package/claude/skills/git-issue/references/issue.md +11 -10
- package/claude/skills/git-pr/SKILL.md +56 -44
- package/claude/skills/git-ship/SKILL.md +43 -34
- package/claude/skills/git-ship/references/ci-watch.md +31 -0
- package/claude/skills/git-split/SKILL.md +28 -100
- package/claude/skills/git-split/references/independent.md +40 -0
- package/claude/skills/git-split/references/stacked.md +73 -0
- package/claude/skills/git-stage/SKILL.md +9 -7
- package/claude/skills/git-worktree/SKILL.md +27 -49
- package/claude/skills/git-worktree/references/cleanup.md +55 -0
- package/claude/skills/markdown-craft/SKILL.md +2 -2
- package/claude/skills/markdown-craft/references/markdown.md +82 -52
- package/claude/skills/plan-feature/SKILL.md +52 -46
- package/claude/skills/plan-feature/references/batches.md +46 -0
- package/claude/skills/plan-groundwork/SKILL.md +60 -74
- package/claude/skills/plan-groundwork/references/groundwork.md +53 -24
- package/claude/skills/plan-groundwork/references/output.md +48 -0
- package/claude/skills/plan-intake/SKILL.md +28 -21
- package/claude/skills/plan-intake-answer/SKILL.md +14 -13
- package/claude/skills/read-frames/SKILL.md +2 -0
- package/claude/skills/record-screencast/SKILL.md +31 -11
- package/claude/skills/review-address/SKILL.md +76 -158
- package/claude/skills/review-address/references/rebase-only.md +34 -0
- package/claude/skills/review-craft/SKILL.md +27 -11
- package/claude/skills/review-pr/SKILL.md +91 -40
- package/claude/skills/review-pr/references/post.md +1 -1
- package/claude/skills/review-ui/SKILL.md +62 -37
- package/claude/skills/review-ui/references/hosted-preview.md +30 -0
- package/claude/skills/role-orchestrator/SKILL.md +105 -74
- package/claude/skills/role-orchestrator/references/orchestrator-filing.md +26 -0
- package/claude/skills/role-orchestrator/references/orchestrator-parked.md +1 -1
- package/claude/skills/role-planner/SKILL.md +66 -64
- package/claude/skills/role-reviewer/SKILL.md +57 -46
- package/claude/skills/role-worker/SKILL.md +68 -63
- package/claude/skills/search-craft/SKILL.md +7 -5
- package/claude/skills/session-compact/SKILL.md +16 -11
- package/claude/skills/session-map/SKILL.md +31 -10
- package/claude/skills/session-relay/SKILL.md +32 -65
- package/claude/skills/session-resume/SKILL.md +18 -13
- package/claude/skills/session-worktree/SKILL.md +70 -42
- package/claude/skills/systematic-debugging/SKILL.md +6 -1
- package/claude/skills/target-check/SKILL.md +13 -6
- package/claude/skills/target-setup/SKILL.md +41 -30
- package/claude/skills/target-setup/references/verify.md +6 -5
- package/claude/skills/task-board/SKILL.md +68 -60
- package/claude/skills/task-board/references/create-report.md +36 -0
- package/claude/skills/task-board/references/tasks.md +3 -1
- package/claude/skills/task-complete/SKILL.md +20 -18
- package/claude/skills/teach-workspace/SKILL.md +61 -33
- package/claude/skills/test-craft/SKILL.md +2 -1
- package/claude/skills/test-first/SKILL.md +15 -9
- package/claude/skills/ui-checklist/SKILL.md +18 -16
- package/claude/skills/ux-audit/SKILL.md +9 -10
- package/claude/skills/ux-measure/SKILL.md +22 -18
- package/claude/skills/video-craft/SKILL.md +15 -7
- package/claude/skills/write-human/SKILL.md +9 -1
- package/claude/skills/youtube-transcripts/SKILL.md +2 -1
- package/docs/agents/context-audit-checks.md +19 -1
- package/docs/agents/context-audit.md +2 -2
- package/docs/agents/driver.md +1 -1
- package/docs/agents/hooks.md +21 -1
- package/docs/agents/index.md +10 -14
- package/docs/agents/indexes.md +25 -29
- package/docs/agents/install-and-sync.md +124 -235
- package/docs/agents/markdown-audit-density.md +39 -0
- package/docs/agents/markdown-audit-weight.md +9 -7
- package/docs/agents/markdown-audit.md +18 -14
- package/docs/agents/migrate.md +41 -16
- package/docs/agents/output-shape.md +60 -45
- package/docs/agents/overview.md +36 -12
- package/docs/agents/routing.md +1 -1
- package/docs/agents/rule-citations.md +1 -1
- package/docs/agents/skills-reach.md +1 -1
- package/docs/agents/targets.md +25 -77
- package/docs/target/migrations.md +1 -1
- package/docs/target/projects.md +3 -3
- package/docs/target/scenarios.md +1 -1
- package/docs/workflow/ai-workflow.md +2 -2
- package/docs/workflow/parallel-features.md +2 -2
- package/docs/workflow/skill-map.md +1 -1
- package/docs/workflow/visual-design-workflow.md +1 -1
- package/governance/detect.toml +6 -1
- package/package.json +6 -3
- package/scripts/core/install-check.sh +1 -1
- package/src/commands/claude.ts +1 -2
- package/src/commands/context.ts +106 -7
- package/src/commands/hooks.ts +63 -0
- package/src/commands/markdown.ts +169 -32
- package/src/commands/pr.ts +1 -1
- package/src/commands/records.ts +0 -1
- package/src/context/audit.ts +256 -5
- package/src/context/classify/prompts.ts +1 -1
- package/src/context/gate.ts +23 -7
- package/src/context/shape-gated.ts +28 -0
- package/src/design/document.ts +1 -1
- package/src/design/tokens.ts +1 -1
- package/src/docs/read.ts +15 -21
- package/src/gate/measures.ts +15 -190
- package/src/gate/stages.ts +21 -23
- package/src/hooks/reply-links.ts +110 -0
- package/src/markdown/density.ts +258 -0
- package/src/markdown/gate.ts +57 -18
- package/src/markdown/reference-shape.ts +103 -0
- package/src/markdown/scope.ts +174 -0
- package/src/markdown/structure.ts +10 -60
- package/src/sandbox/equivalence.ts +7 -9
- package/src/shipped/references.ts +1 -1
- package/src/teach/browser/head.ts +2 -2
- package/src/teach/browser/sidebar.ts +3 -3
- package/src/teach/browser/theme.ts +2 -2
- package/src/tooling/inject.ts +2 -2
- package/src/tooling/package.ts +15 -18
- package/src/tooling/verify-stack.ts +6 -3
- package/tooling/astro/configs/.oxfmtrc.json +8 -0
- package/tooling/astro/configs/.prettierrc +13 -0
- package/tooling/astro/manifest.toml +13 -0
- package/tooling/astro/reference.md +15 -5
- package/tooling/base/configs/.oxfmtrc.json +7 -0
- package/tooling/base/configs/scripts/verify.ts +1 -1
- package/tooling/base/manifest.toml +6 -6
- package/tooling/base/reference.md +12 -9
- package/tooling/base/seeds/.lintstagedrc +1 -3
- package/tooling/base/seeds/canon/context/ci.md +3 -3
- package/tooling/base/seeds/canon/context/development.md +2 -2
- package/tooling/claude/manifest.toml +5 -1
- package/tooling/claude/seeds/.claude/hooks/reply-links.sh +72 -0
- package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +22 -1
- package/tooling/claude/seeds/.claude/settings.json +4 -0
- package/tooling/go/reference.md +2 -2
- package/tooling/nextjs/configs/.oxlintrc.json +223 -0
- package/tooling/nextjs/manifest.toml +2 -5
- package/tooling/nextjs/reference.md +4 -4
- package/tooling/php/manifest.toml +6 -1
- package/tooling/php/reference.md +2 -2
- package/tooling/python/manifest.toml +6 -1
- package/tooling/python/reference.md +4 -4
- package/tooling/vite-react/manifest.toml +1 -4
- package/tooling/vite-react/reference.md +3 -3
- package/tooling/web/configs/.oxlintrc.json +213 -0
- package/tooling/web/manifest.toml +9 -13
- package/tooling/web/reference.md +14 -14
- package/docs/agents/commands.md +0 -154
- package/docs/agents/docs.md +0 -27
- package/docs/agents/drift-surfaces.md +0 -201
- package/docs/agents/gov-detect.md +0 -47
- package/docs/agents/scripting.md +0 -142
- package/src/markdown/growth.ts +0 -43
- package/tooling/base/configs/.prettierrc +0 -12
- package/tooling/base/seeds/.prettierignore +0 -0
- package/tooling/nextjs/configs/eslint.config.js +0 -91
- package/tooling/web/configs/eslint.config.js +0 -82
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Drift surfaces
|
|
3
|
-
description: The seven sections canon sync --check reports beside the per-domain scan, being seeds, superseded artifacts, unmigrated domains, surfaces at the old root, new rules and skills, and the reverse walk, with the managed-target gate and what counts toward the exit code
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Drift surfaces
|
|
7
|
-
|
|
8
|
-
`canon sync --check` reports seven sections outside the per-domain scan that
|
|
9
|
-
`install-and-sync.md` describes, because each names something
|
|
10
|
-
that walk cannot see: `seeds`, `superseded`, `unmigrated`, `unmovedSurfaces`,
|
|
11
|
-
`newSkills`, `newRules`, and `reverse`. None of them produces a change, and no
|
|
12
|
-
sync command applies any of them. The headings below group the first four
|
|
13
|
-
together and give `newSkills` its description under `newRules`, which answers the
|
|
14
|
-
same question about a different corpus.
|
|
15
|
-
|
|
16
|
-
All seven report only against a toolkit-managed target, which is one carrying a
|
|
17
|
-
`.claude/` directory, a `CLAUDE.md`, or a domain still at the root layout. The
|
|
18
|
-
report says so through `managed` in the JSON and routes an unmanaged directory to
|
|
19
|
-
`canon init`. Seeds are why the gate exists, since they enumerate from the toolkit
|
|
20
|
-
source rather than from what a target installed, so an unmanaged directory would
|
|
21
|
-
otherwise report every seed as `missing`.
|
|
22
|
-
|
|
23
|
-
A root-layout domain counts as a marker on its own, because the detection fires
|
|
24
|
-
only on root files the toolkit ships and a project in the old layout is one the
|
|
25
|
-
toolkit installed. When `managed` is false every section comes back empty rather
|
|
26
|
-
than the render alone going quiet, so a consumer reading `--json` never acts on a
|
|
27
|
-
finding the rendered half withheld.
|
|
28
|
-
|
|
29
|
-
## Seeds, superseded artifacts, unmigrated domains, and old-root surfaces
|
|
30
|
-
|
|
31
|
-
`seeds` classifies every seed the toolkit ships against the target's copy, as
|
|
32
|
-
`matching`, `stale`, `drifted`, or `missing`. `missing` has no per-domain
|
|
33
|
-
equivalent, since the domain walk lists what a target installed and cannot see a
|
|
34
|
-
file that never arrived. There is no `customized` verdict here, because that one
|
|
35
|
-
needs a stamp and seeds carry none, so a file history cannot attribute stays
|
|
36
|
-
`drifted`. Merge the section by hand against the toolkit copy rather than
|
|
37
|
-
replacing a file the project edits.
|
|
38
|
-
|
|
39
|
-
A markdown seed installs rewritten rather than copied, since the `stub: true`
|
|
40
|
-
marker the toolkit's own seed gate reads is stripped on the way in. The
|
|
41
|
-
comparison above runs against what the install would write, so a marked seed a
|
|
42
|
-
target never touched still reports `matching`. Every other seed copies byte for
|
|
43
|
-
byte.
|
|
44
|
-
|
|
45
|
-
`superseded` names a file a newer seed folder replaced, such as `.claude/TASKS.md`
|
|
46
|
-
against the `.canon/tasks/` that now ships. The entry carries `replacedBy` and
|
|
47
|
-
nothing else, and the file is never deleted, since the content belongs to the
|
|
48
|
-
project and only its author can decide where it moves. The list derives from the
|
|
49
|
-
seed tree rather than from a fixed set of filenames, so a folder added later is
|
|
50
|
-
covered without a code change. Only an exact stem matches, which leaves a
|
|
51
|
-
suffixed variant such as `TASKS-ARCHIVE.md` unreported.
|
|
52
|
-
|
|
53
|
-
No skill splits the file. The destination's shape lives in the skill that owns
|
|
54
|
-
it, so the split is the project's own to make.
|
|
55
|
-
|
|
56
|
-
`unmigrated` names a domain sitting at the root layout an older toolkit installed
|
|
57
|
-
to, with nothing at the path the current one reads. It carries `rootPath`,
|
|
58
|
-
`installPath`, and a file count. Without it a project holding an older layout at its
|
|
59
|
-
root reports zero entries for that domain and reads as clean, which is the most
|
|
60
|
-
misleading state the report can produce.
|
|
61
|
-
|
|
62
|
-
The field currently names no domain. Snippets was the one the toolkit ever
|
|
63
|
-
installed at a project root, and it retired outright. A leftover `snippets/`
|
|
64
|
-
folder reports under the reverse walk instead, where `docs/target/sync.md` says
|
|
65
|
-
what to do with it.
|
|
66
|
-
|
|
67
|
-
`unmovedSurfaces` names a tracked surface the target still holds at its `.claude/`
|
|
68
|
-
spelling with nothing at the `canon/` one, such as `.claude/REQUIREMENTS.md` or
|
|
69
|
-
`.claude/context/`. Each entry carries `rel` and `movesTo`, and the render names
|
|
70
|
-
`canon migrate surface-roots`, the verb that moves them. Rules glob the `canon/`
|
|
71
|
-
spelling alone, so a target on the old root stops loading the rules scoped to
|
|
72
|
-
those files until it moves. <!-- canon-keep-surface-root -->
|
|
73
|
-
|
|
74
|
-
## Rules the target never received
|
|
75
|
-
|
|
76
|
-
`newRules` names a rule the target could receive and its tree does not hold. A
|
|
77
|
-
sync refreshes the files a target already holds and adds none, so without this
|
|
78
|
-
section a project's rule set freezes at its install date while every file it
|
|
79
|
-
does hold reports as current. That is the report's most confident wrong
|
|
80
|
-
answer, since a clean result reads as a target holding everything the toolkit
|
|
81
|
-
publishes.
|
|
82
|
-
|
|
83
|
-
The list rides beside `newSkills`, which asks the same question about the plugin
|
|
84
|
-
catalog. Both are names rather than paths, and neither queues a change, because
|
|
85
|
-
the two remedies differ: a skill loads live from the plugin directory and needs
|
|
86
|
-
nothing run, while a rule reaches a target only when someone runs
|
|
87
|
-
`canon gov install`.
|
|
88
|
-
|
|
89
|
-
Read a clean section as reporting rather than as delivering. Nothing here
|
|
90
|
-
installs, nothing counts toward `--exit-code`, and a target can read the list and
|
|
91
|
-
act on none of it. The value stops at an operator reading it, which is the same
|
|
92
|
-
contract the skills list already sets.
|
|
93
|
-
|
|
94
|
-
Since `canon gov install` records the stack it resolved, a target carrying that
|
|
95
|
-
record answers this by comparing its current entitlement against its current
|
|
96
|
-
tree, with no anchor and no git diff involved. That is what lets the section
|
|
97
|
-
name a rule that shipped before the target's last sync: the anchor a sync
|
|
98
|
-
advances plays no part in the read, where an anchor-bound diff can never see a
|
|
99
|
-
rule on the far side of a window a later sync moved past it. The per-file
|
|
100
|
-
`missing` state `canon gov sync` reports comes from the same comparison, so a
|
|
101
|
-
rule the chain lists reaches both surfaces the same way.
|
|
102
|
-
|
|
103
|
-
A target stamped before governance recorded a chain falls back to the older
|
|
104
|
-
rule-folder-inference read below. The measurement there anchors on governance's own
|
|
105
|
-
stamp rather than on the oldest anchor across domains, since rules are
|
|
106
|
-
domain-scoped and a shared anchor would let another domain's sync move the
|
|
107
|
-
revision rules are measured from. A target carrying no chain and no governance anchor
|
|
108
|
-
reports nothing at all: it has no date to measure against, and diffing from the
|
|
109
|
-
start of history would read the whole catalog as new.
|
|
110
|
-
|
|
111
|
-
An anchor this toolkit cannot resolve reports nothing by the same route, and that
|
|
112
|
-
one is not visible. A stamp naming a revision the running clone has never seen,
|
|
113
|
-
which is what a registry install without history or a shallow clone produces,
|
|
114
|
-
fails the read and yields an empty list rather than a stated absence. It looks
|
|
115
|
-
identical to a target holding every rule the toolkit publishes. `newSkills`
|
|
116
|
-
behaves the same way, and neither carries the `historyUnavailable` flag the
|
|
117
|
-
per-domain scan uses to separate the two. Treat an empty section on a toolkit
|
|
118
|
-
that is not a full clone as unmeasured rather than clean. This gap does not
|
|
119
|
-
reach the chain-based read above, since it consults no anchor at all.
|
|
120
|
-
|
|
121
|
-
In the fallback, entitlement is filtered, because a stack does not receive
|
|
122
|
-
every rule. The base stack names ten rules, the language stacks add `code` and
|
|
123
|
-
their own language and testing rules, and every other rule is opt-in, so an
|
|
124
|
-
unfiltered list would tell a base consumer about rules it can never receive and
|
|
125
|
-
train the reader to skip the section.
|
|
126
|
-
|
|
127
|
-
The filter accepts a rule folder on either of two grounds. A folder holding a rule the
|
|
128
|
-
base stack resolves to is entitled to every target, read through the stack file so
|
|
129
|
-
a rule added to base later needs no code change. Every other rule folder is read off the folders the
|
|
130
|
-
target already carries, which is the fallback's only evidence of what a target
|
|
131
|
-
was entitled to before it recorded a chain. One rule folder can be reached by more than
|
|
132
|
-
one stack, so the test over-reports inside a folder the target holds, which
|
|
133
|
-
costs a line where under-reporting would cost the section its point.
|
|
134
|
-
|
|
135
|
-
A rule the target already holds is dropped by name. That is what keeps a rule the
|
|
136
|
-
toolkit moved between rule folders out of the list, since a rename reaches this
|
|
137
|
-
read as an addition and only the name tells the two apart.
|
|
138
|
-
|
|
139
|
-
This closes the dangling-citation case as a side effect rather than checking for
|
|
140
|
-
one. The live instance is a rule citing a sibling authored after the target's
|
|
141
|
-
install, and the section names the sibling as new rather than naming the citation
|
|
142
|
-
as broken. That is enough for an operator to act on, and it is not a citation
|
|
143
|
-
check.
|
|
144
|
-
|
|
145
|
-
## The reverse walk
|
|
146
|
-
|
|
147
|
-
`reverse` is the one section built by walking the target rather than the
|
|
148
|
-
catalog. Every other surface enumerates toolkit-owned keys and asks whether the
|
|
149
|
-
target matches, so a folder the toolkit deleted appears in none of them. It
|
|
150
|
-
carries `unclaimed` and `historyUnavailable`.
|
|
151
|
-
|
|
152
|
-
`unclaimed` names a folder the target holds at a top-level path the toolkit once
|
|
153
|
-
shipped and has since deleted. The candidate roots come from the toolkit's own
|
|
154
|
-
history rather than from a list, so a root dropped later is covered without a
|
|
155
|
-
code change. Scoping to those roots is what keeps the walk useful: walking the
|
|
156
|
-
whole tree reports every project folder as unclaimed, which is true and says
|
|
157
|
-
nothing.
|
|
158
|
-
|
|
159
|
-
The managed gate above applies here too, and it is the one place it surprises.
|
|
160
|
-
A directory holding a dropped folder and nothing else reports an empty `reverse`
|
|
161
|
-
rather than the folder, because it carries none of the three markers. Read an
|
|
162
|
-
empty section on an unmanaged target as a walk that never ran rather than as a
|
|
163
|
-
clean result.
|
|
164
|
-
|
|
165
|
-
Each entry carries `rel`, a file count, and an `attribution` of `dropped`,
|
|
166
|
-
`project`, or `unattributed`. A dropped folder and one the project wrote are the
|
|
167
|
-
same bytes at the same path, so the verdict is traced from history rather than
|
|
168
|
-
guessed from the filesystem.
|
|
169
|
-
|
|
170
|
-
Content matching a version the toolkit published reads as `dropped` and carries
|
|
171
|
-
the `since` commit that published it. Names the toolkit shipped holding content
|
|
172
|
-
it never published read as `unattributed`, which is a state in its own right
|
|
173
|
-
rather than a soft yes. No overlap at all reads as `project`, and the render
|
|
174
|
-
drops those while the JSON keeps them.
|
|
175
|
-
|
|
176
|
-
Only files whose path the toolkit once held are hashed, so a project folder
|
|
177
|
-
colliding on a retired name costs the walk no reads. The cost is that a file the
|
|
178
|
-
toolkit shipped and the target renamed goes unmatched, the same limit the
|
|
179
|
-
`unmigrated` count carries.
|
|
180
|
-
|
|
181
|
-
## What counts toward the gate
|
|
182
|
-
|
|
183
|
-
`unmigrated` counts toward `--exit-code`, since running the relocation closes it.
|
|
184
|
-
`superseded` and every seed state are excluded, for the reason `orphaned` already
|
|
185
|
-
is: only the user can move content they wrote, so failing a job on it leaves the
|
|
186
|
-
job red with no mechanical remedy.
|
|
187
|
-
|
|
188
|
-
`unmovedSurfaces` is excluded although `canon migrate surface-roots` closes it.
|
|
189
|
-
The move rewrites citations across the project, so it is a change the project
|
|
190
|
-
schedules, and a job counting it would go red the day a target updated the CLI.
|
|
191
|
-
|
|
192
|
-
`newRules` is excluded on a different ground, since a command does close it. What
|
|
193
|
-
excludes it is that installing a rule changes what a project is governed by, so
|
|
194
|
-
gating on the count would pressure a target into adopting rules nobody chose.
|
|
195
|
-
`newSkills` is excluded because it needs no command at all.
|
|
196
|
-
|
|
197
|
-
The whole `reverse` section is excluded on the same grounds, and more strongly.
|
|
198
|
-
Every entry in it is a judgment about a file the project may own, and one of its
|
|
199
|
-
three verdicts is a labelled unknown by design. The unmigrated detection shipped
|
|
200
|
-
that exact false positive once, failing a push with no action that cleared it,
|
|
201
|
-
so this section reports and gates nothing.
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Rule detection
|
|
3
|
-
description: Proposing opt-in governance rules from a target's dependencies and paths, the evidence file the verb reads, the record it emits, and its exit codes
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Rule detection
|
|
7
|
-
|
|
8
|
-
`canon gov detect` proposes the opt-in governance rules a target's evidence points at, and writes nothing. A rule no stack names reaches a project only through this verb, which `canon:target-setup` calls before it previews an install.
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
canon gov detect
|
|
12
|
-
canon gov detect ../my-app --stack node --json
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
| Option | Behavior |
|
|
16
|
-
| ----------------- | ------------------------------------------------ |
|
|
17
|
-
| `--stack <stack>` | Leave out every rule this stack already resolves |
|
|
18
|
-
| `--json` | Emit the record on stdout instead of the frame |
|
|
19
|
-
|
|
20
|
-
## Evidence
|
|
21
|
-
|
|
22
|
-
Each opt-in rule keeps a table in the toolkit's `governance/detect.toml`, keyed by rule basename. Its `deps` are package names, read from `package.json` (`dependencies` and `devDependencies`), `pyproject.toml`, `go.mod`, and `composer.json`. Its `files` are globs matched against the target's git-listed paths and against each folder on those paths, so `.github/workflows` matches a folder holding a workflow. A glob with no wildcard is also tested on disk, which is how `.canon/canvas` matches in a target that gitignores `.canon/`.
|
|
23
|
-
|
|
24
|
-
Both reads stop at depth two, which reaches a service folder and a workspace package under `packages/<name>/`. Outside git the verb walks the directory to the same depth and skips `.git`, `node_modules`, `vendor`, and `.venv`. A manifest that does not parse contributes nothing.
|
|
25
|
-
|
|
26
|
-
## Record
|
|
27
|
-
|
|
28
|
-
```json
|
|
29
|
-
{
|
|
30
|
-
"target": "/abs/path/my-app",
|
|
31
|
-
"stack": "node",
|
|
32
|
-
"proposals": [
|
|
33
|
-
{
|
|
34
|
-
"rule": "react",
|
|
35
|
-
"evidence": [{ "kind": "dep", "match": "react", "path": "package.json" }]
|
|
36
|
-
}
|
|
37
|
-
]
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
`kind` is `dep` for a dependency, with `path` naming the manifest that declares it, or `file` for a glob, with `path` naming what it matched. `stack` is null when no `--stack` was passed.
|
|
42
|
-
|
|
43
|
-
## Exit codes
|
|
44
|
-
|
|
45
|
-
The verb exits 0 on every readable target, including one with no evidence, which returns an empty `proposals` array. A target that does not exist and a `--stack` that does not resolve each exit 1 with the reason on stderr.
|
|
46
|
-
|
|
47
|
-
Install what the operator kept with `canon gov install --add <rules> <target>`, which needs no stack.
|
package/docs/agents/scripting.md
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Scripting
|
|
3
|
-
description: The runtime catalogs that replace hardcoded names, what each carries, and a headless invocation per domain
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Scripting
|
|
7
|
-
|
|
8
|
-
What a skill or script reads to discover names at runtime, and how each domain is invoked with no TTY.
|
|
9
|
-
|
|
10
|
-
## Runtime catalogs
|
|
11
|
-
|
|
12
|
-
Use these to discover what's available instead of hardcoding names.
|
|
13
|
-
|
|
14
|
-
| Command | Returns |
|
|
15
|
-
| --------------------------------- | ---------------------------------------------------------------- |
|
|
16
|
-
| `canon tooling list --json` | Stacks, extends chain, dep and script counts |
|
|
17
|
-
| `canon gov list --json` | Governance stacks, rule sets, evidence, and unreferenced rules |
|
|
18
|
-
| `canon gov detect --json` | Opt-in rules a target's dependencies and paths propose |
|
|
19
|
-
| `canon claude seeds list --json` | Seed doc sources with content |
|
|
20
|
-
| `canon claude skills list --json` | Plugin skills, descriptions, requirement flag, family vocabulary |
|
|
21
|
-
| `canon docs list --json` | Consumer docs plus per-domain context |
|
|
22
|
-
| `canon audits list --json` | Audits the set runs, the corpus each reads, and whether it gates |
|
|
23
|
-
|
|
24
|
-
### Catalog fields
|
|
25
|
-
|
|
26
|
-
Every catalog serializes through `JSON.stringify`, so a name carrying a quote
|
|
27
|
-
emits valid JSON. `canon tooling list` previously built
|
|
28
|
-
its output with `printf` and no escaping.
|
|
29
|
-
|
|
30
|
-
`canon claude seeds list` reads the same plan `canon claude init` applies, so the
|
|
31
|
-
listing and the install cannot disagree. It now reports
|
|
32
|
-
`canon/context/index.md`, which `init` has always installed and the listing
|
|
33
|
-
never named, and it emits the project-level `CLAUDE.md` last rather than first.
|
|
34
|
-
|
|
35
|
-
`canon gov list` reports each stack's rules already expanded. A stack entry names
|
|
36
|
-
either a rule or a whole rule folder under `governance/rules/`, and the folder
|
|
37
|
-
form reaches this listing as the rules it stands for rather than as the folder
|
|
38
|
-
name. A consumer deduping `--add` extras against a stack therefore reads the same
|
|
39
|
-
set the install writes, whichever form the stack file uses.
|
|
40
|
-
|
|
41
|
-
It also carries `unreferenced`, the rules no stack reaches, on every invocation
|
|
42
|
-
rather than behind a flag. These install only through `--add`, so the key answers
|
|
43
|
-
what a stack leaves out without a caller resolving every stack itself. The key is
|
|
44
|
-
present alongside `stacks` and `rules` and survives `--stacks` or `--rules`
|
|
45
|
-
narrowing the other two.
|
|
46
|
-
|
|
47
|
-
### The skills catalog
|
|
48
|
-
|
|
49
|
-
`canon claude skills list` reads `claude/skills/*/SKILL.md` and reports the folder
|
|
50
|
-
name with the frontmatter description, sorted by name. Internal skills under
|
|
51
|
-
`.claude/skills/` are excluded, since they never install into a target and a
|
|
52
|
-
count spanning both overstates what ships. A skill whose frontmatter is missing
|
|
53
|
-
or unparseable returns an empty description rather than failing the listing, so
|
|
54
|
-
one malformed file cannot hide the rest of the catalog. `--names` emits skill
|
|
55
|
-
names one per line.
|
|
56
|
-
|
|
57
|
-
Each skill in `--json` carries `family`, the `metadata.family` its frontmatter
|
|
58
|
-
declares, or `null` where it declares none. A top-level `families` array holds
|
|
59
|
-
the vocabulary as `{ key, group }` entries in skill map order, where `group` is
|
|
60
|
-
the map heading the family's rows sit under. Read a new skill's family from it
|
|
61
|
-
rather than from the map. `--by-family` prints the human listing as one step per
|
|
62
|
-
family, with a trailing step for any skill whose family is missing or unknown.
|
|
63
|
-
|
|
64
|
-
Each entry also carries `requirement`, whether the folder holds a sibling
|
|
65
|
-
`REQUIREMENT.md`. Every skill is meant to carry one, so a `false` is a gap to
|
|
66
|
-
close rather than a recorded exemption, and the flag answers which skills are
|
|
67
|
-
missing theirs without a caller listing the directory itself. `canon claude skills
|
|
68
|
-
audit` gates that rule across both corpora, so read this flag for the state of
|
|
69
|
-
the shipped catalog and the audit for whether a working tree conforms. Its
|
|
70
|
-
surface is in `skills-audit.md`.
|
|
71
|
-
|
|
72
|
-
## Non-interactive examples
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
# Report what a stack would change, writing nothing
|
|
76
|
-
CANON_NON_INTERACTIVE=1 canon tooling diff astro /path/to/project
|
|
77
|
-
|
|
78
|
-
# Sync a stack into a target project, overwriting its golden configs
|
|
79
|
-
CANON_NON_INTERACTIVE=1 canon tooling sync astro /path/to/project --write
|
|
80
|
-
|
|
81
|
-
# Install a governance stack (the stack argument is required headlessly)
|
|
82
|
-
CANON_NON_INTERACTIVE=1 canon gov install node --add astro,shadcn /path/to/project
|
|
83
|
-
|
|
84
|
-
# Update installed governance rules, dropping a retired .claude/GOV.md
|
|
85
|
-
CANON_NON_INTERACTIVE=1 canon gov sync /path/to/project
|
|
86
|
-
|
|
87
|
-
# Concatenate installed rules into a paste payload
|
|
88
|
-
CANON_NON_INTERACTIVE=1 canon gov build /path/to/project
|
|
89
|
-
|
|
90
|
-
# Sync a monorepo subtree, skipping the base layer the repo root already owns
|
|
91
|
-
CANON_NON_INTERACTIVE=1 canon tooling sync vite-react /path/to/repo/frontend --skip base --write
|
|
92
|
-
|
|
93
|
-
# Verify a stack end-to-end in a throwaway scaffold
|
|
94
|
-
canon tooling verify vite-react
|
|
95
|
-
|
|
96
|
-
# Apply one stack without scanning or prompting, for scripted provisioning
|
|
97
|
-
canon tooling inject base /path/to/project
|
|
98
|
-
canon tooling inject base /path/to/project --configs --seeds
|
|
99
|
-
|
|
100
|
-
# Drop managed gitignore entries a manifest no longer declares
|
|
101
|
-
# Prints the number removed on stdout, diagnostics on stderr
|
|
102
|
-
canon tooling prune-gitignore base /path/to/project
|
|
103
|
-
|
|
104
|
-
# Bootstrap a project. Any flag suppresses the confirmation prompt
|
|
105
|
-
CANON_NON_INTERACTIVE=1 canon init --stack node --skip wiki /path/to/project
|
|
106
|
-
|
|
107
|
-
# Run every domain sync. The git workflow is refused headlessly, so nothing is pushed
|
|
108
|
-
CANON_NON_INTERACTIVE=1 canon sync /path/to/project
|
|
109
|
-
|
|
110
|
-
# Scaffold .claude/wiki/ with a stub index. The target must already exist
|
|
111
|
-
CANON_NON_INTERACTIVE=1 canon wiki init /path/to/project
|
|
112
|
-
|
|
113
|
-
# Run a sandbox scenario non-interactively
|
|
114
|
-
SANDBOX_SCENARIO=sync canon sandbox infra:tooling
|
|
115
|
-
|
|
116
|
-
# Read every audit as one record. Exit 2 is a fact, 3 an audit that did not report
|
|
117
|
-
canon audits run --json
|
|
118
|
-
|
|
119
|
-
# Read committed state rather than an arriving change. Exit 2 carries findings
|
|
120
|
-
canon secrets scan --json
|
|
121
|
-
canon deps audit --json
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
The two state-scoped verbs both exit 2 on findings and mean different things by
|
|
125
|
-
it. A credential in the shipped tree is a fact and fails `canon audits run`, while
|
|
126
|
-
a published advisory is a judgment that reports and moves no verdict. Neither
|
|
127
|
-
reads a diff, so a consumer already running a review surface gets no overlap.
|
|
128
|
-
|
|
129
|
-
Both refuse rather than report clean when they have no corpus, and the refusal
|
|
130
|
-
reason is the field to branch on. A project publishing nothing refuses the secret
|
|
131
|
-
scan with `no-manifest`, and one whose dependencies are not installed refuses the
|
|
132
|
-
advisory check with `no-lockfile`. The aggregate reads those as an absent corpus
|
|
133
|
-
rather than a broken run, so neither pins its verdict at `incomplete`.
|
|
134
|
-
|
|
135
|
-
`canon tooling sync` is the one verb above whose flag is mandatory headlessly. It
|
|
136
|
-
overwrites every golden config a stack ships, which reaches the CI workflow, the
|
|
137
|
-
git hooks, the end-to-end harness, and the shell scripts under `scripts/`, so a
|
|
138
|
-
headless run carrying neither `--check` nor `--write` reports what it would
|
|
139
|
-
replace and exits 1 rather than applying it. Run `--check` first to read the
|
|
140
|
-
list, then `--write` to apply it. `canon tooling sync --help` names both, and
|
|
141
|
-
`canon tooling diff <stack> <target>` reports the per-stack path list resolved
|
|
142
|
-
against a real target.
|
package/src/markdown/growth.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { bodyLines } from '@/markdown/scan'
|
|
2
|
-
import {
|
|
3
|
-
CHECKPOINTS,
|
|
4
|
-
type Checkpoints,
|
|
5
|
-
type LongBlock,
|
|
6
|
-
longBlocks,
|
|
7
|
-
} from '@/markdown/structure'
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Reduces text to the words a reader meets, so a block reflowed, re-marked, or
|
|
11
|
-
* moved under another heading still matches the copy it came from.
|
|
12
|
-
*
|
|
13
|
-
* List markers and emphasis marks are dropped because turning a bullet into a
|
|
14
|
-
* labelled bullet or a paragraph changes the shape of a statement and none of
|
|
15
|
-
* its words, which is the edit the sweep makes. A word changed is a text
|
|
16
|
-
* changed, and that is what the growth stage exists to see.
|
|
17
|
-
*/
|
|
18
|
-
export function normalizeProse(text: string): string {
|
|
19
|
-
return text
|
|
20
|
-
.replace(/^\s*(?:[-*+]|\d+\.)\s+/gm, '')
|
|
21
|
-
.replace(/[*_]/g, '')
|
|
22
|
-
.replace(/\s+/g, ' ')
|
|
23
|
-
.trim()
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* The paragraphs and top-level bullets of `source` past their checkpoints whose
|
|
28
|
-
* text appears nowhere in `base`.
|
|
29
|
-
*
|
|
30
|
-
* Containment rather than line matching, so an unchanged long block passes
|
|
31
|
-
* wherever it sits and an edited or new one fails. `base` is every document the
|
|
32
|
-
* caller counts as the copy it may have come from, already normalized, since a
|
|
33
|
-
* block moved into a sibling entry is as unchanged as one left in place.
|
|
34
|
-
*/
|
|
35
|
-
export function grownBlocks(
|
|
36
|
-
source: string,
|
|
37
|
-
base: string,
|
|
38
|
-
checkpoints: Checkpoints = CHECKPOINTS,
|
|
39
|
-
): LongBlock[] {
|
|
40
|
-
return longBlocks(bodyLines(source), checkpoints).filter(
|
|
41
|
-
(block) => !base.includes(normalizeProse(block.text)),
|
|
42
|
-
)
|
|
43
|
-
}
|
|
File without changes
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import js from '@eslint/js'
|
|
2
|
-
import { defineConfig, globalIgnores } from 'eslint/config'
|
|
3
|
-
import prettier from 'eslint-config-prettier'
|
|
4
|
-
import checkFile from 'eslint-plugin-check-file'
|
|
5
|
-
import reactHooks from 'eslint-plugin-react-hooks'
|
|
6
|
-
import reactRefresh from 'eslint-plugin-react-refresh'
|
|
7
|
-
import simpleImportSort from 'eslint-plugin-simple-import-sort'
|
|
8
|
-
import vitest from 'eslint-plugin-vitest'
|
|
9
|
-
import globals from 'globals'
|
|
10
|
-
import tseslint from 'typescript-eslint'
|
|
11
|
-
|
|
12
|
-
export default defineConfig([
|
|
13
|
-
globalIgnores([
|
|
14
|
-
'.next',
|
|
15
|
-
'next-env.d.ts',
|
|
16
|
-
'dist',
|
|
17
|
-
'dist-ssr',
|
|
18
|
-
'coverage',
|
|
19
|
-
'release',
|
|
20
|
-
'.claude',
|
|
21
|
-
'.vscode',
|
|
22
|
-
'.husky',
|
|
23
|
-
'test-results',
|
|
24
|
-
'playwright-report',
|
|
25
|
-
'blob-report',
|
|
26
|
-
'playwright/.cache',
|
|
27
|
-
]),
|
|
28
|
-
js.configs.recommended,
|
|
29
|
-
...tseslint.configs.recommended,
|
|
30
|
-
{
|
|
31
|
-
files: ['**/*.{ts,tsx,js,jsx}'],
|
|
32
|
-
plugins: {
|
|
33
|
-
'react-hooks': reactHooks,
|
|
34
|
-
'react-refresh': reactRefresh,
|
|
35
|
-
'simple-import-sort': simpleImportSort,
|
|
36
|
-
'check-file': checkFile,
|
|
37
|
-
},
|
|
38
|
-
languageOptions: {
|
|
39
|
-
globals: {
|
|
40
|
-
...globals.browser,
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
rules: {
|
|
44
|
-
...reactHooks.configs.recommended.rules,
|
|
45
|
-
'react-refresh/only-export-components': [
|
|
46
|
-
'warn',
|
|
47
|
-
{ allowConstantExport: true },
|
|
48
|
-
],
|
|
49
|
-
'simple-import-sort/imports': 'error',
|
|
50
|
-
'simple-import-sort/exports': 'error',
|
|
51
|
-
'@typescript-eslint/no-unused-vars': [
|
|
52
|
-
'error',
|
|
53
|
-
{ varsIgnorePattern: '^_', argsIgnorePattern: '^_' },
|
|
54
|
-
],
|
|
55
|
-
'check-file/filename-naming-convention': [
|
|
56
|
-
'error',
|
|
57
|
-
{ '**/*.{ts,tsx}': 'KEBAB_CASE' },
|
|
58
|
-
{ ignoreMiddleExtensions: true },
|
|
59
|
-
],
|
|
60
|
-
'check-file/folder-naming-convention': [
|
|
61
|
-
'error',
|
|
62
|
-
{ 'src/**/!(__tests__)/': 'KEBAB_CASE' },
|
|
63
|
-
],
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
// App Router route and layout files export non-component values (metadata, route handlers) and use bracket, paren, and at-sign folder syntax (dynamic segments, route groups, parallel slots), which these rules flag as violations.
|
|
68
|
-
files: ['src/app/**/*.{ts,tsx}'],
|
|
69
|
-
rules: {
|
|
70
|
-
'react-refresh/only-export-components': 'off',
|
|
71
|
-
'check-file/folder-naming-convention': 'off',
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
files: ['**/*.test.{ts,tsx}', '**/*.spec.{ts,tsx}'],
|
|
76
|
-
...vitest.configs.recommended,
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
files: [
|
|
80
|
-
'*.config.{js,mjs,cjs,ts}',
|
|
81
|
-
'vitest.config.ts',
|
|
82
|
-
'playwright.config.ts',
|
|
83
|
-
],
|
|
84
|
-
languageOptions: {
|
|
85
|
-
globals: {
|
|
86
|
-
...globals.node,
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
|
-
prettier,
|
|
91
|
-
])
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import js from '@eslint/js'
|
|
2
|
-
import { defineConfig, globalIgnores } from 'eslint/config'
|
|
3
|
-
import prettier from 'eslint-config-prettier'
|
|
4
|
-
import checkFile from 'eslint-plugin-check-file'
|
|
5
|
-
import reactHooks from 'eslint-plugin-react-hooks'
|
|
6
|
-
import reactRefresh from 'eslint-plugin-react-refresh'
|
|
7
|
-
import simpleImportSort from 'eslint-plugin-simple-import-sort'
|
|
8
|
-
import vitest from 'eslint-plugin-vitest'
|
|
9
|
-
import globals from 'globals'
|
|
10
|
-
import tseslint from 'typescript-eslint'
|
|
11
|
-
|
|
12
|
-
export default defineConfig([
|
|
13
|
-
globalIgnores([
|
|
14
|
-
'dist',
|
|
15
|
-
'dist-ssr',
|
|
16
|
-
'coverage',
|
|
17
|
-
'release',
|
|
18
|
-
'.claude',
|
|
19
|
-
'.vscode',
|
|
20
|
-
'.husky',
|
|
21
|
-
'test-results',
|
|
22
|
-
'playwright-report',
|
|
23
|
-
'blob-report',
|
|
24
|
-
'playwright/.cache',
|
|
25
|
-
]),
|
|
26
|
-
js.configs.recommended,
|
|
27
|
-
...tseslint.configs.recommended,
|
|
28
|
-
{
|
|
29
|
-
files: ['**/*.{ts,tsx,js,jsx}'],
|
|
30
|
-
plugins: {
|
|
31
|
-
'react-hooks': reactHooks,
|
|
32
|
-
'react-refresh': reactRefresh,
|
|
33
|
-
'simple-import-sort': simpleImportSort,
|
|
34
|
-
'check-file': checkFile,
|
|
35
|
-
},
|
|
36
|
-
languageOptions: {
|
|
37
|
-
globals: {
|
|
38
|
-
...globals.browser,
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
rules: {
|
|
42
|
-
...reactHooks.configs.recommended.rules,
|
|
43
|
-
'react-refresh/only-export-components': [
|
|
44
|
-
'warn',
|
|
45
|
-
{ allowConstantExport: true },
|
|
46
|
-
],
|
|
47
|
-
'simple-import-sort/imports': 'error',
|
|
48
|
-
'simple-import-sort/exports': 'error',
|
|
49
|
-
'@typescript-eslint/no-unused-vars': [
|
|
50
|
-
'error',
|
|
51
|
-
{ varsIgnorePattern: '^_', argsIgnorePattern: '^_' },
|
|
52
|
-
],
|
|
53
|
-
'check-file/filename-naming-convention': [
|
|
54
|
-
'error',
|
|
55
|
-
{ '**/!(App).{ts,tsx}': 'KEBAB_CASE' },
|
|
56
|
-
{ ignoreMiddleExtensions: true },
|
|
57
|
-
],
|
|
58
|
-
'check-file/folder-naming-convention': [
|
|
59
|
-
'error',
|
|
60
|
-
{ 'src/**/!(__tests__)/': 'KEBAB_CASE' },
|
|
61
|
-
],
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
files: ['**/*.test.{ts,tsx}', '**/*.spec.{ts,tsx}'],
|
|
66
|
-
...vitest.configs.recommended,
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
files: [
|
|
70
|
-
'*.config.{js,mjs,cjs,ts}',
|
|
71
|
-
'vite.config.ts',
|
|
72
|
-
'vitest.config.ts',
|
|
73
|
-
'playwright.config.ts',
|
|
74
|
-
],
|
|
75
|
-
languageOptions: {
|
|
76
|
-
globals: {
|
|
77
|
-
...globals.node,
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
prettier,
|
|
82
|
-
])
|