@ethlete/agent-rules 0.1.0-next.3 → 0.1.0-next.30
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/AGENTS.md +28 -0
- package/CHANGELOG.md +463 -0
- package/CLAUDE.md +1 -0
- package/README.md +362 -29
- package/THIRD-PARTY-LICENSES.md +35 -0
- package/content/defaults.json +1 -1
- package/content/git-hooks/post-checkout.sh +10 -0
- package/content/git-hooks/pre-push.sh +5 -0
- package/content/hooks/context-warning.py +871 -110
- package/content/hooks/subagent-model-policy.py +194 -0
- package/content/mods/.claude-plugin/marketplace.json +11 -0
- package/content/mods/plugins/e2e-progress/.claude-plugin/plugin.json +6 -0
- package/content/mods/plugins/e2e-progress/hooks/hooks.json +1 -0
- package/content/mods/plugins/e2e-progress/hooks/register.tsx +442 -0
- package/content/mods/plugins/e2e-progress/tsconfig.json +3 -0
- package/content/mods/plugins/e2e-progress/types/index.d.ts +23 -0
- package/content/output-styles/ste-clarity.md +131 -0
- package/content/rules/agent-sessions-wake-up.md +11 -0
- package/content/rules/app-styling.md +66 -0
- package/content/rules/comments.md +4 -1
- package/content/rules/lint-and-format.md +7 -5
- package/content/rules/nx-layout.md +50 -0
- package/content/rules/reactive-state.md +1 -1
- package/content/rules/styling.md +9 -7
- package/content/rules/subagent-models.md +39 -0
- package/content/skills/agent-sessions/SKILL.md +81 -0
- package/content/skills/agent-sessions/agent-sessions.mjs +492 -0
- package/content/skills/angular-patterns/SKILL.md +30 -7
- package/content/skills/api-source/SKILL.md +156 -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 +657 -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/e2e-triage/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 +11 -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 +51 -0
- package/content/skills/handoff/SKILL.md +125 -5
- package/content/skills/query/SKILL.md +165 -64
- package/content/skills/rxjs-signals/SKILL.md +33 -4
- package/content/skills/sdk-docs/SKILL.md +50 -14
- package/content/skills/sdk-local-build/SKILL.md +26 -8
- package/content/skills/sdk-local-build/sdk-local-baseline.mjs +64 -0
- package/content/skills/sdk-source/SKILL.md +37 -34
- package/content/skills/sdk-update/SKILL.md +103 -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 +50 -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 +19 -3
- package/src/index.js +85 -30
- 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 +41 -5
- package/src/lib/config.js +117 -10
- 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 +23 -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 +165 -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 +165 -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 +140 -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 +116 -0
- package/src/lib/gitlab.js.map +1 -0
- package/src/lib/index.d.ts +2 -0
- package/src/lib/index.js +26 -11
- package/src/lib/index.js.map +1 -1
- package/src/lib/migrate.js +6 -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 +4 -0
- package/src/lib/package-runner.js +86 -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 +164 -40
- package/src/lib/plan.js.map +1 -1
- package/src/lib/prompt.d.ts +8 -0
- package/src/lib/prompt.js +35 -0
- package/src/lib/prompt.js.map +1 -0
- package/src/lib/render.d.ts +25 -2
- package/src/lib/render.js +43 -10
- package/src/lib/render.js.map +1 -1
- package/src/lib/sessions-command.d.ts +4 -0
- package/src/lib/sessions-command.js +16 -0
- package/src/lib/sessions-command.js.map +1 -0
- package/src/lib/sync.d.ts +0 -1
- package/src/lib/sync.js +30 -17
- 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 +3 -23
- package/src/lib/targets/claude-hooks.js +22 -86
- package/src/lib/targets/claude-hooks.js.map +1 -1
- package/src/lib/targets/claude-mods.d.ts +20 -0
- package/src/lib/targets/claude-mods.js +47 -0
- package/src/lib/targets/claude-mods.js.map +1 -0
- package/src/lib/targets/claude.js +2 -3
- 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 +35 -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 +4 -4
- package/src/lib/targets/copilot.js.map +1 -1
- package/src/lib/targets/cursor.js +3 -3
- package/src/lib/targets/cursor.js.map +1 -1
- package/src/lib/targets/git-hooks.d.ts +25 -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 +60 -0
- package/src/lib/targets/hooks-shared.js +130 -0
- package/src/lib/targets/hooks-shared.js.map +1 -0
- package/src/lib/targets/mcp.d.ts +16 -0
- package/src/lib/targets/mcp.js +68 -0
- package/src/lib/targets/mcp.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 +1063 -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 +279 -0
- package/src/lib/timetrack.js.map +1 -0
- package/content/skills/styleguide/STYLEGUIDE.md +0 -520
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ste-clarity
|
|
3
|
+
description: Write all prose in ASD-STE100 Simplified Technical English — approved words, simple verb forms, active voice, one idea per sentence.
|
|
4
|
+
keep-coding-instructions: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# ASD-STE100 output style
|
|
8
|
+
|
|
9
|
+
Write every sentence you show the user in Simplified Technical English, as specified
|
|
10
|
+
by ASD-STE100. Clarity comes first. Never sacrifice technical accuracy for brevity.
|
|
11
|
+
|
|
12
|
+
## Scope
|
|
13
|
+
|
|
14
|
+
Apply STE to your own prose: answers, explanations, plans, summaries, commit
|
|
15
|
+
messages, and pull request text.
|
|
16
|
+
|
|
17
|
+
Do not apply STE to:
|
|
18
|
+
|
|
19
|
+
- Code, identifiers, file paths, and command names.
|
|
20
|
+
- Quoted material: error messages, log lines, command output, and text from files.
|
|
21
|
+
Copy these exactly. Never rewrite a quote to make it simpler.
|
|
22
|
+
- Text the user asks you to write in a different style.
|
|
23
|
+
|
|
24
|
+
Markdown is still available. Use code blocks, and use `file.ts:42` references.
|
|
25
|
+
|
|
26
|
+
## Words
|
|
27
|
+
|
|
28
|
+
1. Use the most common, shortest word that has one clear meaning.
|
|
29
|
+
2. Use one word for one meaning. Do not use synonyms for the same thing. If you
|
|
30
|
+
write "flag" for a variable, do not later call it a "switch" or an "option".
|
|
31
|
+
3. Use one meaning for one word. Do not use "close" for both a state and an action
|
|
32
|
+
if this can confuse the reader.
|
|
33
|
+
4. Technical names are permitted. Use the exact name from the code or the domain.
|
|
34
|
+
5. Do not use slang, idioms, or figures of speech. "The build blew up" is wrong.
|
|
35
|
+
"The build failed" is correct.
|
|
36
|
+
6. Do not use "etc." Complete the list, or write "for example" and give two items.
|
|
37
|
+
7. Do not use a noun as a verb. Write "make a request", not "request it", when
|
|
38
|
+
"request" is a name in the code.
|
|
39
|
+
|
|
40
|
+
Prefer the word on the right:
|
|
41
|
+
|
|
42
|
+
| Not approved | Use |
|
|
43
|
+
| ------------------------ | ----------------- |
|
|
44
|
+
| utilize, employ | use |
|
|
45
|
+
| initiate, commence | start |
|
|
46
|
+
| terminate | stop, end |
|
|
47
|
+
| perform, execute | do, run |
|
|
48
|
+
| modify | change |
|
|
49
|
+
| indicate | show |
|
|
50
|
+
| ascertain, determine | find, find out |
|
|
51
|
+
| assist, aid | help |
|
|
52
|
+
| attempt | try |
|
|
53
|
+
| require | need |
|
|
54
|
+
| sufficient | enough |
|
|
55
|
+
| additional | more |
|
|
56
|
+
| numerous, multiple | many |
|
|
57
|
+
| approximately | about |
|
|
58
|
+
| currently, presently | now |
|
|
59
|
+
| prior to | before |
|
|
60
|
+
| subsequent to, following | after |
|
|
61
|
+
| in order to | to |
|
|
62
|
+
| due to the fact that | because |
|
|
63
|
+
| via | with, by, through |
|
|
64
|
+
| such as | for example |
|
|
65
|
+
| in the event that | if |
|
|
66
|
+
| at this point in time | now |
|
|
67
|
+
|
|
68
|
+
This table is a guide, not the full ASD-STE100 Dictionary. The Dictionary holds about
|
|
69
|
+
900 approved words, each with one approved part of speech and one approved meaning.
|
|
70
|
+
When you do not know if a word is approved, choose the shortest common word that has
|
|
71
|
+
one clear meaning.
|
|
72
|
+
|
|
73
|
+
## Verbs
|
|
74
|
+
|
|
75
|
+
1. Use only these verb forms: the infinitive, the imperative, the simple present, the
|
|
76
|
+
simple past, the simple future, and the past participle as an adjective.
|
|
77
|
+
2. Do not use complex tenses. Write "I changed the config", not "I have changed the
|
|
78
|
+
config".
|
|
79
|
+
3. Do not use "-ing" forms, unless the form is part of a technical name, for example
|
|
80
|
+
"a logging module".
|
|
81
|
+
4. Use the active voice. Write "the parser drops the field", not "the field is dropped
|
|
82
|
+
by the parser". Use the passive voice only when the actor is unknown or does not
|
|
83
|
+
matter.
|
|
84
|
+
5. Do not leave out a verb to make a sentence shorter.
|
|
85
|
+
|
|
86
|
+
## Noun phrases
|
|
87
|
+
|
|
88
|
+
1. Do not build a cluster of more than three nouns. Break up "user account balance
|
|
89
|
+
sync failure" as "a failure in the sync of the user account balance".
|
|
90
|
+
2. Add articles ("a", "the") where they help the reader.
|
|
91
|
+
|
|
92
|
+
## Sentences
|
|
93
|
+
|
|
94
|
+
1. Instructions: 20 words maximum.
|
|
95
|
+
2. Descriptions: 25 words maximum.
|
|
96
|
+
3. One idea per sentence. One instruction per sentence.
|
|
97
|
+
4. A paragraph holds 6 sentences maximum, and covers one topic.
|
|
98
|
+
5. Put a condition at the start of the sentence, before the instruction. Write "If the
|
|
99
|
+
sync fails, restart the server".
|
|
100
|
+
6. Use connecting words such as "however", "therefore", and "then" to show the link
|
|
101
|
+
between sentences.
|
|
102
|
+
7. Use a vertical list when the content has more than three parallel parts. Do not use
|
|
103
|
+
a list to give structure to a single idea.
|
|
104
|
+
|
|
105
|
+
## Procedures
|
|
106
|
+
|
|
107
|
+
1. Use the imperative for each step. Write "Open the file", not "You should open the
|
|
108
|
+
file" or "We can open the file".
|
|
109
|
+
2. Number the steps in the order the user must do them.
|
|
110
|
+
3. Give the result after the action, if the result is not obvious.
|
|
111
|
+
|
|
112
|
+
## Warnings
|
|
113
|
+
|
|
114
|
+
1. Put a warning or a caution before the step it applies to, never after.
|
|
115
|
+
2. Start the warning with a clear command. Write "Do not run this on the production
|
|
116
|
+
database. The command deletes all rows."
|
|
117
|
+
3. State the consequence in a separate, simple sentence.
|
|
118
|
+
|
|
119
|
+
## Punctuation
|
|
120
|
+
|
|
121
|
+
1. Do not use a slash to mean "and" or "or". Write "the date or the payee".
|
|
122
|
+
2. Do not use parentheses for information the reader needs. Put it in its own sentence.
|
|
123
|
+
3. Do not use a dash to join two thoughts. Use two sentences.
|
|
124
|
+
4. Use a hyphen only to make a compound word clear.
|
|
125
|
+
|
|
126
|
+
## When STE and accuracy conflict
|
|
127
|
+
|
|
128
|
+
Accuracy wins. If a simple word would hide a real distinction, use the exact term and
|
|
129
|
+
define it once in a short sentence. Never simplify a claim about what the code does.
|
|
130
|
+
Keep the difference between what you verified and what you assume: write "I ran the
|
|
131
|
+
tests and they passed" or "I did not run the tests", not a sentence that blurs the two.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-sessions-wake-up
|
|
3
|
+
description: A prompt that says "New mailbox message for <name>" means run the inbox command in it and act on the result; read the agent-sessions skill before you edit a file another agent may edit.
|
|
4
|
+
kind: rule
|
|
5
|
+
scope: both
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Agent sessions
|
|
9
|
+
|
|
10
|
+
If a prompt says `New mailbox message for <name>`, run the `inbox` command in that prompt and act on
|
|
11
|
+
the messages. Before you edit a file that another agent may edit, read {% skill:agent-sessions %}.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: app-styling
|
|
3
|
+
description: App components are styled with Tailwind utilities in their templates; app CSS stays out of @layer components; the SDK needs a 10px rem root; hardcoded colours are never primary values.
|
|
4
|
+
kind: rule
|
|
5
|
+
scope: consumer
|
|
6
|
+
requires: ['@ethlete/core']
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Styling
|
|
10
|
+
|
|
11
|
+
Every component in this workspace (views, pages, shells, shared UI in `libs/`) is laid out
|
|
12
|
+
and styled with **Tailwind utility classes in its template**, including the colour utilities
|
|
13
|
+
the app's theme provides: the generated SDK theme utilities (`bg-et-surface-bg`,
|
|
14
|
+
`border-et-surface-border`, `text-et-<theme>`) where the app generates them, or the palette its
|
|
15
|
+
Tailwind config defines. Do not
|
|
16
|
+
invent a BEM class system, and do not write a `.css` file for layout, spacing or
|
|
17
|
+
typography a utility expresses. Every app component sets `encapsulation: ViewEncapsulation.None`,
|
|
18
|
+
as the `require-view-encapsulation-none` lint rule requires. Its CSS is then global, so give the
|
|
19
|
+
component a host class (`host: { class: 'app-player-card' }`) and scope every selector under it,
|
|
20
|
+
the way SDK components scope theirs under their `et-` classes. Never write a bare element or
|
|
21
|
+
unprefixed class selector in a component stylesheet.
|
|
22
|
+
|
|
23
|
+
In an existing repo, convert a component's styles whenever you change any of its files (class,
|
|
24
|
+
template, template-bound logic or CSS), not only its styles; if the conversion is large, ask the
|
|
25
|
+
user first. A legacy component that relies on emulated encapsulation keeps it until its CSS is
|
|
26
|
+
scoped under a host class: without that scope, `ViewEncapsulation.None` leaks its CSS into every
|
|
27
|
+
view.
|
|
28
|
+
|
|
29
|
+
If the repo as a whole breaks this section (global classes in `styles.css`, hardcoded colours),
|
|
30
|
+
tell the user once at first contact, with the size of the conversion (files, classes, hardcoded
|
|
31
|
+
colours), and record it as owed work in the plan or handoff. Never skip it silently. This holds
|
|
32
|
+
for a deviation from any rule here: report it once and record it.
|
|
33
|
+
|
|
34
|
+
Write CSS only for what utilities cannot express. With Tailwind 4, keep that CSS **unlayered**
|
|
35
|
+
or in `@layer utilities` — never in `@layer components`, and that includes the global
|
|
36
|
+
stylesheet. SDK component styles are injected into `@layer components` at runtime, after your
|
|
37
|
+
stylesheet, so an app rule in the same layer ties on layer and loses on source order. With
|
|
38
|
+
Tailwind 3, `@layer` is a Tailwind directive that emits unlayered CSS, so app CSS already beats
|
|
39
|
+
the SDK's layered styles.
|
|
40
|
+
|
|
41
|
+
To change an SDK component's look, set its `--et-*` tokens first (documented per
|
|
42
|
+
component), then use a utility class or unlayered CSS on the element — see "Overriding
|
|
43
|
+
component styles" in the docs site's components overview.
|
|
44
|
+
|
|
45
|
+
The SDK sizes everything in `rem` on a **10px root**: the app's global stylesheet must set
|
|
46
|
+
`html { font-size: 62.5%; }`. Without it every SDK control renders 1.6× too large. With it,
|
|
47
|
+
`1rem` is `10px`, so the app's own `rem` values stay easy to read.
|
|
48
|
+
|
|
49
|
+
The 10px root also shrinks every rem-based Tailwind scale to 62.5% of its nominal size (1.6×
|
|
50
|
+
smaller): `p-4` is 10px instead of 16px, and `max-w-3xl` is 480px instead of 768px. Keep the
|
|
51
|
+
spacing scale on its 4px step: with Tailwind 4, set `--spacing: 0.4rem` in the app's `@theme`,
|
|
52
|
+
as the SDK's own Storybook does; with Tailwind 3, redefine `theme.spacing` in
|
|
53
|
+
`tailwind.config`. In an app that already uses utilities without it, the change rescales every
|
|
54
|
+
view: tell the user rather than make it. Redefine any other rem scale the app uses (text,
|
|
55
|
+
container, radius) the same way, or use px where a size matters. Breakpoints are not affected:
|
|
56
|
+
a media query's `rem` ignores the root font size.
|
|
57
|
+
|
|
58
|
+
**Never use a hardcoded colour as the primary value.** Backgrounds, text, borders and
|
|
59
|
+
interaction states resolve from the app's theme: the SDK surface and colour tokens
|
|
60
|
+
(`--et-surface-*-solid`, `--et-theme-color-*`) and their generated utilities, or the palette
|
|
61
|
+
the app's Tailwind config defines. Never write an arbitrary colour value such as
|
|
62
|
+
`bg-[#1a1a1a]` in a template. A static fallback inside `var(--token, <fallback>)` is
|
|
63
|
+
permitted, but not required.
|
|
64
|
+
|
|
65
|
+
Theme **names** (`brand`, `danger`, `dark-elevated`, …) are registered by this app; the SDK
|
|
66
|
+
ships none. Semantic colours resolve by theme `type` (e.g. `injectSemanticColorTheme('error')`).
|
|
@@ -20,6 +20,8 @@ smaller function, or a type; fix that instead of narrating it.
|
|
|
20
20
|
limitation) and linking it where a link exists, so the next reader can tell when it may go.
|
|
21
21
|
4. **Public API JSDoc** — what it does and how to call it, on something a lib actually
|
|
22
22
|
exports. One or two sentences. Not internals, not history, not why it is shaped that way.
|
|
23
|
+
In an application nothing is public API unless it lives in a shared lib other projects
|
|
24
|
+
import, so this case rarely applies to app code.
|
|
23
25
|
|
|
24
26
|
Nothing else qualifies. Not "this is subtle", not "worth noting", not a heading over a group
|
|
25
27
|
of members, not a summary of the function underneath it.
|
|
@@ -43,7 +45,8 @@ years.
|
|
|
43
45
|
annotation, a factory instead of a literal, a helper moved into its own file. The type, the
|
|
44
46
|
annotation and the import already say what happens.
|
|
45
47
|
- **Migration narration** — "moved here from X", "used to be a tuple", "so Y no longer pulls
|
|
46
|
-
Z", "renamed for clarity". Git
|
|
48
|
+
Z", "renamed for clarity", "see ADR-0012". Git and the ADR index know; the next reader does
|
|
49
|
+
not care.
|
|
47
50
|
- **The same explanation at every call site.** Explain a pattern once where it is defined (the
|
|
48
51
|
helper's JSDoc, the lint rule's message, the guide) and let every use site stay silent.
|
|
49
52
|
- **Commented-out code.**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: lint-and-format
|
|
3
|
-
description: Run lint with --fix before fixing anything by hand, and format every edited file.
|
|
3
|
+
description: Run lint with --fix before fixing anything by hand, and format every edited source file Prettier supports.
|
|
4
4
|
kind: rule
|
|
5
5
|
scope: both
|
|
6
6
|
vars: [lintCommand, lintFixCommand, formatCommand]
|
|
@@ -12,14 +12,16 @@ Run lint with `--fix` — most styleguide rules in `@ethlete/eslint-plugin` ship
|
|
|
12
12
|
so let them do the work before correcting anything by hand:
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
{%lintFixCommand%} # auto-fixes first (case, ordering, $ suffix
|
|
15
|
+
{%lintFixCommand%} # auto-fixes first (case, ordering, metadata, …); rename to the $ suffix by hand
|
|
16
16
|
{%lintCommand%} # then re-run to see what needs a manual fix
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
For
|
|
20
|
-
|
|
19
|
+
For judgment calls lint cannot enforce, load the repository's focused guidance for the
|
|
20
|
+
code you are changing.
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
Format every edited Prettier-supported source file before wrapping up, in one call over all of
|
|
23
|
+
them, not one call per file. Do not send binary,
|
|
24
|
+
generated, or unsupported files to this command:
|
|
23
25
|
|
|
24
26
|
```bash
|
|
25
27
|
{%formatCommand%}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nx-layout
|
|
3
|
+
description: Nx workspace layout - thin apps, feature code in libs grouped by kind, path-mirroring aliases, scope tags.
|
|
4
|
+
kind: rule
|
|
5
|
+
scope: consumer
|
|
6
|
+
requires: ['nx']
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Nx workspace layout
|
|
10
|
+
|
|
11
|
+
Apps are thin shells. All feature code lives in libs, grouped by kind, not by Nx type:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
apps/<app>/src/app/ app.component.ts, app.config.ts, app.routes.ts only
|
|
15
|
+
libs/
|
|
16
|
+
domain/<app>/ one lib per app
|
|
17
|
+
src/lib/<feature>/ views, components, services, <feature>.routes.ts
|
|
18
|
+
src/lib/shared/ code shared by the app's features (optional)
|
|
19
|
+
queries/ query clients and creators, one folder per backend
|
|
20
|
+
types/ API models and shared types
|
|
21
|
+
uikit/ app-agnostic presentational components
|
|
22
|
+
theme/ surface and colour themes
|
|
23
|
+
env/ environment.ts, environment.production.ts
|
|
24
|
+
assets/ fonts, icons, images
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
- Each feature folder exports its own `<FEATURE>_ROUTES`, re-exported from the lib's
|
|
28
|
+
`src/index.ts`. `app.routes.ts` only lazy-loads them:
|
|
29
|
+
`loadChildren: () => import('@acme/domain/admin').then((m) => m.USERS_ROUTES)`.
|
|
30
|
+
- Split a feature into its own lib (`libs/domain/<app>/<feature>`) only for a concrete
|
|
31
|
+
reason, such as size or build time, and name that reason to the user.
|
|
32
|
+
Never put features, queries, shared UI or theme in the app project.
|
|
33
|
+
- Do not add Nx `feature/ui/data-access/util` folders or `type:*` tags.
|
|
34
|
+
- Every lib has `src/index.ts` and explicit `build` (`@nx/angular:ng-packagr-lite`), `lint`
|
|
35
|
+
and `test` targets in `project.json`. Keep `plugins: []` in `nx.json`.
|
|
36
|
+
- Alias = path with slashes: `@acme/domain/admin`, `@acme/queries`, `@acme/types`,
|
|
37
|
+
`@acme/uikit`, `@acme/env`. Project name = path with dashes (`domain-admin`).
|
|
38
|
+
Component `prefix` = the repo abbreviation.
|
|
39
|
+
- Tag every project with one `scope:*`: `scope:<app>` for an app and its domain libs,
|
|
40
|
+
`scope:core` for env and types, plus `scope:queries`, `scope:uikit`, `scope:theme`.
|
|
41
|
+
`@nx/enforce-module-boundaries` with `enforceBuildableLibDependency: true` lets
|
|
42
|
+
`scope:<app>` depend on itself and the shared scopes, never on another app.
|
|
43
|
+
- A backend in the same workspace is an app in `apps/` with its libs in
|
|
44
|
+
`libs/domain/<name>-api`. Ban `@angular/*` in backend scopes and `@nestjs/*` in frontend
|
|
45
|
+
scopes with `bannedExternalImports`.
|
|
46
|
+
- Environment config lives only in `libs/env`, never hardcoded in a query client.
|
|
47
|
+
|
|
48
|
+
This is the layout for new workspaces and new code. Do not restructure the folders, projects
|
|
49
|
+
and tags of an existing workspace that deviates from it unless the user asks. This covers the
|
|
50
|
+
workspace layout only: every other rule still applies to the code you touch.
|
|
@@ -12,4 +12,4 @@ scope: both
|
|
|
12
12
|
- **Bridge, don't copy.** Cross the boundary with `toSignal()` / `toObservable()`, never by
|
|
13
13
|
`.subscribe()`-ing and assigning the value somewhere.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
For subscriptions and effects, load the repository's focused reactive-state guidance.
|
package/content/rules/styling.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: styling
|
|
3
|
-
description: Component CSS is plain CSS in @layer components, and
|
|
3
|
+
description: Component CSS is plain CSS in @layer components, and hardcoded colours are never primary values.
|
|
4
4
|
kind: rule
|
|
5
|
-
scope:
|
|
5
|
+
scope: sdk
|
|
6
6
|
requires: ['@ethlete/core']
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -26,10 +26,12 @@ utility can win.
|
|
|
26
26
|
rule, so source order decides. Leave interaction states (`:hover`, `:focus-visible`,
|
|
27
27
|
`:active`) bare so they escalate and win.
|
|
28
28
|
|
|
29
|
-
**Never
|
|
30
|
-
from the surface and colour theming tokens
|
|
31
|
-
|
|
29
|
+
**Never use a hardcoded colour as the primary value.** Backgrounds, text, borders and
|
|
30
|
+
interaction states resolve from the surface and colour theming tokens
|
|
31
|
+
(`--et-surface-*-solid`, `--et-theme-color-*`). A static fallback inside
|
|
32
|
+
`var(--token, <fallback>)` is permitted, but not required.
|
|
32
33
|
|
|
33
34
|
Theme **names** (`brand`, `danger`, `dark-elevated`, …) are registered by the application;
|
|
34
|
-
the SDK ships none. Never hardcode
|
|
35
|
-
|
|
35
|
+
the SDK ships none. Never hardcode them as an SDK-defined union or reusable API contract.
|
|
36
|
+
If an app-specific example names one, label it as belonging to that app. Semantic colours
|
|
37
|
+
resolve by theme `type` (e.g. `injectSemanticColorTheme('error')`).
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: subagent-models
|
|
3
|
+
description: A subagent's model is an explicit choice on every call - haiku for lookups and small specified jobs, sonnet for scoped work, opus for hard work, fable for judgment.
|
|
4
|
+
kind: rule
|
|
5
|
+
scope: both
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Delegating: name the subagent's model
|
|
9
|
+
|
|
10
|
+
A subagent spawned without a `model` runs on the model leading the session, so an expensive
|
|
11
|
+
model ends up doing every small job it delegates. **Set `model` on every call**, matched to the
|
|
12
|
+
task:
|
|
13
|
+
|
|
14
|
+
| Model | The work it fits |
|
|
15
|
+
| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
16
|
+
| `haiku` | Lookups and small, fully specified jobs: grep, find, read and summarize files or a CI log, run a command and report, a mechanical edit in named files. Haiku 5.5 does these well. |
|
|
17
|
+
| `sonnet` | Scoped work with a clear target: a fix in a named file, a spec, a docs page, a lint cleanup, research that needs reasoning. Sonnet 5.5 is close to opus here and costs less. |
|
|
18
|
+
| `opus` | Hard work: a bug with no known cause, a change across many files, a review of a diff, and any task sonnet did not finish. |
|
|
19
|
+
| `fable` | Judgment-heavy work: planning, design, cross-cutting review, leading other subagents. The most expensive of the four, so ask the user before picking it. |
|
|
20
|
+
|
|
21
|
+
Effort follows the prompt, not a parameter: scope the prompt to one question, name what "done"
|
|
22
|
+
means, and say "keep it brief" for a lookup. Two calls need no `model` of their own - a named
|
|
23
|
+
agent type carries the model and reasoning effort its own definition sets, and a fork always
|
|
24
|
+
inherits the parent's model.
|
|
25
|
+
|
|
26
|
+
A subagent starts cold: it loads the full start context (about 50k tokens) before its first step,
|
|
27
|
+
and measured subagents cost as much as the sessions that spawn them. Do a lookup of a few tool
|
|
28
|
+
calls yourself. Give each subagent one large slice, not several small ones.
|
|
29
|
+
|
|
30
|
+
A subagent has the same context budget as the session, measured on its own transcript, and the
|
|
31
|
+
context-warning hook tells it to hand back at the critical tier. Size each prompt to fit: one
|
|
32
|
+
slice of work, the files it needs named, and "keep your context small - no whole big files".
|
|
33
|
+
Work that will not fit goes to several subagents in sequence, a fresh one per slice; a subagent
|
|
34
|
+
that hands back early names its remaining steps, which become the next one's prompt.
|
|
35
|
+
|
|
36
|
+
A subagent does not have to be a Claude one. Delegate to a Codex agent where another model
|
|
37
|
+
family would answer better - a second opinion, a review of your own diff, a bug hunt your own
|
|
38
|
+
reading failed - and whenever the Claude usage limit is close, because a Codex run does not draw
|
|
39
|
+
on it. Read {%skill:codex-subagent%} first.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-sessions
|
|
3
|
+
description: Run agents in tmux sessions of one checkout, message them, wake idle ones, restart a session with a prompt, and claim paths so two agents do not overwrite each other. Read before you edit a shared file while another agent may be active, and when the user says "mailbox", "coordinate with the other agent", "claim a file", "hand off to the other agent", or "restart the session".
|
|
4
|
+
kind: skill
|
|
5
|
+
scope: both
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Agent sessions
|
|
9
|
+
|
|
10
|
+
One script, {%resource:agent-sessions.mjs%}, does three jobs for the agents of one checkout:
|
|
11
|
+
|
|
12
|
+
- **Sessions.** It runs each agent in a `tmux` session, and it can clear a session and start it with a prompt.
|
|
13
|
+
- **Messages.** Agents send each other messages through an append-only JSON-lines file, the mailbox. A dispatcher wakes an idle agent.
|
|
14
|
+
- **Claims.** An agent announces the paths it edits, so two agents do not overwrite each other.
|
|
15
|
+
|
|
16
|
+
Below, `<skill-dir>` is the directory this file sits in, and `<name>` is your own sender name. Where
|
|
17
|
+
the `ethlete-agents` package is a dependency, `npx ethlete-agents sessions <command>` runs the same
|
|
18
|
+
script, so you do not need `<skill-dir>`. The older name `npx ethlete-agents mailbox` works too.
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
node <skill-dir>/agent-sessions.mjs run <name> <command...>
|
|
22
|
+
node <skill-dir>/agent-sessions.mjs up <name>[=<command>]...
|
|
23
|
+
node <skill-dir>/agent-sessions.mjs restart <name> [--after <seconds>] <prompt...>
|
|
24
|
+
node <skill-dir>/agent-sessions.mjs down [<name>...]
|
|
25
|
+
node <skill-dir>/agent-sessions.mjs shell-install [<agent>...] [--file <path>] [--remove] [--dry-run]
|
|
26
|
+
node <skill-dir>/agent-sessions.mjs shell-init [<agent>...]
|
|
27
|
+
node <skill-dir>/agent-sessions.mjs send <name> [--to <agent>] '<message>'
|
|
28
|
+
node <skill-dir>/agent-sessions.mjs inbox <name> [--wait <seconds>]
|
|
29
|
+
node <skill-dir>/agent-sessions.mjs read [--last <n>] [--all]
|
|
30
|
+
node <skill-dir>/agent-sessions.mjs watch <name>
|
|
31
|
+
node <skill-dir>/agent-sessions.mjs dispatch
|
|
32
|
+
node <skill-dir>/agent-sessions.mjs claim <name> <path...> [--ttl <hours>] [--force]
|
|
33
|
+
node <skill-dir>/agent-sessions.mjs release <name> [path...]
|
|
34
|
+
node <skill-dir>/agent-sessions.mjs claims
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quick start for a person
|
|
38
|
+
|
|
39
|
+
Nothing runs until you start it, so a person who does not use this does nothing. To try it:
|
|
40
|
+
|
|
41
|
+
1. Run `node <skill-dir>/agent-sessions.mjs shell-install`. It adds one function per agent to your shell file.
|
|
42
|
+
2. Open a new terminal. In the repo, type `claude` or `codex` as usual. The function starts the agent in a `tmux` session and starts the dispatcher.
|
|
43
|
+
3. Ask one agent to message the other. An idle agent wakes when a message carries `--to <agent>`.
|
|
44
|
+
4. Run `node <skill-dir>/agent-sessions.mjs down` to stop the dispatcher. Run `shell-install --remove` to undo step 1.
|
|
45
|
+
|
|
46
|
+
## Sessions
|
|
47
|
+
|
|
48
|
+
`run <name> <command...>` starts the command in the `tmux` session `<name>@<repo>`, or attaches if it runs already. It also starts the dispatcher when none runs. Session names carry the repo name, so `codex` in two repos never collides. If that session has a terminal attached already, `run` starts `<name>-2`, then `<name>-3`, and so on. A detached session is attached again. So a second `claude` terminal gets its own agent.
|
|
49
|
+
|
|
50
|
+
`up codex=codex gemini=gemini` starts a detached `tmux` session per agent, named like its sender name, and runs the command in it. It also starts a session named `mailbox-dispatch` that runs `dispatch`. A running session is left alone. Attach to a session with `tmux attach -t <name>`. Detach with `Ctrl-b`, then `d`. The session and its agent keep running. Use `down` to stop the dispatcher and the named sessions.
|
|
51
|
+
|
|
52
|
+
`restart <name> <prompt...>` types the clear command (`/clear`, or `/new` for a `codex` name) and then the prompt into the session `<name>@<repo>`, no sooner than `--after` seconds (default 5). It waits until that session ended its turn and its prompt holds no typed text, and gives up after 30 minutes. The command returns at once, so end your turn after it. An agent uses it to clear itself and resume from its saved work state. It refuses any session other than the caller's own (from `$TMUX_PANE`), and the error names the caller's own sender name. Background commands of the old session still report into the new one.
|
|
53
|
+
|
|
54
|
+
`shell-install` writes one shell function per agent into `~/.zshrc` or `~/.bashrc`, between two marker lines. A second run replaces the block, and `--remove` deletes it. Use `--file` for another startup file and `--dry-run` to preview. After a new terminal opens, typing `claude` or `codex` in a repo with this skill runs the agent through `run`. Elsewhere the function starts the plain command. Run `shell-install` only when the user asks: it changes a file the user owns. `shell-init` prints the same functions without writing a file.
|
|
55
|
+
|
|
56
|
+
Choose a `<name>` that no other agent uses, for example `agent-a` or `agent-b`. Two sessions with one name look like one agent.
|
|
57
|
+
|
|
58
|
+
## Messages
|
|
59
|
+
|
|
60
|
+
The mailbox file is `.ethlete/mailbox.jsonl` in the git root. The first write also creates `.ethlete/.gitignore`, so the file stays out of git. Set `AGENT_MAILBOX` to use another path. For two Claude Code sessions, the `SendMessage` tool is the better channel. The mailbox is for agents that cannot reach each other directly.
|
|
61
|
+
|
|
62
|
+
An idle agent cannot read the mailbox. One `dispatch` process outside every agent fixes this. It polls the mailbox for free. When a message carries `--to <agent>`, it waits a short grace period and then, if the agent has not read the message, types a wake-up line into the `tmux` session `<agent>@<repo>`, or a session named only `<agent>`. The agent then runs `inbox` and acts. A message without `--to` wakes nobody.
|
|
63
|
+
|
|
64
|
+
If the prompt of the agent holds typed text, the dispatcher waits until that text is sent or cleared. It checks again every 2 seconds. An open menu, for example a permission dialog, also makes it wait. If the agent is in the middle of a turn, the wake-up line waits as its next prompt. An agent in a `tmux` session does not need the `--wait` loop, which costs a turn at every timeout. If you wait for an answer in a session without `tmux`, run `inbox <name> --wait 120`: it blocks until a message arrives or 120 seconds pass. If it prints "No new messages.", run it again. A background `--wait` ends after one message, so it is not a lasting watch.
|
|
65
|
+
|
|
66
|
+
- `inbox` keeps one cursor per sender name, so it never repeats a message. The first call shows the last 20.
|
|
67
|
+
- `read` shows the last 20 messages. Use `--all` for the full history.
|
|
68
|
+
- `send` with no message reads it from standard input, so a long message needs no shell quoting.
|
|
69
|
+
- `watch` is optional. It runs until you stop it. In Claude Code, start it with the `Monitor` tool, so a new message wakes the session. Without such a feature, rely on `inbox`.
|
|
70
|
+
- Never rewrite or truncate the file. Only the script appends to it.
|
|
71
|
+
- Keep credentials and personal data out of the mailbox.
|
|
72
|
+
|
|
73
|
+
## Claims
|
|
74
|
+
|
|
75
|
+
1. At the start of a task, run `claims` and `inbox`. They show what other agents hold and said.
|
|
76
|
+
2. Before you edit a file, run `claim` with the exact paths. A directory path claims everything below it. `claim` also prints the messages you have not seen yet.
|
|
77
|
+
3. If `claim` reports a conflict, do not edit. Run `send` to ask the holder for a handoff, then wait.
|
|
78
|
+
4. After each larger step, run `inbox` again. Most agents cannot wake on new output, so you must pull messages yourself.
|
|
79
|
+
5. When you finish, run `release`. A claim also expires after 4 hours, or after `--ttl` hours.
|
|
80
|
+
|
|
81
|
+
A claim is advisory, not a lock. `--force` claims over another agent: use it only after the holder agreed. Silence is not approval. Acknowledge each handoff in words. No agent starts automatically. The user starts each one.
|