@ethlete/agent-rules 0.1.0-next.2 → 0.1.0-next.20
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/CHANGELOG.md +269 -0
- package/README.md +350 -29
- package/THIRD-PARTY-LICENSES.md +35 -0
- package/content/git-hooks/post-checkout.sh +10 -0
- package/content/git-hooks/pre-push.sh +5 -0
- package/content/hooks/context-warning.py +766 -108
- package/content/hooks/subagent-model-policy.py +187 -0
- package/content/output-styles/ste-clarity.md +131 -0
- package/content/rules/app-styling.md +59 -0
- package/content/rules/comments.md +53 -20
- package/content/rules/lint-and-format.md +6 -5
- package/content/rules/nx-layout.md +47 -0
- package/content/rules/reactive-state.md +1 -1
- package/content/rules/styling.md +9 -7
- package/content/rules/subagent-models.md +29 -0
- package/content/skills/angular-patterns/SKILL.md +30 -7
- package/content/skills/api-source/SKILL.md +130 -0
- package/content/skills/app-testing/SKILL.md +141 -0
- package/content/skills/codex-subagent/SKILL.md +90 -0
- package/content/skills/codex-subagent/codex-agent.mjs +229 -0
- package/content/skills/design-exploration/SKILL.md +205 -0
- package/content/skills/design-exploration/check-story.mjs +139 -0
- package/content/skills/design-exploration/shoot-template.mjs +61 -0
- package/content/skills/domain-modeling/ADR-FORMAT.md +47 -0
- package/content/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
- package/content/skills/domain-modeling/SKILL.md +80 -0
- package/content/skills/figma-export/SKILL.md +191 -0
- package/content/skills/figma-export/dump-figma-layers.py +83 -0
- package/content/skills/figma-export/dump-figma-svg.py +235 -0
- package/content/skills/figma-export/measure-template.mjs +87 -0
- package/content/skills/git-commit/SKILL.md +6 -7
- package/content/skills/git-flow/SKILL.md +87 -0
- package/content/skills/grill-with-docs/SKILL.md +13 -0
- package/content/skills/grilling/SKILL.md +34 -0
- package/content/skills/handoff/SKILL.md +74 -4
- package/content/skills/query/SKILL.md +165 -64
- package/content/skills/rxjs-signals/SKILL.md +31 -4
- package/content/skills/sdk-docs/SKILL.md +50 -14
- package/content/skills/sdk-local-build/SKILL.md +30 -10
- package/content/skills/sdk-local-build/sdk-local-baseline.mjs +64 -0
- package/content/skills/sdk-source/SKILL.md +49 -21
- package/content/skills/sdk-update/SKILL.md +96 -0
- package/content/skills/story-styling/SKILL.md +10 -8
- package/content/skills/styleguide/SKILL.md +12 -7
- package/content/skills/styleguide/assets.md +54 -0
- package/content/skills/styleguide/changesets.md +17 -0
- package/content/skills/styleguide/file-structure.md +73 -0
- package/content/skills/styleguide/lint-rule-lookup.md +51 -0
- package/content/skills/styleguide/storybook-structure.md +25 -0
- package/content/skills/theming/SKILL.md +41 -28
- package/content/skills/timetrack/SKILL.md +397 -0
- package/content/skills/verify-in-app/SKILL.md +107 -0
- package/migrations/app-styling-utilities.md +63 -0
- package/migrations/list-state-query-form.md +20 -0
- package/migrations/nx-layout.md +29 -0
- package/migrations/sdk-components-over-hand-built-ui.md +27 -0
- package/migrations/search-query-field.md +52 -0
- package/migrations.json +48 -0
- package/package.json +16 -2
- package/src/index.js +63 -28
- package/src/index.js.map +1 -1
- package/src/lib/cli-args.d.ts +9 -0
- package/src/lib/cli-args.js +48 -0
- package/src/lib/cli-args.js.map +1 -0
- package/src/lib/commitlint.d.ts +10 -0
- package/src/lib/commitlint.js +51 -0
- package/src/lib/commitlint.js.map +1 -0
- package/src/lib/config.d.ts +38 -4
- package/src/lib/config.js +84 -8
- package/src/lib/config.js.map +1 -1
- package/src/lib/filter.d.ts +2 -0
- package/src/lib/filter.js +4 -4
- package/src/lib/filter.js.map +1 -1
- package/src/lib/frontmatter.d.ts +2 -0
- package/src/lib/frontmatter.js +33 -5
- package/src/lib/frontmatter.js.map +1 -1
- package/src/lib/git-flow/build.d.ts +35 -0
- package/src/lib/git-flow/build.js +24 -0
- package/src/lib/git-flow/build.js.map +1 -0
- package/src/lib/git-flow/config.d.ts +59 -0
- package/src/lib/git-flow/config.js +50 -0
- package/src/lib/git-flow/config.js.map +1 -0
- package/src/lib/git-flow/index.d.ts +6 -0
- package/src/lib/git-flow/index.js +10 -0
- package/src/lib/git-flow/index.js.map +1 -0
- package/src/lib/git-flow/parse.d.ts +49 -0
- package/src/lib/git-flow/parse.js +300 -0
- package/src/lib/git-flow/parse.js.map +1 -0
- package/src/lib/git-flow/rename.d.ts +24 -0
- package/src/lib/git-flow/rename.js +70 -0
- package/src/lib/git-flow/rename.js.map +1 -0
- package/src/lib/git-flow/start.d.ts +49 -0
- package/src/lib/git-flow/start.js +57 -0
- package/src/lib/git-flow/start.js.map +1 -0
- package/src/lib/git-flow/validate.d.ts +34 -0
- package/src/lib/git-flow/validate.js +72 -0
- package/src/lib/git-flow/validate.js.map +1 -0
- package/src/lib/git-flow-command.d.ts +4 -0
- package/src/lib/git-flow-command.js +157 -0
- package/src/lib/git-flow-command.js.map +1 -0
- package/src/lib/git-flow-repair.d.ts +17 -0
- package/src/lib/git-flow-repair.js +157 -0
- package/src/lib/git-flow-repair.js.map +1 -0
- package/src/lib/git-flow-start.d.ts +20 -0
- package/src/lib/git-flow-start.js +132 -0
- package/src/lib/git-flow-start.js.map +1 -0
- package/src/lib/git.d.ts +64 -0
- package/src/lib/git.js +131 -0
- package/src/lib/git.js.map +1 -0
- package/src/lib/gitlab.d.ts +35 -0
- package/src/lib/gitlab.js +108 -0
- package/src/lib/gitlab.js.map +1 -0
- package/src/lib/index.d.ts +2 -0
- package/src/lib/index.js +2 -0
- package/src/lib/index.js.map +1 -1
- package/src/lib/migrate.js +1 -1
- package/src/lib/migrate.js.map +1 -1
- package/src/lib/output-style-command.d.ts +3 -0
- package/src/lib/output-style-command.js +69 -0
- package/src/lib/output-style-command.js.map +1 -0
- package/src/lib/output-style.d.ts +38 -0
- package/src/lib/output-style.js +134 -0
- package/src/lib/output-style.js.map +1 -0
- package/src/lib/owned-paths.js +27 -3
- package/src/lib/owned-paths.js.map +1 -1
- package/src/lib/package-runner.d.ts +3 -0
- package/src/lib/package-runner.js +69 -0
- package/src/lib/package-runner.js.map +1 -0
- package/src/lib/plain-text.d.ts +9 -0
- package/src/lib/plain-text.js +22 -0
- package/src/lib/plain-text.js.map +1 -0
- package/src/lib/plan.d.ts +6 -6
- package/src/lib/plan.js +147 -40
- package/src/lib/plan.js.map +1 -1
- package/src/lib/prompt.d.ts +8 -0
- package/src/lib/prompt.js +27 -0
- package/src/lib/prompt.js.map +1 -0
- package/src/lib/render.d.ts +24 -2
- package/src/lib/render.js +39 -10
- package/src/lib/render.js.map +1 -1
- package/src/lib/sync.d.ts +0 -1
- package/src/lib/sync.js +23 -15
- package/src/lib/sync.js.map +1 -1
- package/src/lib/targets/agents-skills.js +1 -1
- package/src/lib/targets/agents-skills.js.map +1 -1
- package/src/lib/targets/claude-hooks.d.ts +1 -23
- package/src/lib/targets/claude-hooks.js +17 -85
- package/src/lib/targets/claude-hooks.js.map +1 -1
- package/src/lib/targets/claude.js +1 -2
- package/src/lib/targets/claude.js.map +1 -1
- package/src/lib/targets/codex-hooks.d.ts +12 -0
- package/src/lib/targets/codex-hooks.js +34 -0
- package/src/lib/targets/codex-hooks.js.map +1 -0
- package/src/lib/targets/codex.js +4 -4
- package/src/lib/targets/codex.js.map +1 -1
- package/src/lib/targets/copilot.js +3 -3
- package/src/lib/targets/copilot.js.map +1 -1
- package/src/lib/targets/cursor.js +2 -2
- package/src/lib/targets/cursor.js.map +1 -1
- package/src/lib/targets/git-hooks.d.ts +24 -0
- package/src/lib/targets/git-hooks.js +71 -0
- package/src/lib/targets/git-hooks.js.map +1 -0
- package/src/lib/targets/hooks-shared.d.ts +58 -0
- package/src/lib/targets/hooks-shared.js +128 -0
- package/src/lib/targets/hooks-shared.js.map +1 -0
- package/src/lib/targets/shared.d.ts +1 -9
- package/src/lib/targets/shared.js +4 -8
- package/src/lib/targets/shared.js.map +1 -1
- package/src/lib/timetrack-command.d.ts +11 -0
- package/src/lib/timetrack-command.js +1055 -0
- package/src/lib/timetrack-command.js.map +1 -0
- package/src/lib/timetrack-snapshot.d.ts +55 -0
- package/src/lib/timetrack-snapshot.js +120 -0
- package/src/lib/timetrack-snapshot.js.map +1 -0
- package/src/lib/timetrack.d.ts +561 -0
- package/src/lib/timetrack.js +271 -0
- package/src/lib/timetrack.js.map +1 -0
- package/content/skills/styleguide/STYLEGUIDE.md +0 -520
|
@@ -20,6 +20,13 @@ Two sources, both authoritative for different things:
|
|
|
20
20
|
| **Docs site** | {%docsBaseUrl%} | Prose guides: what a thing is for, options, defaults, behaviour, migration notes |
|
|
21
21
|
| **Storybook** | {%sdkStorybookUrl%} | The live component: every variant rendered, the real controls, and the exact markup a story uses |
|
|
22
22
|
|
|
23
|
+
## First: app setup
|
|
24
|
+
|
|
25
|
+
Before the first component, work through `{%docsBaseUrl%}/components/setup` - the 62.5% root
|
|
26
|
+
font size, Tailwind 4 theme generation, a `type: 'error'` color theme, and the providers
|
|
27
|
+
(`provideOverlay`, `provideDateLocale`, label tokens, …). Missing any of them fails at runtime,
|
|
28
|
+
not at compile time.
|
|
29
|
+
|
|
23
30
|
## Finding the right page
|
|
24
31
|
|
|
25
32
|
Page URLs follow `{%docsBaseUrl%}/<lib>/<topic>`. The library sections:
|
|
@@ -28,23 +35,51 @@ Page URLs follow `{%docsBaseUrl%}/<lib>/<topic>`. The library sections:
|
|
|
28
35
|
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
29
36
|
| `/components/` | The active UI library - one guide per domain (see the list below) |
|
|
30
37
|
| `/core/` | Framework primitives: `theming`, `overlay-runtime`, `signal-utils`, `element-signals`, `animations`, `scrolling`, `drag-resize`, `directives-pipes`, `providers`, `seo`, `utilities` |
|
|
31
|
-
| `/query/` | Data fetching
|
|
38
|
+
| `/query/` | Data fetching; load the dedicated query guide first when this package emitted one |
|
|
32
39
|
| `/cdk/` | The predecessor UI toolkit, maintenance mode. Only for code that still uses it |
|
|
33
40
|
| `/contentful/`, `/cli/`, `/eslint/`, `/types/` | The remaining packages |
|
|
34
41
|
|
|
35
42
|
Component domains under `/components/`:
|
|
36
43
|
|
|
37
|
-
`accordion` `
|
|
38
|
-
`
|
|
39
|
-
`
|
|
40
|
-
`
|
|
41
|
-
`
|
|
42
|
-
`
|
|
43
|
-
`
|
|
44
|
+
`accordion` `avatar` `badge` `banner` `bracket` `bracket-prediction` `bracket-rounds-list`
|
|
45
|
+
`breadcrumb` `button` `calendar` `card` `carousel` `cascader` `chart` `chip`
|
|
46
|
+
`choice-inputs` `command-palette` `copy-button` `date-time-inputs` `description-list`
|
|
47
|
+
`divider` `dropzone` `empty-state` `error-codes` `filter-overlay` `floating-action`
|
|
48
|
+
`focus-ring` `forms` `grid` `icon` `kbd` `line-chart` `loader` `localization` `masonry`
|
|
49
|
+
`match` `menu` `mixed-state` `notification` `overlay-openers` `overlays` `paged-query-trigger`
|
|
50
|
+
`pagination` `picture` `pie-chart` `progress-steps` `query-error` `rich-text-editor` `sankey-chart`
|
|
51
|
+
`scheduler` `scrollable` `scrollbar` `select` `setup` `skeleton` `slider` `sport-recipes` `stat-tile`
|
|
52
|
+
`standings` `standings-pick` `stream` `table` `tabs` `testing` `text-inputs` `time-picker`
|
|
53
|
+
`timeline` `toggletip` `toolbar` `tooltip` `tree`
|
|
54
|
+
|
|
55
|
+
**Check this list before you build any UI by hand.** Some needs hide behind a name you
|
|
56
|
+
would not guess:
|
|
57
|
+
|
|
58
|
+
| You need | Read |
|
|
59
|
+
| ------------------------------------------ | ----------------------------------------- |
|
|
60
|
+
| Bar or stacked bar chart, series legend | `chart` |
|
|
61
|
+
| Line, pie, flow chart | `line-chart`, `pie-chart`, `sankey-chart` |
|
|
62
|
+
| Progress bar, spinner | `loader` |
|
|
63
|
+
| Initials or user picture in a circle | `avatar` |
|
|
64
|
+
| "No results" or empty table state | `empty-state` |
|
|
65
|
+
| Failed request with a retry button | `query-error` |
|
|
66
|
+
| Status pill, count | `badge` |
|
|
67
|
+
| Tab strip that switches a view or a filter | `tabs` (nav tabs) |
|
|
68
|
+
| Dialog, bottom sheet, side panel | `overlays`, `overlay-openers` |
|
|
69
|
+
| Label and value pairs | `description-list` |
|
|
70
|
+
| Stepper, wizard progress | `progress-steps` |
|
|
71
|
+
| Providers and styles a new app needs | `setup` |
|
|
44
72
|
|
|
45
73
|
So the table guide is `{%docsBaseUrl%}/components/table`, the menu guide
|
|
46
|
-
`{%docsBaseUrl%}/components/menu`, and so on.
|
|
47
|
-
|
|
74
|
+
`{%docsBaseUrl%}/components/menu`, and so on.
|
|
75
|
+
|
|
76
|
+
That list is a snapshot. The site itself is machine-readable, so fetch rather than guess:
|
|
77
|
+
|
|
78
|
+
- `{%docsBaseUrl%}/llms.txt` - every page's title and path as of the last deploy. Use it
|
|
79
|
+
when a name isn't in the list above, or to check the list hasn't drifted.
|
|
80
|
+
- Append `.md` to any page URL - `{%docsBaseUrl%}/components/button.md` - to get raw
|
|
81
|
+
markdown instead of the rendered page. Prefer this over `/llms-full.txt`, which is the
|
|
82
|
+
entire site in one ~1 MB file.
|
|
48
83
|
|
|
49
84
|
## How to use them
|
|
50
85
|
|
|
@@ -59,13 +94,14 @@ So the table guide is `{%docsBaseUrl%}/components/table`, the menu guide
|
|
|
59
94
|
`-next` prereleases should read `{%docsBaseUrl%}` and `{%sdkStorybookUrl%}` only if
|
|
60
95
|
they are the matching prerelease deployments, otherwise expect drift and verify
|
|
61
96
|
against the installed `.d.ts` in `node_modules/@ethlete/<lib>`.
|
|
62
|
-
-
|
|
63
|
-
|
|
97
|
+
- **Use the SDK skills instead of searching `node_modules` ad hoc.** The installed `.d.ts`
|
|
98
|
+
files are authoritative for the public type surface this consumer can compile against.
|
|
99
|
+
Source matching that installed build is authoritative for runtime implementation details.
|
|
100
|
+
A dirty or ahead `next` checkout is not automatically source for the installed package.
|
|
101
|
+
If docs and installed types disagree, report the drift.
|
|
64
102
|
- **Never treat a `subtle` namespace as public API.** Anything exposed under `subtle` is
|
|
65
103
|
an unsupported escape hatch that can change without a major version.
|
|
66
104
|
|
|
67
105
|
## Related
|
|
68
106
|
|
|
69
|
-
- Data fetching has its own guide: {%skill:query%}
|
|
70
|
-
- Theming tokens and how to register themes: {%skill:theming%}
|
|
71
107
|
- When the docs cannot answer it, read the SDK source: {%skill:sdk-source%}
|
|
@@ -17,12 +17,14 @@ published yet, or when you are iterating on it.
|
|
|
17
17
|
|
|
18
18
|
## 1. Prerequisites
|
|
19
19
|
|
|
20
|
-
- The checkout path comes from `sdkSourcePath` in `ethlete
|
|
20
|
+
- The checkout path comes from `sdkSourcePath` in `ethlete.config.local.json`;
|
|
21
21
|
{%skill:sdk-source%} covers resolving it and what to check before trusting it.
|
|
22
22
|
- The checkout has its dependencies installed (`yarn install` in the checkout root - the
|
|
23
23
|
SDK repo is a Yarn 4 workspace).
|
|
24
|
-
-
|
|
25
|
-
|
|
24
|
+
- Check which branch it is on before building - unless the user said otherwise, that
|
|
25
|
+
should be `next`, up to date with `origin/next`. Building `main` when your app runs
|
|
26
|
+
`-next` prereleases swaps in a completely different API surface, and building a stale
|
|
27
|
+
`next` rebuilds a bug that is already fixed upstream. Ask before changing its branch.
|
|
26
28
|
|
|
27
29
|
## 2. Build the libraries you changed
|
|
28
30
|
|
|
@@ -42,6 +44,21 @@ If a build stalls trying to reach Nx Cloud, re-run it with `NX_NO_CLOUD=true`.
|
|
|
42
44
|
|
|
43
45
|
## 3. Point this repo at the build
|
|
44
46
|
|
|
47
|
+
Preflight the manifest and lockfile before changing either:
|
|
48
|
+
|
|
49
|
+
Use {%resource:sdk-local-baseline.mjs%} to capture their exact bytes:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
git status --short -- <manifest> yarn.lock
|
|
53
|
+
sdk_local_baseline_dir=$(mktemp -d)
|
|
54
|
+
node <path-to-sdk-local-baseline.mjs> capture <manifest> yarn.lock "$sdk_local_baseline_dir"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
If either file already differs and you cannot tell who owns the edit, stop and ask. If
|
|
58
|
+
the user authorizes the experiment, keep the exact baseline above; pre-existing edits
|
|
59
|
+
are part of it and must survive byte-for-byte. If either file changes for another reason
|
|
60
|
+
during the experiment, stop and take a new agreed baseline before cleanup.
|
|
61
|
+
|
|
45
62
|
Edit the version specifiers in `package.json` (the one declaring the dependency - in a
|
|
46
63
|
workspace that is the workspace package, not necessarily the root):
|
|
47
64
|
|
|
@@ -95,17 +112,20 @@ reinstalling; the restart in step 3 is still required.)
|
|
|
95
112
|
## 6. Clean up when you are done
|
|
96
113
|
|
|
97
114
|
Leaving a `file:` dependency behind breaks every other checkout and CI, because the path
|
|
98
|
-
does not exist there. Restore
|
|
115
|
+
does not exist there. Restore the exact recorded baseline as part of the same task:
|
|
99
116
|
|
|
100
117
|
```bash
|
|
101
|
-
|
|
102
|
-
yarn install
|
|
103
|
-
|
|
118
|
+
node <path-to-sdk-local-baseline.mjs> restore <manifest> yarn.lock "$sdk_local_baseline_dir"
|
|
119
|
+
yarn install --immutable
|
|
120
|
+
node <path-to-sdk-local-baseline.mjs> verify <manifest> yarn.lock "$sdk_local_baseline_dir"
|
|
104
121
|
```
|
|
105
122
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
123
|
+
The verification proves that the local-build delta is gone while preserving any edits
|
|
124
|
+
that existed before it. Do not require either file to be globally clean, and do
|
|
125
|
+
not run whole-file `git checkout` or `git restore`. Report the temporary baseline path;
|
|
126
|
+
it can be removed after verification because this workflow created it. Never commit a
|
|
127
|
+
`file:` specifier or the lockfile it produced. If the verified fix is still unreleased,
|
|
128
|
+
say what has to be published instead of shipping a local path.
|
|
109
129
|
|
|
110
130
|
## Related
|
|
111
131
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { join, resolve } from 'node:path';
|
|
4
|
+
|
|
5
|
+
const baselinePaths = (baselineDir) => ({
|
|
6
|
+
manifest: join(baselineDir, 'package.json.baseline'),
|
|
7
|
+
lockfile: join(baselineDir, 'yarn.lock.baseline'),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const captureBaseline = (manifestPath, lockfilePath, baselineDir) => {
|
|
11
|
+
const baseline = baselinePaths(baselineDir);
|
|
12
|
+
|
|
13
|
+
mkdirSync(baselineDir, { recursive: true });
|
|
14
|
+
|
|
15
|
+
if (existsSync(baseline.manifest) || existsSync(baseline.lockfile)) {
|
|
16
|
+
throw new Error(`Baseline already exists in ${baselineDir}.`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
copyFileSync(manifestPath, baseline.manifest);
|
|
20
|
+
copyFileSync(lockfilePath, baseline.lockfile);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const restoreBaseline = (manifestPath, lockfilePath, baselineDir) => {
|
|
24
|
+
const baseline = baselinePaths(baselineDir);
|
|
25
|
+
|
|
26
|
+
copyFileSync(baseline.manifest, manifestPath);
|
|
27
|
+
copyFileSync(baseline.lockfile, lockfilePath);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const verifyBaseline = (manifestPath, lockfilePath, baselineDir) => {
|
|
31
|
+
const baseline = baselinePaths(baselineDir);
|
|
32
|
+
|
|
33
|
+
for (const [current, recorded] of [
|
|
34
|
+
[manifestPath, baseline.manifest],
|
|
35
|
+
[lockfilePath, baseline.lockfile],
|
|
36
|
+
]) {
|
|
37
|
+
if (!readFileSync(current).equals(readFileSync(recorded))) {
|
|
38
|
+
throw new Error(`${current} does not match its recorded baseline.`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const run = () => {
|
|
44
|
+
const [mode, manifestPath, lockfilePath, baselineDir] = process.argv.slice(2);
|
|
45
|
+
|
|
46
|
+
if (!mode || !manifestPath || !lockfilePath || !baselineDir) {
|
|
47
|
+
throw new Error('Usage: sdk-local-baseline.mjs <capture|restore|verify> <manifest> <lockfile> <baseline-dir>');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const actions = {
|
|
51
|
+
capture: captureBaseline,
|
|
52
|
+
restore: restoreBaseline,
|
|
53
|
+
verify: verifyBaseline,
|
|
54
|
+
};
|
|
55
|
+
const action = actions[mode];
|
|
56
|
+
|
|
57
|
+
if (!action) throw new Error(`Unknown mode "${mode}".`);
|
|
58
|
+
|
|
59
|
+
action(manifestPath, lockfilePath, baselineDir);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
if (process.argv[1] && fileURLToPath(import.meta.url) === resolve(process.argv[1])) {
|
|
63
|
+
run();
|
|
64
|
+
}
|
|
@@ -21,7 +21,7 @@ first. Reach for the source when the docs genuinely cannot answer the question:
|
|
|
21
21
|
|
|
22
22
|
## 1. Resolve the checkout
|
|
23
23
|
|
|
24
|
-
The path is per machine, so it lives in the gitignored `ethlete
|
|
24
|
+
The path is per machine, so it lives in the gitignored `ethlete.config.local.json`
|
|
25
25
|
at the repo root:
|
|
26
26
|
|
|
27
27
|
```json
|
|
@@ -30,6 +30,9 @@ at the repo root:
|
|
|
30
30
|
}
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
Older checkouts still keep this key in `ethlete-agents.config.local.json`. Read that file as a
|
|
34
|
+
fallback when `ethlete.config.local.json` is absent.
|
|
35
|
+
|
|
33
36
|
Read that file before searching anywhere. A relative path is resolved from the repo root.
|
|
34
37
|
|
|
35
38
|
If the file or the key is missing, **do not guess a path** and do not clone the
|
|
@@ -38,27 +41,50 @@ holds the full `.d.ts` surface of exactly the version this repo runs - and to
|
|
|
38
41
|
{%docsBaseUrl%}. Then tell the user a local checkout would help, and offer the snippet
|
|
39
42
|
above (the file is gitignored, so adding it changes nothing for anyone else).
|
|
40
43
|
|
|
41
|
-
## 2.
|
|
44
|
+
## 2. Match evidence to the installed package
|
|
45
|
+
|
|
46
|
+
Start with this routing:
|
|
47
|
+
|
|
48
|
+
- Installed `.d.ts` files are authoritative for the public type surface available to
|
|
49
|
+
this consumer.
|
|
50
|
+
- Source matching the installed build is authoritative for runtime implementation
|
|
51
|
+
details.
|
|
52
|
+
- Docs explain intended usage and defaults, but can drift from a prerelease.
|
|
53
|
+
- A dirty or ahead `next` checkout is not automatically source for the installed build.
|
|
54
|
+
|
|
55
|
+
Compare the installed package version with the checkout version before attributing
|
|
56
|
+
runtime behavior to the checkout:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
grep '"@ethlete/' package.json
|
|
60
|
+
grep -m1 '"version"' <sdkSourcePath>/libs/<lib>/package.json
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Matching version strings are necessary but not sufficient when the checkout is ahead of
|
|
64
|
+
the published commit. Never write consumer code against source that the installed types
|
|
65
|
+
do not expose.
|
|
66
|
+
|
|
67
|
+
## 3. Check only the paths that answer the question
|
|
42
68
|
|
|
43
|
-
|
|
44
|
-
|
|
69
|
+
Resolve the implementation, public barrel, specs, and docs relevant to the question.
|
|
70
|
+
Then inspect state for those paths:
|
|
45
71
|
|
|
46
72
|
```bash
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
git -C <sdkSourcePath>
|
|
73
|
+
git -C <sdkSourcePath> status -sb
|
|
74
|
+
git -C <sdkSourcePath> status --short -- <relevant-paths>
|
|
75
|
+
git -C <sdkSourcePath> diff -- <relevant-paths>
|
|
50
76
|
```
|
|
51
77
|
|
|
52
|
-
|
|
78
|
+
Unrelated dirty files, another branch, or unrelated ahead commits do not block a source
|
|
79
|
+
lookup. If relevant paths are dirty or differ in the relevant commit range, label the
|
|
80
|
+
worktree behavior separately from published behavior. Ask only when that distinction
|
|
81
|
+
changes the answer.
|
|
53
82
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
against it, and never assume it is available - say what release it needs.
|
|
58
|
-
- A dirty checkout may contain someone's work in progress. Say so rather than quoting
|
|
59
|
-
it as SDK behaviour.
|
|
83
|
+
Use existing remote refs first. `git fetch` preserves worktree files but uses the network
|
|
84
|
+
and mutates remote refs. Fetch only when freshness is material, and request any approval
|
|
85
|
+
the environment requires. Never switch, pull, stash, or reset the checkout yourself.
|
|
60
86
|
|
|
61
|
-
##
|
|
87
|
+
## 4. Where things live
|
|
62
88
|
|
|
63
89
|
Paths are relative to the checkout root:
|
|
64
90
|
|
|
@@ -71,7 +97,7 @@ Paths are relative to the checkout root:
|
|
|
71
97
|
| `libs/cdk/` | The predecessor UI toolkit, maintenance mode - only for code still on it |
|
|
72
98
|
| `libs/eslint-plugin/src/` | The lint rules, including the message text explaining each one |
|
|
73
99
|
| `apps/docs/` | The markdown behind {%docsBaseUrl%} |
|
|
74
|
-
| `apps/
|
|
100
|
+
| `apps/storybook/` | The Storybook app - stories also live next to each component |
|
|
75
101
|
|
|
76
102
|
Inside a component domain: `<name>.component.ts` with its `.css` next to it,
|
|
77
103
|
`<name>.imports.ts` (the imports array to spread into a consumer component),
|
|
@@ -79,7 +105,7 @@ Inside a component domain: `<name>.component.ts` with its `.css` next to it,
|
|
|
79
105
|
`index.ts` as the barrel. The lib's public surface is `libs/<lib>/src/index.ts` -
|
|
80
106
|
anything not re-exported from there is internal, whatever it looks like.
|
|
81
107
|
|
|
82
|
-
##
|
|
108
|
+
## 5. Search it, don't read it whole
|
|
83
109
|
|
|
84
110
|
```bash
|
|
85
111
|
rg -n "etButton" <sdkSourcePath>/libs/components/src --glob '!*.spec.ts' # a selector
|
|
@@ -91,12 +117,14 @@ Specs are the cheapest description of intended behaviour - `<name>.component.spe
|
|
|
91
117
|
next to a component usually answers "is this supposed to happen?" faster than the
|
|
92
118
|
implementation does.
|
|
93
119
|
|
|
94
|
-
##
|
|
120
|
+
## 6. The checkout is read-only from here
|
|
95
121
|
|
|
96
122
|
It is a different repository with its own branch, lint, docs and changeset workflow.
|
|
97
|
-
Never edit it while working on a task in this repo
|
|
98
|
-
|
|
99
|
-
|
|
123
|
+
Never edit it while working on a task in this repo - that covers its git state too, so
|
|
124
|
+
no `checkout`, `pull`, `stash` or `reset` without the user asking for it. Never copy its
|
|
125
|
+
internals into consumer code either - a private helper is not a
|
|
126
|
+
supported API and disappears without a major version (the same goes for anything under
|
|
127
|
+
a `subtle` namespace).
|
|
100
128
|
|
|
101
129
|
When the fix belongs in the SDK, say so and describe it precisely: file, symbol, and
|
|
102
130
|
the behaviour it should have. If the user wants that fix verified against this app
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sdk-update
|
|
3
|
+
description: Update the @ethlete/* packages in this repo with `et update`, and work the migration tasks it leaves behind - the codemods it runs itself, the recommendations a human must decide, and the tasks written as a prompt for you. Read whenever this repo moves to a newer @ethlete version, when a task list under .ethlete/update is present, or when the user asks you to apply an SDK migration.
|
|
4
|
+
kind: skill
|
|
5
|
+
scope: consumer
|
|
6
|
+
requires: ['@ethlete/cli']
|
|
7
|
+
vars: [docsBaseUrl, lintCommand]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Updating the @ethlete SDK
|
|
11
|
+
|
|
12
|
+
`et update` moves this repo's `@ethlete/*` dependencies to a newer version and runs the migrations
|
|
13
|
+
those versions ship. Never bump an `@ethlete/*` range by hand: the version that lands is what selects
|
|
14
|
+
the migrations, so a hand-written bump skips every one of them silently.
|
|
15
|
+
|
|
16
|
+
## 1. See what is pending
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
{%packageRunner%} et update --check
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
It prints one line per package, `installed → target`, and exits 1 while an update is pending. It
|
|
23
|
+
writes nothing. The target follows the dist tag the installed version is on: a repo on a `-next`
|
|
24
|
+
prerelease stays on `next`.
|
|
25
|
+
|
|
26
|
+
Name a package to limit the run, short or in full:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
{%packageRunner%} et update core # only @ethlete/core
|
|
30
|
+
{%packageRunner%} et update core --to 5.0.0-next.55
|
|
31
|
+
{%packageRunner%} et update --tag latest # leave the prerelease line
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 2. Run it
|
|
35
|
+
|
|
36
|
+
The working tree must be clean - the codemods rewrite files, and you need a diff you can read.
|
|
37
|
+
Commit or stash first, then:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
{%packageRunner%} et update
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
In order, it writes the new ranges into every `package.json` in the repo that declares the package -
|
|
44
|
+
an Nx library manifest included, not only the root one - runs the install, reads the migrations out of
|
|
45
|
+
the freshly installed packages, runs every codemod, regenerates the agent rules and skills with
|
|
46
|
+
`ethlete-agents sync` when `@ethlete/agent-rules` moved, and writes what is left to `.ethlete/update`.
|
|
47
|
+
|
|
48
|
+
An older `@ethlete/cli` skips the sync. If the run moved `@ethlete/agent-rules` and printed no
|
|
49
|
+
`ethlete-agents sync` line, run `{%packageRunner%} ethlete-agents sync` yourself before the first task: the
|
|
50
|
+
tasks assume the guidance of the new version.
|
|
51
|
+
|
|
52
|
+
If the install or a codemod fails, the run stops and leaves `.ethlete/update/pending.json` behind.
|
|
53
|
+
Fix the cause, then continue - do not start over, or the migrations of the versions already installed
|
|
54
|
+
are skipped:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
{%packageRunner%} et update --continue
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## 3. Work the task list
|
|
61
|
+
|
|
62
|
+
Two files describe what is left. Read the JSON one when you work through the list yourself:
|
|
63
|
+
|
|
64
|
+
| File | What it holds |
|
|
65
|
+
| --------------------------------- | --------------------------------------------------------------------- |
|
|
66
|
+
| `.ethlete/update/tasks.md` | The report for a human: what moved, what applied, what is left |
|
|
67
|
+
| `.ethlete/update/tasks.json` | The same tasks as data: `kind`, `instructionsFile`, `docsUrl` |
|
|
68
|
+
| `.ethlete/update/<pkg>-<name>.md` | One task in full: what moved, plus the instructions the package ships |
|
|
69
|
+
|
|
70
|
+
Every task carries a `kind`, and the kind decides who acts:
|
|
71
|
+
|
|
72
|
+
- **`assisted`** - written for you. The task file states one bounded change to apply across this repo.
|
|
73
|
+
Read the whole file before the first edit, then work it until its `Done when` list holds. These are
|
|
74
|
+
the changes no codemod can make, so expect a decision per call site rather than one pattern. What the
|
|
75
|
+
file leaves for later stays for later: report it, do not do it. A view you cannot open in the browser
|
|
76
|
+
(a login fails, no API) goes into your report as unchecked; it does not block the task.
|
|
77
|
+
- **`manual`** - a recommendation for the developer. It needs a product or design decision, or a
|
|
78
|
+
command with answers only they have. Do not guess the answer. Report the task and what it needs.
|
|
79
|
+
- **`unsupported`** - a codemod that could not run here, because this repo has no Nx. The task carries
|
|
80
|
+
the exact command. Ask before running it: it rewrites files.
|
|
81
|
+
|
|
82
|
+
## 4. Finish
|
|
83
|
+
|
|
84
|
+
1. Run the type check and `{%lintCommand%}` for every project you changed.
|
|
85
|
+
2. Run the tests that cover what you touched.
|
|
86
|
+
3. Delete the task files you finished under `.ethlete/update`, and leave the ones you could not decide.
|
|
87
|
+
4. Tell the user, per task: what you changed, and what still needs their decision.
|
|
88
|
+
|
|
89
|
+
## Rules
|
|
90
|
+
|
|
91
|
+
- **Never invent a migration.** Only the tasks in `.ethlete/update` and the guides they link are real.
|
|
92
|
+
A rewrite you reasoned out from a version number is a guess.
|
|
93
|
+
- **Never edit the generated report to make it look done.** Deleting a finished task file is right;
|
|
94
|
+
deleting an entry you did not work is not.
|
|
95
|
+
- **One task at a time.** Each has its own diff, so a failure stays readable.
|
|
96
|
+
- The version notes and every guide a task links live at {%docsBaseUrl%}.
|
|
@@ -12,9 +12,10 @@ vars: [themeStylesheet]
|
|
|
12
12
|
|
|
13
13
|
Two separate rules, often confused:
|
|
14
14
|
|
|
15
|
-
1. **
|
|
16
|
-
component, wrapped in `@layer components`, using
|
|
17
|
-
{%skill:theming%}.
|
|
15
|
+
1. **A library component's source is plain CSS, never Tailwind.** The `.css` next
|
|
16
|
+
to a component a library ships, wrapped in `@layer components`, using
|
|
17
|
+
surface/color tokens - see {%skill:theming%}. Application components are the
|
|
18
|
+
opposite: they use Tailwind utilities in their templates.
|
|
18
19
|
2. **Story files may use Tailwind** (`*.stories.ts`, anything under a `stories/`
|
|
19
20
|
folder) for demo layout only - the frame around the component, not the
|
|
20
21
|
component's own look.
|
|
@@ -33,11 +34,11 @@ error and no warning, the element just renders unstyled. A theme that does this:
|
|
|
33
34
|
leaves `bg-blue-500`, `text-gray-700` and `text-sm` as dead strings, even though
|
|
34
35
|
they are "real" Tailwind classes.
|
|
35
36
|
|
|
36
|
-
**Read the theme before reaching for an unfamiliar utility.** This project's
|
|
37
|
-
`{%themeStylesheet%}
|
|
37
|
+
**Read the theme before reaching for an unfamiliar utility.** This project's lives in
|
|
38
|
+
`{%themeStylesheet%}` (a file, or a folder of theme files):
|
|
38
39
|
|
|
39
40
|
```bash
|
|
40
|
-
grep -
|
|
41
|
+
grep -rnE -- '--(color|text|font|spacing)-' {%themeStylesheet%}
|
|
41
42
|
```
|
|
42
43
|
|
|
43
44
|
If `@theme` doesn't define the token, the class doesn't exist. Check rather than
|
|
@@ -62,7 +63,7 @@ paints must come from those tokens - the same rule as component CSS
|
|
|
62
63
|
|
|
63
64
|
- A tinted panel: put `etAutoSurface` on it (next elevation up) and read the token:
|
|
64
65
|
`style="background: var(--et-surface-background-solid)"`.
|
|
65
|
-
- An accent: scope it with `[etProvideColor]="
|
|
66
|
+
- An accent: scope it with `[etProvideColor]="storyAccentTheme"` and read
|
|
66
67
|
`--et-theme-color-primary-solid` / `--et-theme-color-ink-solid`. Theme names are
|
|
67
68
|
whatever **your app** registers - fine to name in a story, never in library code.
|
|
68
69
|
- Better still: don't hand-paint. Compose the component that already does it
|
|
@@ -80,4 +81,5 @@ paints must come from those tokens - the same rule as component CSS
|
|
|
80
81
|
- Text sizes from your theme's scale, not Tailwind's default `text-sm`/`text-xs`.
|
|
81
82
|
- No `dark:` variants.
|
|
82
83
|
- Width/height that matters is px, not the rem container scale.
|
|
83
|
-
- Then verify it actually renders
|
|
84
|
+
- Then verify it actually renders with the repository's installed Storybook verification
|
|
85
|
+
workflow, or inspect the story directly when no such guide was emitted.
|
|
@@ -14,18 +14,23 @@ Don't hand-check or hand-fix those - **run lint with `--fix` first**; many rules
|
|
|
14
14
|
ship auto-fixers, so most violations are corrected for you:
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
{%lintFixCommand%} # auto-fixes first (case, ordering, $ suffix
|
|
17
|
+
{%lintFixCommand%} # auto-fixes first (case, ordering, metadata, …); rename to the $ suffix by hand
|
|
18
18
|
{%lintCommand%} # then re-run to see what needs a manual fix
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
file-structure example: {%resource:STYLEGUIDE.md%}.
|
|
21
|
+
Load only the reference needed for the current question:
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
- {%resource:lint-rule-lookup.md%} when a lint fix or diagnostic needs explanation.
|
|
24
|
+
- {%resource:file-structure.md%} when placing routes, views, reusable components,
|
|
25
|
+
providers, or local utilities.
|
|
26
|
+
- {%resource:assets.md%} when deciding where build, serve, shared, or Storybook assets
|
|
27
|
+
belong.
|
|
28
|
+
- {%resource:storybook-structure.md%} when placing a story file or its private helpers.
|
|
29
|
+
- {%resource:changesets.md%} when deciding whether an application or library change
|
|
30
|
+
needs a release note and no repository-specific release skill exists.
|
|
25
31
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
lifecycle.
|
|
32
|
+
For reactive state or Angular building blocks, load the corresponding focused repository
|
|
33
|
+
guide if one was emitted. This entry point does not duplicate those guides.
|
|
29
34
|
|
|
30
35
|
The rest of this guide is the cross-cutting judgment that doesn't belong to one
|
|
31
36
|
of those.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Assets
|
|
2
|
+
|
|
3
|
+
Read this file when deciding whether an asset belongs to production, local serve, a
|
|
4
|
+
specific app, Storybook, or shared output.
|
|
5
|
+
|
|
6
|
+
Keep assets in the workspace assets library and separate them by consumer and purpose:
|
|
7
|
+
|
|
8
|
+
```plaintext
|
|
9
|
+
assets/
|
|
10
|
+
├── my-app/
|
|
11
|
+
│ ├── build/
|
|
12
|
+
│ ├── serve/
|
|
13
|
+
│ └── storybook/
|
|
14
|
+
├── other-app/
|
|
15
|
+
│ ├── build/
|
|
16
|
+
│ ├── serve/
|
|
17
|
+
│ └── storybook/
|
|
18
|
+
└── shared/
|
|
19
|
+
├── build/
|
|
20
|
+
├── serve/
|
|
21
|
+
└── storybook/
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- `build/` contains production assets.
|
|
25
|
+
- `serve/` contains development-only placeholders or fixtures.
|
|
26
|
+
- `storybook/` contains assets used only by stories.
|
|
27
|
+
- `shared/` contains assets genuinely used by more than one app.
|
|
28
|
+
- Preserve the intended public URL through the project's `assets` configuration. Do not
|
|
29
|
+
expose a `build` directory segment in the final URL.
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"assets": [
|
|
34
|
+
{
|
|
35
|
+
"input": "libs/assets/src/my-app/build",
|
|
36
|
+
"glob": "**/*",
|
|
37
|
+
"output": "assets"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"input": "libs/assets/src/my-app/serve",
|
|
41
|
+
"glob": "**/*",
|
|
42
|
+
"output": "assets/serve"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"input": "libs/assets/src/shared/build",
|
|
46
|
+
"glob": "**/*",
|
|
47
|
+
"output": "assets/shared"
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Add only build assets to a production configuration. Add serve and Storybook assets
|
|
54
|
+
only to the configurations that need them.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Changesets
|
|
2
|
+
|
|
3
|
+
Read this fallback only when the repository has no more specific release workflow.
|
|
4
|
+
|
|
5
|
+
- Add a changeset for a consumer-visible change to a published package.
|
|
6
|
+
- Do not add one for formatting, comments, tests, or an internal refactor with no
|
|
7
|
+
consumer-visible effect.
|
|
8
|
+
- Use `patch` for fixes, `minor` for backward-compatible API additions, and `major` for
|
|
9
|
+
breaking API or behavior changes.
|
|
10
|
+
- Keep one logical release note focused. Split unrelated changes.
|
|
11
|
+
- Write the note for the package consumer: state what they now get, not how the change
|
|
12
|
+
was implemented.
|
|
13
|
+
- Keep the note to one sentence, two at most, under 40 words.
|
|
14
|
+
- Do not run an interactive changeset command in a non-interactive agent environment;
|
|
15
|
+
write the repository's changeset file format directly.
|
|
16
|
+
|
|
17
|
+
When a repository supplies its own release skill or policy, that local guidance wins.
|