@yaawn/workflow 0.0.0-stage → 0.4.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 +172 -2
- package/agents/instructions/output-styles/yaawn-eli5.instructions.md +45 -0
- package/agents/instructions/yaawn-accessibility.css.instructions.md +58 -0
- package/agents/instructions/yaawn-accessibility.html.instructions.md +90 -0
- package/agents/instructions/yaawn-accessibility.javascript.instructions.md +50 -0
- package/agents/instructions/yaawn-clean-code.typescript.instructions.md +74 -0
- package/agents/instructions/yaawn-function-coupling.typescript.instructions.md +100 -0
- package/agents/instructions/yaawn-html-css-js.html.instructions.md +32 -0
- package/agents/instructions/yaawn-open-source-first.instructions.md +38 -0
- package/agents/instructions/yaawn-personas.instructions.md +18 -0
- package/agents/instructions/yaawn-semantic-html.html.instructions.md +40 -0
- package/agents/instructions/yaawn-vanilla-css.css.instructions.md +50 -0
- package/agents/output-styles/yaawn-eli5.instructions.md +45 -0
- package/agents/personas/yaawn-developer.md +16 -0
- package/agents/personas/yaawn-product-owner.md +18 -0
- package/agents/personas/yaawn-reviewer.md +16 -0
- package/agents/skills/yaawn-clean-code/SKILL.md +61 -0
- package/agents/skills/yaawn-clean-code/references/classes.md +114 -0
- package/agents/skills/yaawn-clean-code/references/comments.md +164 -0
- package/agents/skills/yaawn-clean-code/references/error-handling.md +151 -0
- package/agents/skills/yaawn-clean-code/references/formatting.md +146 -0
- package/agents/skills/yaawn-clean-code/references/functions.md +261 -0
- package/agents/skills/yaawn-clean-code/references/meaningful-names.md +234 -0
- package/agents/skills/yaawn-clean-code/references/objects-and-data-structures.md +130 -0
- package/agents/skills/yaawn-clean-code/references/principles.md +76 -0
- package/agents/skills/yaawn-clean-code/references/simple-design-and-code-smells.md +130 -0
- package/agents/skills/yaawn-clean-code/references/unit-tests.md +114 -0
- package/agents/skills/yaawn-create-plan/SKILL.md +234 -0
- package/agents/skills/yaawn-grill-bug-report/SKILL.md +31 -0
- package/agents/skills/yaawn-grill-bug-report/references/bug-report-checklist.md +27 -0
- package/agents/skills/yaawn-grill-design/SKILL.md +68 -0
- package/agents/skills/yaawn-grill-design/references/design-checklist.md +36 -0
- package/agents/skills/yaawn-grill-other/SKILL.md +31 -0
- package/agents/skills/yaawn-grill-other/references/other-checklist.md +19 -0
- package/agents/skills/yaawn-grill-refactor/SKILL.md +31 -0
- package/agents/skills/yaawn-grill-refactor/references/refactor-checklist.md +26 -0
- package/agents/skills/yaawn-grill-spike/SKILL.md +31 -0
- package/agents/skills/yaawn-grill-spike/references/spike-checklist.md +25 -0
- package/agents/skills/yaawn-grill-story/SKILL.md +34 -0
- package/agents/skills/yaawn-grill-story/references/concept-challenge.md +77 -0
- package/agents/skills/yaawn-grill-story/references/story-checklist.md +44 -0
- package/agents/skills/yaawn-implement-plan/SKILL.md +196 -0
- package/agents/skills/yaawn-implement-plan/assets/fix-prompt.md +66 -0
- package/agents/skills/yaawn-implement-plan/assets/review-prompt.md +89 -0
- package/agents/skills/yaawn-implement-plan/assets/session-prompt.md +80 -0
- package/agents/skills/yaawn-implement-plan/scripts/agent.ts +218 -0
- package/agents/skills/yaawn-implement-plan/scripts/caffeinate.ts +56 -0
- package/agents/skills/yaawn-implement-plan/scripts/groups.ts +233 -0
- package/agents/skills/yaawn-implement-plan/scripts/overnight.ts +772 -0
- package/agents/skills/yaawn-implement-plan/scripts/parallel.ts +1176 -0
- package/agents/skills/yaawn-implement-plan/scripts/processes.ts +53 -0
- package/agents/skills/yaawn-implement-plan/scripts/stages.ts +65 -0
- package/agents/skills/yaawn-implement-plan/scripts/targets.ts +381 -0
- package/agents/skills/yaawn-implement-plan/scripts/worktrees.ts +431 -0
- package/agents/skills/yaawn-owasp-security/SKILL.md +106 -0
- package/agents/skills/yaawn-owasp-security/references/a01-broken-access-control.md +58 -0
- package/agents/skills/yaawn-owasp-security/references/a02-security-misconfiguration.md +56 -0
- package/agents/skills/yaawn-owasp-security/references/a03-software-supply-chain-failures.md +56 -0
- package/agents/skills/yaawn-owasp-security/references/a04-cryptographic-failures.md +67 -0
- package/agents/skills/yaawn-owasp-security/references/a05-injection.md +53 -0
- package/agents/skills/yaawn-owasp-security/references/a06-insecure-design.md +48 -0
- package/agents/skills/yaawn-owasp-security/references/a07-authentication-failures.md +68 -0
- package/agents/skills/yaawn-owasp-security/references/a08-software-data-integrity-failures.md +45 -0
- package/agents/skills/yaawn-owasp-security/references/a09-security-logging-alerting-failures.md +59 -0
- package/agents/skills/yaawn-owasp-security/references/a10-mishandling-exceptional-conditions.md +63 -0
- package/agents/skills/yaawn-prepare-plan/SKILL.md +110 -0
- package/agents/skills/yaawn-save-plan/SKILL.md +84 -0
- package/agents/skills/yaawn-save-plan/scripts/plan-body.ts +397 -0
- package/agents/skills/yaawn-save-plan/scripts/save-plan.ts +539 -0
- package/agents/skills/yaawn-split-story/SKILL.md +189 -0
- package/agents/skills/yaawn-split-story/references/spider.md +64 -0
- package/agents/skills/yaawn-split-story/scripts/create-issue.ts +162 -0
- package/agents/skills/yaawn-verify-executed-plan/SKILL.md +154 -0
- package/agents/skills/yaawn-verify-executed-plan/scripts/overnight.ts +362 -0
- package/agents/skills/yaawn-verify-executed-plan/scripts/pull-request.ts +131 -0
- package/agents/skills/yaawn-write-bug-report/SKILL.md +87 -0
- package/agents/skills/yaawn-write-other/SKILL.md +90 -0
- package/agents/skills/yaawn-write-refactor/SKILL.md +94 -0
- package/agents/skills/yaawn-write-spike/SKILL.md +94 -0
- package/agents/skills/yaawn-write-user-story/SKILL.md +187 -0
- package/agents/skills/yaawn-write-user-story/references/acceptance-criteria.md +186 -0
- package/agents/skills/yaawn-write-user-story/references/five-types-of-value.md +82 -0
- package/agents/skills/yaawn-write-user-story/references/user-story-fundamentals.md +75 -0
- package/agents/yaawn-glossary.md +146 -0
- package/agents/yaawn-grilling.md +75 -0
- package/agents/yaawn-worktrees.md +69 -0
- package/config/install-tasks.json +35 -0
- package/config/settings.json +23 -0
- package/config/wizard.json +128 -0
- package/github/ISSUE_TEMPLATE/yaawn-bug-report.md +59 -0
- package/github/ISSUE_TEMPLATE/yaawn-other.md +38 -0
- package/github/ISSUE_TEMPLATE/yaawn-refactor.md +38 -0
- package/github/ISSUE_TEMPLATE/yaawn-spike.md +16 -0
- package/github/ISSUE_TEMPLATE/yaawn-story.md +56 -0
- package/package.json +33 -4
- package/scripts/install.js +73 -0
- package/yaawn/gitignore +1 -0
- package/yaawn/yaawn-definition-of-done.md +5 -0
- package/yaawn/yaawn-project-glossary.md +7 -0
- package/yaawn/yaawn-user-roles.md +3 -0
- package/yaawn/yaawn-verification-commands.md +7 -0
package/README.md
CHANGED
|
@@ -1,3 +1,173 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @yaawn/workflow
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Installs `.agents/` skill files (skills, instructions, output-styles), agent personas, the shared `.yaawn/yaawn-definition-of-done.md`, `.yaawn/yaawn-verification-commands.md`, `.yaawn/yaawn-user-roles.md` and `.yaawn/yaawn-project-glossary.md`, and the `yaawn-*` issue templates into your project.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @yaawn/workflow
|
|
9
|
+
npx @yaawn/workflow
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
### Options
|
|
13
|
+
|
|
14
|
+
| Flag | Effect |
|
|
15
|
+
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
16
|
+
| `-y`, `--yes` | Skip the interactive setup (with `--uninstall`: remove without asking) |
|
|
17
|
+
| `--agent copilot\|claude\|vibe` | Coding agent to set up; saved to `.yaawn/yaawn-settings.json`, which is local to each developer (gitignored). Omitted: the previous choice, else `copilot`. Other values exit with code 1 |
|
|
18
|
+
| `--uninstall` | Remove the yaawn files from your project instead of installing |
|
|
19
|
+
| `-v`, `--version` | Print the version |
|
|
20
|
+
| `-h`, `--help` | Show help |
|
|
21
|
+
|
|
22
|
+
The install command syncs the bundled payload to your project root:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
your-project/
|
|
26
|
+
├── .agents/
|
|
27
|
+
│ ├── instructions/
|
|
28
|
+
│ ├── output-styles/
|
|
29
|
+
│ ├── personas/
|
|
30
|
+
│ └── skills/
|
|
31
|
+
├── .github/
|
|
32
|
+
│ └── ISSUE_TEMPLATE/
|
|
33
|
+
│ ├── yaawn-bug-report.md
|
|
34
|
+
│ ├── yaawn-refactor.md
|
|
35
|
+
│ ├── yaawn-spike.md
|
|
36
|
+
│ └── yaawn-story.md
|
|
37
|
+
└── .yaawn/
|
|
38
|
+
├── .gitignore
|
|
39
|
+
├── yaawn-definition-of-done.md
|
|
40
|
+
├── yaawn-project-glossary.md
|
|
41
|
+
├── yaawn-user-roles.md
|
|
42
|
+
└── yaawn-verification-commands.md
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
In a terminal, the sync prints colored output with one line per synced directory. After syncing, the command runs a short keyboard-driven setup:
|
|
46
|
+
|
|
47
|
+
1. **Coding agent** — pick exactly one: GitHub Copilot, Claude Code, or Mistral Vibe. The choice is saved to `.yaawn/yaawn-settings.json` and preselected on the next run. The file is local to each developer — `.yaawn/.gitignore` keeps it out of git, so every teammate picks their own agent.
|
|
48
|
+
1. **Definition of done** — type the tasks your team requires before work counts as done. They are added as a checklist to `.yaawn/yaawn-definition-of-done.md`.
|
|
49
|
+
1. **Verification commands** — type the commands to run, in order. They are added in run order as a list to `.yaawn/yaawn-verification-commands.md`. `/yaawn-verify-executed-plan` runs exactly these commands and stops at the first failure, so list the cheap ones first.
|
|
50
|
+
1. **User roles** — type the roles your product's users have, the "As a …" of a user story (for example `Account Owner`). They are added as a plain list to `.yaawn/yaawn-user-roles.md`, and the story skills write stories from these roles. With no roles listed, stories are written for the Developer.
|
|
51
|
+
1. **GitHub projects** — type the names of the GitHub projects your team uses (for example `Team Board`). After the sync, they are written into the `projects:` line of every `yaawn-*` issue template in `.github/ISSUE_TEMPLATE/`, so new issues land on those project boards. Names already in the templates are kept and merged with the new ones (case-insensitive, no duplicates); with no names entered, the templates stay unchanged.
|
|
52
|
+
1. **Languages** — check the languages your project uses. Only the matching language-tagged instructions — `yaawn-*.<lang>.instructions.md` files in `.agents/instructions/` — are installed; instructions without a language tag always install.
|
|
53
|
+
|
|
54
|
+
After the sync, the command links `.agents/` where the chosen agent looks for it, with relative symlinks:
|
|
55
|
+
|
|
56
|
+
- **Copilot:** `.github/skills` → `../.agents/skills` and `.github/instructions` → `../.agents/instructions`.
|
|
57
|
+
- **Claude Code:** `.claude/skills` → `../.agents/skills`. Instructions are imported in `.claude/CLAUDE.md` with one `@../.agents/instructions/<file>` line per instruction file, inside a block between `<!-- yaawn:instructions:start -->` and `<!-- yaawn:instructions:end -->`. Only that block is written; the rest of the file stays yours.
|
|
58
|
+
- **Vibe:** no skill links — Vibe reads `.agents/skills` natively. Instructions are listed in the root `AGENTS.md`, inside a block between `<!-- yaawn:instructions:start -->` and `<!-- yaawn:instructions:end -->`: a note to read the instructions whose `applyTo` matches a file before editing it, followed by one `- .agents/instructions/<file>` line per instruction file. Only that block is written; text outside it stays yours.
|
|
59
|
+
|
|
60
|
+
If the folder already exists as a real folder, each `yaawn-*` skill or instruction is linked inside it one by one. Existing links into `.agents/` are kept, and anything else with the same name is skipped and left untouched. Each link is reported as created, already there, skipped, or failed; a failed link shows the `ln -s` command to create it by hand, the other links are still created, and the command exits with code 1. Switching agents keeps the old agent's links.
|
|
61
|
+
|
|
62
|
+
Keyboard controls in the setup wizard: `enter` adds the typed item to the current step (on an empty line it continues to the next step), `tab`/`shift+tab` switch to the next/previous step, `esc` finishes the setup from any step and installs (like `tab`, it keeps what you typed on the current step), `ctrl+c` cancels the install without writing anything. In the language step, `space` toggles the language under the cursor, `up`/`down` move, and `enter` confirms the selection and finishes the setup.
|
|
63
|
+
|
|
64
|
+
Existing answers are kept when you run it again — already-listed items show up pre-checked, selected languages show up pre-checked, and duplicates are skipped — and the setup is skipped when you pass `--yes`; then all language-tagged instructions install. Without a terminal (for example in CI) the command stops unless you pass `--yes`. You can also edit these files by hand. In the commands file, every `- ` bullet is one command, run through the shell from the repo root:
|
|
65
|
+
|
|
66
|
+
```markdown
|
|
67
|
+
- `npm run lint && npm test`
|
|
68
|
+
- `npm run e2e`
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The command runs as an explicit step, not a lifecycle script, so it behaves the same in every package manager (npm, yarn, bun). With npm or yarn you can also invoke the bin directly: `npm exec workflow` or `yarn workflow`.
|
|
72
|
+
|
|
73
|
+
## Uninstall
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npx @yaawn/workflow --uninstall # list, confirm, remove
|
|
77
|
+
npx @yaawn/workflow --uninstall --yes # remove without asking (CI)
|
|
78
|
+
npm uninstall @yaawn/workflow
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
When yaawn files are found, an interactive run first asks whether to **Install / update** or **Uninstall**; fresh projects skip this question. `--uninstall` skips the question and goes straight to uninstalling.
|
|
82
|
+
|
|
83
|
+
- **List, then confirm.** The command lists every file it will remove and asks before deleting anything. The answer defaults to "No"; declining or `ctrl+c` prints "Uninstall cancelled. Nothing was removed." and exits with code 130.
|
|
84
|
+
- **What is removed.** Every `yaawn-*` entry the current package ships that exists in your project — in `.agents/skills/`, `.agents/instructions/`, `.agents/output-styles/`, `.agents/personas/`, `.github/ISSUE_TEMPLATE/`, plus `.agents/yaawn-glossary.md`, `.agents/yaawn-grilling.md`, `.yaawn/yaawn-definition-of-done.md`, `.yaawn/yaawn-verification-commands.md`, `.yaawn/yaawn-user-roles.md`, `.yaawn/yaawn-project-glossary.md`, `.yaawn/yaawn-settings.json`, and `.yaawn/.gitignore`. Every agent link into `.agents/` is removed too, for every agent — `.github/skills`, `.github/instructions`, `.claude/skills`, the links inside those folders when they are real folders, and the yaawn import block in `.claude/CLAUDE.md`, and the yaawn instructions block in `AGENTS.md` (each file is deleted only when nothing else is left in it). Folders that become empty are removed too; `.agents/`, `.github/`, and `.yaawn/` themselves are kept, and so are folders that were already empty.
|
|
85
|
+
- **What is kept.** `.yaawn/plans/` (your team's plans and logs), your own files, and stale `yaawn-*` entries from older versions that the current package no longer ships.
|
|
86
|
+
- **Stays inside your project.** Symlinks are removed, never the files they point to. If a target folder points outside the project, the command stops before removing anything.
|
|
87
|
+
- **Stops at the first error.** Agent links are removed first, and every link is tried even if one fails. If a file cannot be removed, the command stops, shows what was already removed and the error, and exits with code 1. Nothing is restored.
|
|
88
|
+
- **Nothing to remove.** Without yaawn files the command says so and exits with code 0.
|
|
89
|
+
- **Without a terminal.** `--uninstall` without `--yes` exits with code 1 and removes nothing.
|
|
90
|
+
- **Package removal.** The summary ends with the command that removes the package itself: `npm uninstall @yaawn/workflow`.
|
|
91
|
+
|
|
92
|
+
## Behavior
|
|
93
|
+
|
|
94
|
+
- **Always overwrites, except your answers.** The package is the source of truth — after `npm update @yaawn/workflow`, re-run `npx @yaawn/workflow` to sync the latest versions into your project. The exceptions are `.yaawn/yaawn-definition-of-done.md`, `.yaawn/yaawn-verification-commands.md`, `.yaawn/yaawn-user-roles.md`, and `.yaawn/yaawn-project-glossary.md`: they are only written when missing, so your team's answers survive updates.
|
|
95
|
+
- **Deletes yaawn files first.** Before copying, the command deletes the `yaawn-*` entries in `.agents/skills/`, `.agents/instructions/`, `.agents/output-styles/`, `.agents/personas/`, and `.github/ISSUE_TEMPLATE/`, so skills and templates the package no longer ships disappear. Do not put your own changes into `yaawn-*` files — they are replaced on every sync. Everything else in those folders (your own skills, workflows, and templates) and everything in `.yaawn/` (your answers and plans) is left alone.
|
|
96
|
+
- **Language-tagged instructions.** Instruction files named `yaawn-*.<lang>.instructions.md` (for example `yaawn-clean-code.typescript.instructions.md`) install only for the languages selected in the setup. Unchecking a language on a later run removes its instructions again. With `--yes` or without a terminal, all language-tagged instructions install.
|
|
97
|
+
- **Tracked by git.** The command never touches your root `.gitignore` — `.yaawn/` is meant to be committed, so plans, logs, your definition of done, and your verification commands are shared with the team. The exception is `yaawn-settings.json`: the command writes `.yaawn/.gitignore` (replaced on every sync) to keep each developer's coding-agent choice out of git.
|
|
98
|
+
- **Non-destructive.** Existing `.yaawn/` and `.github/` folders are kept — only the shipped `yaawn-*` files are replaced in them, and missing folders are created.
|
|
99
|
+
- **Idempotent.** Running the install command multiple times produces the same result.
|
|
100
|
+
- **Non-blocking.** If the sync fails for any reason, the command reports the error but does not fail.
|
|
101
|
+
- **`--yes` in CI.** Without a terminal and without `--yes`, the command exits with code 1 and a message to rerun with `--yes`, and writes nothing. In CI, always run `npx @yaawn/workflow --yes`.
|
|
102
|
+
- **Native binary.** The installer is a Go binary shipped per platform; `npx @yaawn/workflow` runs a small Node.js shim that starts it. See [Supported platforms](#supported-platforms).
|
|
103
|
+
|
|
104
|
+
## What's included
|
|
105
|
+
|
|
106
|
+
- **Skills** — agent skill definitions with references and scripts
|
|
107
|
+
- **Instructions** — project-level instruction files
|
|
108
|
+
- **Output styles** — predefined output formatting styles
|
|
109
|
+
- **Agent personas** — `.agents/personas/yaawn-*.md`: Developer (default), Reviewer, and Product Owner. The always-on `yaawn-personas` instruction picks the persona per task; you never choose one
|
|
110
|
+
- **Issue templates** — `yaawn-*` templates for bugs, refactors, spikes, and stories; they no longer reference the Definition of Done
|
|
111
|
+
- **Definition of Done** — `.yaawn/yaawn-definition-of-done.md`, the standard checklist and its single source of truth; `/yaawn-implement-plan` and `/yaawn-verify-executed-plan` read it directly
|
|
112
|
+
- **Verification commands** — `.yaawn/yaawn-verification-commands.md`, the commands `/yaawn-verify-executed-plan` runs
|
|
113
|
+
- **User roles** — `.yaawn/yaawn-user-roles.md`, the roles the story skills write for; Developer when none are listed
|
|
114
|
+
- **Project glossary** — `.yaawn/yaawn-project-glossary.md`, the project's settled terms, written by `/yaawn-grill-design`; created once and kept across updates
|
|
115
|
+
|
|
116
|
+
## Supported platforms
|
|
117
|
+
|
|
118
|
+
The binary ships in one optional dependency per platform, and npm installs only the one matching your machine:
|
|
119
|
+
|
|
120
|
+
| Platform | Package |
|
|
121
|
+
| -------------------- | ------------------------------ |
|
|
122
|
+
| macOS, Apple silicon | `@yaawn/workflow-darwin-arm64` |
|
|
123
|
+
| macOS, Intel | `@yaawn/workflow-darwin-x64` |
|
|
124
|
+
| Linux, x64 | `@yaawn/workflow-linux-x64` |
|
|
125
|
+
| Linux, arm64 | `@yaawn/workflow-linux-arm64` |
|
|
126
|
+
| Windows, x64 | `@yaawn/workflow-win32-x64` |
|
|
127
|
+
|
|
128
|
+
On any other platform, the command exits with code 1 and prints `workflow: unsupported platform <platform>/<arch> — supported: ...`. When the platform package is missing (for example after `npm install --omit=optional`, or from a stale `npx` cache), it prints `workflow: installer binary package @yaawn/workflow-<platform> is not installed — ...`.
|
|
129
|
+
|
|
130
|
+
## Configuration
|
|
131
|
+
|
|
132
|
+
The installer's content lives in three JSON files in `config/`. The binary reads them at every start, so editing them needs no rebuild:
|
|
133
|
+
|
|
134
|
+
- **`wizard.json`** — the setup steps in order (`id`, `title`, `description`, `kind` of `text-list` or `multiselect`, `targetFile`, `placeholder`) and every user-facing message under `messages`: help, version, intro, outro, key hints, and status and error lines. `{placeholders}` are filled in at runtime.
|
|
135
|
+
- **`settings.json`** — `brandColor`, the `filePrefix` of yaawn-owned files, the `outputFileNames` the text-list steps write to, the `languagePattern` that extracts the language tag from instruction file names, the `languageLabels` shown in the language step, and the `languageImplications` — tags whose files also install when a tag is selected (e.g. TypeScript also installs JavaScript, not the other way round).
|
|
136
|
+
- **`install-tasks.json`** — the `syncTargets`: which bundled `source` directory is copied to which project `target`, which files are only seeded when missing (`seedOnly`), which `removeFirst` globs are deleted before copying, which files are installed under a different name (`renames`, plain file names mapped source → target, e.g. `gitignore` → `.gitignore`, because npm drops `.gitignore` files from published packages), and which directory holds the language-tagged instructions (`languageInstructions`).
|
|
137
|
+
|
|
138
|
+
All three are validated strictly on load. An unknown key, a missing field, or a path that escapes the package root (sources) or the project directory (targets) stops the command with exit code 1 and a message naming the file and field — nothing is written.
|
|
139
|
+
|
|
140
|
+
## Development
|
|
141
|
+
|
|
142
|
+
The installer source is a Go module in `cli/`. Install the Go version pinned by the `toolchain` line in `cli/go.mod`, then:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
cd packages/workflow/cli
|
|
146
|
+
go test ./...
|
|
147
|
+
go run ./cmd/workflow --package-root .. --yes
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
`--package-root` points the binary at the package directory holding `config/` and the payload; the shim passes it automatically. The local run syncs into the current directory (or `INIT_CWD` when set), so run it from a scratch project, not from this repository.
|
|
151
|
+
|
|
152
|
+
## Releasing
|
|
153
|
+
|
|
154
|
+
Publishing runs only in GitHub Actions ([`publish-workflow.yml`](../../.github/workflows/publish-workflow.yml)); the release script refuses to publish locally.
|
|
155
|
+
|
|
156
|
+
To release, open **Actions → Publish @yaawn/workflow → Run workflow** on `main`, pick the version bump (`patch`, `minor`, `major`), and uncheck **dry-run**.
|
|
157
|
+
|
|
158
|
+
The workflow runs the Go tests, bumps `version` in `package.json`, and runs `release/release-installer.mjs`. The script cross-compiles the binary for the five supported platforms into `npm/<platform>/` (gitignored), writes one package per platform at the new version, sets `optionalDependencies` to that version, publishes the platform packages, and then publishes `@yaawn/workflow`. After a successful publish, the workflow commits `package.json` to `main` and pushes the tag `workflow-v<version>`. Versions that are already on npm are skipped.
|
|
159
|
+
|
|
160
|
+
With **dry-run** checked, the workflow builds and runs `npm publish --dry-run` without committing or tagging. Locally, run `npm run release:dry-run` with Go installed.
|
|
161
|
+
|
|
162
|
+
Publishing uses [npm trusted publishing](https://docs.npmjs.com/trusted-publishers): npm authenticates the workflow via OIDC, so no long-lived token is stored. On npmjs.com, each of the six packages (`@yaawn/workflow` and `@yaawn/workflow-<platform>`) needs a trusted publisher with repository `markusfalk/yaawn`, workflow `publish-workflow.yml`, and environment `npm`.
|
|
163
|
+
|
|
164
|
+
Trusted publishers can only be added to packages that already exist. To bootstrap a new package, publish its first version once by hand with interactive 2FA, then add the trusted publisher. For the platform packages:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
cd packages/workflow
|
|
168
|
+
npm login
|
|
169
|
+
npm run release:dry-run
|
|
170
|
+
for p in darwin-arm64 darwin-x64 linux-x64 linux-arm64 win32-x64; do
|
|
171
|
+
(cd "npm/$p" && npm publish)
|
|
172
|
+
done
|
|
173
|
+
```
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ELI5
|
|
3
|
+
description: 'Use only when the user explicitly asks for an ELI5, beginner-level, or plainly-worded explanation. Rewrites chat prose to use analogies, everyday vocabulary, and short sentences. Changes wording only — never code, commands, or file paths.'
|
|
4
|
+
keep-coding-instructions: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# ELI5
|
|
8
|
+
|
|
9
|
+
Explain things the way you would to someone smart who has never seen this system before.
|
|
10
|
+
|
|
11
|
+
## Scope
|
|
12
|
+
|
|
13
|
+
This style changes **the prose of chat answers only**. It never changes:
|
|
14
|
+
|
|
15
|
+
- code, identifiers, and type names
|
|
16
|
+
- file paths and shell commands
|
|
17
|
+
- API names, endpoints, and configuration keys
|
|
18
|
+
- error messages, stack traces, and log output
|
|
19
|
+
- diffs and code comments
|
|
20
|
+
- commit messages and PR descriptions
|
|
21
|
+
- i18n keys and i18n values
|
|
22
|
+
- anything inside a fenced code block
|
|
23
|
+
|
|
24
|
+
Reproduce all of the above verbatim. Generated code follows the repository's existing conventions and is never reworded to fit this style.
|
|
25
|
+
|
|
26
|
+
Accuracy outranks every rule below:
|
|
27
|
+
|
|
28
|
+
- Never simplify a technical term into an inaccurate one.
|
|
29
|
+
- Never shorten an error message or a security warning.
|
|
30
|
+
- Never drop a caveat to make a sentence shorter.
|
|
31
|
+
|
|
32
|
+
If a rule in this file would make the answer wrong, the rule loses.
|
|
33
|
+
|
|
34
|
+
If another output style is also active, stop and ask which one applies.
|
|
35
|
+
|
|
36
|
+
## Writing rules
|
|
37
|
+
|
|
38
|
+
- Lead with an analogy or a concrete everyday comparison, then connect it back to the real thing.
|
|
39
|
+
- Use everyday vocabulary. Prefer "reads" over "consumes", "goes wrong" over "fails to resolve".
|
|
40
|
+
- Keep sentences short. One idea per sentence.
|
|
41
|
+
- Introduce every technical term the first time it appears: name it, then say what it does in plain words.
|
|
42
|
+
- Prefer concrete examples over abstract description.
|
|
43
|
+
- Say what something is _for_ before saying how it works.
|
|
44
|
+
- Do not use jargon as a shortcut. If a term is unavoidable, explain it.
|
|
45
|
+
- Keep the answer as short as the question allows. Simple is not the same as long.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: '**/*.css'
|
|
3
|
+
description: 'Write accessible CSS following the A11Y Project checklist: color contrast, visible focus, reduced motion, zoom and reflow, touch targets. See https://www.a11yproject.com/checklist/'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Accessible CSS
|
|
7
|
+
|
|
8
|
+
Style content so everyone can perceive and operate it. These rules cover the styling layer of the A11Y Project checklist; they never replace accessible markup — fix the HTML first, then style it.
|
|
9
|
+
|
|
10
|
+
### Content
|
|
11
|
+
|
|
12
|
+
- Align body text to the start edge (`text-align: start`) — avoid centered or justified paragraphs
|
|
13
|
+
- Never use CSS-generated content (`::before`/`::after`) for information the page needs; keep it in the markup
|
|
14
|
+
|
|
15
|
+
### Keyboard
|
|
16
|
+
|
|
17
|
+
- Give every interactive element a clearly visible focus style with `:focus-visible`
|
|
18
|
+
- Never remove `outline` without a replacement of equal visibility (`outline: none` alone is forbidden)
|
|
19
|
+
- Make the skip link visible when it receives focus
|
|
20
|
+
- Do not reorder content visually (`order`, `flex-direction: row-reverse`, grid placement) so that focus order no longer matches what people see
|
|
21
|
+
|
|
22
|
+
### Controls
|
|
23
|
+
|
|
24
|
+
- Make links recognizable without color — underline links in body text
|
|
25
|
+
- Style hover, focus, and active states for every control
|
|
26
|
+
|
|
27
|
+
### Appearance
|
|
28
|
+
|
|
29
|
+
- Size text and containers in relative units (`rem`, `em`, `%`) so content stays readable and does not overlap at 200% text size or zoom
|
|
30
|
+
- Do not fix heights on containers holding text; let them grow
|
|
31
|
+
- Keep related content, labels, and controls close together so people using screen magnifiers can find them
|
|
32
|
+
- Never convey information by color alone — add text, an icon, a pattern, or an underline
|
|
33
|
+
- Keep the layout simple and consistent across pages
|
|
34
|
+
- Hide content visually but keep it for assistive technology with a visually-hidden class (clip pattern); use `display: none` or `visibility: hidden` only when content must be hidden from everyone
|
|
35
|
+
|
|
36
|
+
### Animation
|
|
37
|
+
|
|
38
|
+
- Wrap non-essential animation, transitions, parallax, and smooth scrolling in `@media (prefers-reduced-motion: no-preference)`, or remove them inside `@media (prefers-reduced-motion: reduce)`
|
|
39
|
+
- Slow down animation that is essential to understanding instead of removing it
|
|
40
|
+
- Never flash content more than three times per second
|
|
41
|
+
- Keep animations subtle and short
|
|
42
|
+
|
|
43
|
+
### Color contrast
|
|
44
|
+
|
|
45
|
+
- Give normal-sized text a contrast ratio of at least 4.5:1 against its background
|
|
46
|
+
- Give large text (24px, or 18.66px bold) at least 3:1
|
|
47
|
+
- Give icons, input borders (text inputs, checkboxes, radio buttons), and focus indicators at least 3:1
|
|
48
|
+
- Keep text over images or video legible — add a solid or semi-opaque backdrop behind it
|
|
49
|
+
- Respect forced-colors mode: do not convey state only through `background-color` or `box-shadow`, which forced colors remove
|
|
50
|
+
|
|
51
|
+
### Mobile and touch
|
|
52
|
+
|
|
53
|
+
- Build layouts that reflow to a 320 CSS px wide viewport without horizontal scrolling (except data tables, maps, and similar 2D content)
|
|
54
|
+
- Support portrait and landscape — never hide or rotate content based on `orientation`
|
|
55
|
+
- Make touch targets at least 44×44 CSS px, using padding instead of shrinking the hit area
|
|
56
|
+
- Leave space between adjacent interactive items so people can scroll past them
|
|
57
|
+
|
|
58
|
+
Reference: [The A11Y Project — Checklist](https://www.a11yproject.com/checklist/)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: '**/*.{html,tsx,jsx}'
|
|
3
|
+
description: 'Write accessible markup following the A11Y Project checklist: alt text, one h1, labelled inputs, table headers, captions, lang. See https://www.a11yproject.com/checklist/'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Accessible HTML
|
|
7
|
+
|
|
8
|
+
Write markup that assistive technology can read, understand, and operate. These rules cover the markup layer of the A11Y Project checklist; they build on the semantic HTML instruction — pick the semantic element first, then apply the rules below.
|
|
9
|
+
|
|
10
|
+
### Content
|
|
11
|
+
|
|
12
|
+
- Give every `<a>`, `<button>`, and `<label>` text that is unique on the page and describes its destination or action — never "click here" or "read more" alone
|
|
13
|
+
- Write instructions that name the element or section, not only its position, shape, color, or sound ("use the Search button", not "the button on the right")
|
|
14
|
+
|
|
15
|
+
### Global code
|
|
16
|
+
|
|
17
|
+
- Write valid HTML — no duplicate `id`s, no unclosed or misnested elements
|
|
18
|
+
- Set the page language on the root element (`<html lang="en">`) and mark passages in another language with `lang` on their element
|
|
19
|
+
- Give every page or view a unique, descriptive `<title>`
|
|
20
|
+
- Never disable zoom in the viewport meta tag — no `user-scalable=no`, no `maximum-scale=1`
|
|
21
|
+
- Wrap page regions in landmark elements: `<header>`, `<nav>`, `<main>` (exactly one), `<aside>`, `<footer>`
|
|
22
|
+
- Keep DOM order equal to visual order so content flows linearly
|
|
23
|
+
- Use `tabindex` only with `0` or `-1` — never a positive value; do not add it to natively focusable elements
|
|
24
|
+
- Do not use the `autofocus` attribute
|
|
25
|
+
|
|
26
|
+
### Keyboard
|
|
27
|
+
|
|
28
|
+
- Make every interactive element reachable by keyboard by using native controls (`<a href>`, `<button>`, form fields)
|
|
29
|
+
- Mark content that is hidden from view as `hidden` or `inert` so its controls cannot receive focus (closed menus, off-screen navigation, closed dialogs)
|
|
30
|
+
|
|
31
|
+
### Images
|
|
32
|
+
|
|
33
|
+
- Give every `<img>` an `alt` attribute
|
|
34
|
+
- Use `alt=""` for decorative images; describe the content and purpose for informative ones
|
|
35
|
+
- Include any text shown in the image in its `alt` (a logo's alt is the brand name)
|
|
36
|
+
- Provide a full text alternative for complex images (charts, graphs, maps) next to the image, linked via `<figure>`/`<figcaption>` or `aria-describedby`
|
|
37
|
+
- Give inline `<svg>` that conveys meaning `role="img"` and an accessible name (`<title>` or `aria-label`); give decorative `<svg>` `aria-hidden="true"`
|
|
38
|
+
|
|
39
|
+
### Headings
|
|
40
|
+
|
|
41
|
+
- Use exactly one `<h1>` per page or view, describing its purpose — not the site name repeated on every page
|
|
42
|
+
- Introduce each content section with a heading; never use headings only for their look
|
|
43
|
+
- Nest headings in order and never skip a level (`h2` → `h3`, not `h2` → `h4`)
|
|
44
|
+
|
|
45
|
+
### Lists
|
|
46
|
+
|
|
47
|
+
- Mark up related items as `<ul>`, `<ol>`, or `<dl>` — including navigation links and card grids
|
|
48
|
+
|
|
49
|
+
### Controls
|
|
50
|
+
|
|
51
|
+
- Use `<a href="…">` for navigation, always with an `href` — also in single-page apps
|
|
52
|
+
- Use `<button>` for actions and set `type="button"` on buttons that do not submit a form
|
|
53
|
+
- Provide a skip link to `<main>` as the first focusable element on the page
|
|
54
|
+
- Avoid opening links in a new tab or window; when one must, say so in the link text or an accessible hint
|
|
55
|
+
- Give icon-only controls an accessible name (visually hidden text or `aria-label`)
|
|
56
|
+
|
|
57
|
+
### Tables
|
|
58
|
+
|
|
59
|
+
- Use `<table>` for tabular data only, never for layout
|
|
60
|
+
- Mark header cells as `<th>` with `scope="col"` or `scope="row"`
|
|
61
|
+
- Give every table a `<caption>` that names its content
|
|
62
|
+
|
|
63
|
+
### Forms
|
|
64
|
+
|
|
65
|
+
- Associate every input with a `<label>` via `for`/`id`
|
|
66
|
+
- Group related inputs with `<fieldset>` and name the group with `<legend>`
|
|
67
|
+
- Set `autocomplete` on fields that ask for personal data (name, email, address, phone)
|
|
68
|
+
- After submission, show an error summary above the form that lists each error and links to its field
|
|
69
|
+
- Link each error message to its input with `aria-describedby` and mark the input `aria-invalid="true"`
|
|
70
|
+
- State errors, warnings, and success in text or an icon with a text alternative — never by color alone
|
|
71
|
+
|
|
72
|
+
### Media
|
|
73
|
+
|
|
74
|
+
- Do not set `autoplay` on `<video>` or `<audio>`
|
|
75
|
+
- Use the `controls` attribute or an accessible custom player so every media element can be paused
|
|
76
|
+
|
|
77
|
+
### Video
|
|
78
|
+
|
|
79
|
+
- Provide captions for every video with speech or meaningful sound via `<track kind="captions" srclang="…" label="…">`
|
|
80
|
+
|
|
81
|
+
### Audio
|
|
82
|
+
|
|
83
|
+
- Provide a text transcript for every audio file and link it next to the player
|
|
84
|
+
|
|
85
|
+
### Mobile and touch
|
|
86
|
+
|
|
87
|
+
- Do not lock the page to one orientation
|
|
88
|
+
- Keep space between adjacent links and buttons so people can scroll without activating them
|
|
89
|
+
|
|
90
|
+
Reference: [The A11Y Project — Checklist](https://www.a11yproject.com/checklist/)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: '**/*.{js,jsx,ts,tsx,mts}'
|
|
3
|
+
description: 'Write accessible JavaScript following the A11Y Project checklist: keyboard-operable controls, focus management, live regions, reduced motion, safe rendering. See https://www.a11yproject.com/checklist/'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Accessible JavaScript
|
|
7
|
+
|
|
8
|
+
Keep scripted behavior operable for keyboard, screen reader, and switch users. These rules cover the scripting layer of the A11Y Project checklist. Reach for JavaScript last — when a native HTML element or CSS solves the problem, use it instead.
|
|
9
|
+
|
|
10
|
+
### Global code
|
|
11
|
+
|
|
12
|
+
- Update `document.title` on every client-side route change so each view has a unique title
|
|
13
|
+
- Let people turn off, adjust, or extend session timeouts — warn them before the session ends and offer a way to extend it
|
|
14
|
+
- Do not move focus or change context on load or on input alone (no automatic submit on `change`)
|
|
15
|
+
|
|
16
|
+
### Keyboard
|
|
17
|
+
|
|
18
|
+
- Prefer native elements (`<button>`, `<a href>`, `<dialog>`, `<details>`) over scripted widgets — they are keyboard-operable for free
|
|
19
|
+
- When a custom control is unavoidable, give it the matching `role`, `tabindex="0"`, an accessible name, and state attributes (`aria-expanded`, `aria-pressed`, `aria-selected`) kept in sync with its state
|
|
20
|
+
- Handle `Enter` and `Space` for button-like controls, and arrow keys where the ARIA Authoring Practices pattern expects them
|
|
21
|
+
- Never bind actions to mouse-only events (`mousedown`, `mouseover`, `dblclick`) without a keyboard equivalent
|
|
22
|
+
- Set `inert` (or remove from the DOM) on content that is closed or off screen so it cannot receive focus
|
|
23
|
+
|
|
24
|
+
### Controls
|
|
25
|
+
|
|
26
|
+
- Move focus into a dialog when it opens and return it to the triggering control when it closes; prefer `<dialog>` with `showModal()`
|
|
27
|
+
- Trap focus only inside a modal dialog, and always let `Escape` close it
|
|
28
|
+
- Move focus to the new view's `<h1>` or `<main>` (with `tabindex="-1"`) after a client-side route change
|
|
29
|
+
- Announce dynamic updates (results counts, saved states, toasts, form errors) through a live region (`role="status"` or `aria-live="polite"`; `role="alert"` only for urgent errors) that exists in the DOM before the update
|
|
30
|
+
- On a failed submit, render the error summary, move focus to it, and link each error to its field
|
|
31
|
+
|
|
32
|
+
### Media
|
|
33
|
+
|
|
34
|
+
- Never start playback automatically — play only after a user action
|
|
35
|
+
- Give custom media players keyboard-operable, labelled controls for play/pause, volume, captions, and seeking
|
|
36
|
+
- Let `Space` toggle playback when the player has focus, without hijacking `Space` scrolling elsewhere on the page
|
|
37
|
+
|
|
38
|
+
### Animation
|
|
39
|
+
|
|
40
|
+
- Check `matchMedia('(prefers-reduced-motion: reduce)')` before running scripted animation, scrolling, or auto-advancing carousels, and listen for changes
|
|
41
|
+
- Provide a control to pause, stop, or hide anything that moves, blinks, or auto-updates for more than five seconds, including background video
|
|
42
|
+
|
|
43
|
+
### Safe rendering
|
|
44
|
+
|
|
45
|
+
- Render user-supplied or remote content with `textContent`, `setAttribute`, or framework bindings that escape output — never with `innerHTML`, `outerHTML`, `insertAdjacentHTML`, or `document.write`
|
|
46
|
+
- Sanitize HTML with a maintained sanitizer (for example DOMPurify) when rich content must be rendered, and avoid framework escape hatches such as `dangerouslySetInnerHTML` with untrusted data
|
|
47
|
+
- Write messages into live regions as text, never as markup built from user input
|
|
48
|
+
- Never pass user content to `eval`, `new Function`, or string arguments of `setTimeout`/`setInterval`
|
|
49
|
+
|
|
50
|
+
Reference: [The A11Y Project — Checklist](https://www.a11yproject.com/checklist/)
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: '**/*.{ts,mts,tsx}'
|
|
3
|
+
description: 'This document outlines the clean code principles and best practices for the codebase.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Clean Code Principles (Based on Robert C. Martin)
|
|
7
|
+
|
|
8
|
+
### 1. Single Responsibility Principle (SRP)
|
|
9
|
+
|
|
10
|
+
- Each class/module should have one and only one reason to change
|
|
11
|
+
- Keep functions focused and small
|
|
12
|
+
- Separate concerns appropriately
|
|
13
|
+
|
|
14
|
+
### 2. Naming Conventions
|
|
15
|
+
|
|
16
|
+
- Use intention-revealing names
|
|
17
|
+
- Choose meaningful and pronounceable variable names
|
|
18
|
+
- Use consistent verbs for method names (get/set/is/has/update)
|
|
19
|
+
- Avoid abbreviations unless they're widely accepted
|
|
20
|
+
- never use snake_case or Hungarian notation
|
|
21
|
+
- Use PascalCase for classes and interfaces
|
|
22
|
+
- Use camelCase for variables, functions, and methods
|
|
23
|
+
|
|
24
|
+
### 3. Function Rules
|
|
25
|
+
|
|
26
|
+
- Functions should do one thing
|
|
27
|
+
- Keep functions small (preferably under 20 lines)
|
|
28
|
+
- Minimize the number of arguments (3 or fewer is ideal)
|
|
29
|
+
- Avoid flag arguments
|
|
30
|
+
- Don't repeat yourself (DRY principle)
|
|
31
|
+
|
|
32
|
+
### 4. Comments and Documentation
|
|
33
|
+
|
|
34
|
+
- See the Comments section of `AGENTS.md` — it is the single source of truth for when to comment and how to tag one
|
|
35
|
+
|
|
36
|
+
### 5. Error Handling
|
|
37
|
+
|
|
38
|
+
- Use strong typing to prevent errors
|
|
39
|
+
- Handle errors gracefully
|
|
40
|
+
- Don't ignore caught errors
|
|
41
|
+
- Prefer early returns
|
|
42
|
+
- Use meaningful error messages
|
|
43
|
+
|
|
44
|
+
### 6. Code Organization
|
|
45
|
+
|
|
46
|
+
- Keep related code together
|
|
47
|
+
- Organize code by feature/module
|
|
48
|
+
- Maintain a clear and consistent project structure
|
|
49
|
+
|
|
50
|
+
### 7. Testing
|
|
51
|
+
|
|
52
|
+
- Write tests first (TDD)
|
|
53
|
+
- Write a failing test that defines the desired behavior
|
|
54
|
+
- Write the minimum code needed to make the test pass
|
|
55
|
+
- Refactor while keeping tests green
|
|
56
|
+
- No new code without corresponding tests
|
|
57
|
+
- Make tests readable
|
|
58
|
+
- Use descriptive test names that explain the behavior being tested
|
|
59
|
+
- Follow the AAA pattern (Arrange, Act, Assert)
|
|
60
|
+
- Keep test setup focused and minimal
|
|
61
|
+
- One assert per test
|
|
62
|
+
- Each test should verify one specific behavior
|
|
63
|
+
- Use separate tests for different conditions
|
|
64
|
+
- Avoid testing multiple things in one test case
|
|
65
|
+
- Keep tests fast and independent
|
|
66
|
+
- No dependencies between tests
|
|
67
|
+
- Clean up test data after each test
|
|
68
|
+
- Mock external dependencies appropriately
|
|
69
|
+
- Tests should be able to run in any order
|
|
70
|
+
- Test Coverage
|
|
71
|
+
- Aim for high test coverage in business logic
|
|
72
|
+
- Unit test all public APIs
|
|
73
|
+
- Include edge cases and error conditions
|
|
74
|
+
- Write integration tests for critical paths
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: '**/*.{ts,mts,tsx}'
|
|
3
|
+
description: 'Orchestrate the steps of a flow in parallel at the call site, and pass shared data through the constructor or class members.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## **✅ Keep methods independent of each other**
|
|
7
|
+
|
|
8
|
+
Orchestrate every step of a flow from one method, so each step can change or be removed without touching the others. Methods are coupled when a change in one forces changes in the others.
|
|
9
|
+
|
|
10
|
+
❌ **Counter-example** — each method calls the next and threads the same parameter, so removing `findLastChapter()` would also force a change in `openBook()`:
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
export class ReaderService {
|
|
14
|
+
|
|
15
|
+
// this is where my journey through middle earth begins
|
|
16
|
+
read(isbn: number) {
|
|
17
|
+
// some extra logic
|
|
18
|
+
this.openBook(isbn);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
openBook(isbn: number) {
|
|
22
|
+
// some extra logic
|
|
23
|
+
this.findLastChapter(isbn);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
findLastChapter(isbn: number) {
|
|
27
|
+
// some extra logic
|
|
28
|
+
this.findLastPage(isbn);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
findLastPage(isbn: number) {
|
|
32
|
+
// some extra logic
|
|
33
|
+
this.startReading(isbn);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
startReading(isbn: number) {
|
|
37
|
+
// some extra logic
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## **✅ Call the steps in parallel**
|
|
43
|
+
|
|
44
|
+
Call every step from the orchestrating method, so the complete flow is visible in one place and each step stays independently testable.
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
export class ReadBookService {
|
|
48
|
+
|
|
49
|
+
// the isbn is passed from another service/component/controller/...
|
|
50
|
+
read(isbn: number) {
|
|
51
|
+
// Now I can see the complete feature in one place 🥳
|
|
52
|
+
// There is no coupling any more between functions.
|
|
53
|
+
this.openBook(isbn);
|
|
54
|
+
this.findLastChapter(isbn);
|
|
55
|
+
this.findLastPage(isbn);
|
|
56
|
+
this.startReading(isbn);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private openBook(isbn: number) {
|
|
60
|
+
// some logic
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private findLastChapter(isbn: number) {
|
|
64
|
+
// some logic
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private findLastPage(isbn: number) {
|
|
68
|
+
// some logic
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private startReading(isbn: number) {
|
|
72
|
+
// some logic
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## **✅ Reduce repeated arguments with class members**
|
|
78
|
+
|
|
79
|
+
Inject shared data once through the constructor — or a lifecycle hook such as Angular's `OnInit` — and read it from the class member in every method that needs it.
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
export class ReadBookService {
|
|
83
|
+
|
|
84
|
+
constructor(private isbn: number) {}
|
|
85
|
+
|
|
86
|
+
read() {
|
|
87
|
+
// No params passed
|
|
88
|
+
this.openBook();
|
|
89
|
+
this.findLastChapter();
|
|
90
|
+
this.findLastPage();
|
|
91
|
+
this.startReading();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private openBook() {
|
|
95
|
+
// use class member
|
|
96
|
+
console.log(this.isbn);
|
|
97
|
+
}
|
|
98
|
+
// findLastChapter(), findLastPage(), startReading() follow the same shape
|
|
99
|
+
}
|
|
100
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: '**/*.{html,css,ts,tsx,js,jsx}'
|
|
3
|
+
description: 'When creating new features, resolve the needed logic in this order: HTML first, then HTML & CSS, and only then JavaScript/TypeScript.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## HTML > CSS > JS
|
|
7
|
+
|
|
8
|
+
When building new UI features, prefer the simplest technology that solves the problem. Follow this priority order:
|
|
9
|
+
|
|
10
|
+
### 1. HTML only
|
|
11
|
+
|
|
12
|
+
- Use native HTML elements and attributes to achieve the desired behavior
|
|
13
|
+
- Examples: `<details>`/`<summary>` for expand/collapse, `<dialog>` for modals, form validation attributes (`required`, `pattern`, `min`, `max`), the `popover` attribute, `contenteditable`
|
|
14
|
+
- If a native HTML feature solves the problem, use it — no CSS or JS needed
|
|
15
|
+
|
|
16
|
+
### 2. HTML + CSS
|
|
17
|
+
|
|
18
|
+
- If HTML alone is not sufficient, add CSS before reaching for JavaScript
|
|
19
|
+
- Examples: `:hover`/`:focus`/`:focus-within` for interactivity, CSS transitions and animations, `position: sticky`, CSS Grid/Flexbox for layout, `@media` queries for responsive behavior, `scroll-behavior: smooth`, `:target` for tab-like behavior without JS
|
|
20
|
+
- Prefer a CSS-only solution over a JS-driven one whenever it is equally maintainable
|
|
21
|
+
|
|
22
|
+
### 3. JavaScript / TypeScript
|
|
23
|
+
|
|
24
|
+
- Only add JS/TS when neither HTML nor CSS can achieve the required behavior
|
|
25
|
+
- Examples: fetching data, complex state management, real-time updates, browser APIs not covered by HTML/CSS
|
|
26
|
+
- Keep the JS layer as thin as possible — use it to enhance, not to replace, what HTML and CSS can already do
|
|
27
|
+
|
|
28
|
+
### Why this order
|
|
29
|
+
|
|
30
|
+
- HTML and CSS are more accessible, performant, and resilient than JS — they work without JavaScript enabled, parse faster, and degrade gracefully
|
|
31
|
+
- Less JavaScript means less to load, less to maintain, and fewer bugs
|
|
32
|
+
- Progressive enhancement: start with a working baseline and layer on complexity only when needed
|