@ethlete/agent-rules 0.1.0-next.0 → 0.1.0-next.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +102 -0
- package/README.md +363 -16
- package/content/git-hooks/post-checkout.sh +10 -0
- package/content/git-hooks/pre-push.sh +5 -0
- package/content/hooks/context-warning.py +430 -0
- package/content/output-styles/ste-clarity.md +131 -0
- package/content/rules/comments.md +50 -20
- package/content/skills/angular-patterns/SKILL.md +1 -1
- package/content/skills/api-source/SKILL.md +118 -0
- package/content/skills/figma-export/SKILL.md +193 -0
- package/content/skills/figma-export/dump-figma-layers.py +83 -0
- package/content/skills/figma-export/dump-figma-svg.py +235 -0
- package/content/skills/figma-export/measure-template.mjs +87 -0
- package/content/skills/git-commit/SKILL.md +6 -7
- package/content/skills/git-flow/SKILL.md +87 -0
- package/content/skills/handoff/SKILL.md +4 -0
- package/content/skills/query/SKILL.md +23 -13
- package/content/skills/rxjs-signals/SKILL.md +1 -1
- package/content/skills/sdk-docs/SKILL.md +10 -2
- package/content/skills/sdk-local-build/SKILL.md +115 -0
- package/content/skills/sdk-source/SKILL.md +133 -0
- package/content/skills/styleguide/STYLEGUIDE.md +2 -2
- package/content/skills/theming/SKILL.md +1 -1
- package/content/skills/timetrack/SKILL.md +66 -0
- package/package.json +12 -1
- package/src/index.js +35 -14
- package/src/index.js.map +1 -1
- 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 +64 -2
- package/src/lib/config.js +54 -9
- package/src/lib/config.js.map +1 -1
- package/src/lib/git-flow/build.d.ts +35 -0
- package/src/lib/git-flow/build.js +24 -0
- package/src/lib/git-flow/build.js.map +1 -0
- package/src/lib/git-flow/config.d.ts +59 -0
- package/src/lib/git-flow/config.js +50 -0
- package/src/lib/git-flow/config.js.map +1 -0
- package/src/lib/git-flow/index.d.ts +6 -0
- package/src/lib/git-flow/index.js +10 -0
- package/src/lib/git-flow/index.js.map +1 -0
- package/src/lib/git-flow/parse.d.ts +49 -0
- package/src/lib/git-flow/parse.js +274 -0
- package/src/lib/git-flow/parse.js.map +1 -0
- package/src/lib/git-flow/rename.d.ts +24 -0
- package/src/lib/git-flow/rename.js +70 -0
- package/src/lib/git-flow/rename.js.map +1 -0
- package/src/lib/git-flow/start.d.ts +49 -0
- package/src/lib/git-flow/start.js +57 -0
- package/src/lib/git-flow/start.js.map +1 -0
- package/src/lib/git-flow/validate.d.ts +34 -0
- package/src/lib/git-flow/validate.js +72 -0
- package/src/lib/git-flow/validate.js.map +1 -0
- package/src/lib/git-flow-command.d.ts +4 -0
- package/src/lib/git-flow-command.js +157 -0
- package/src/lib/git-flow-command.js.map +1 -0
- package/src/lib/git-flow-repair.d.ts +17 -0
- package/src/lib/git-flow-repair.js +146 -0
- package/src/lib/git-flow-repair.js.map +1 -0
- package/src/lib/git-flow-start.d.ts +20 -0
- package/src/lib/git-flow-start.js +132 -0
- package/src/lib/git-flow-start.js.map +1 -0
- package/src/lib/git.d.ts +27 -0
- package/src/lib/git.js +49 -0
- package/src/lib/git.js.map +1 -0
- package/src/lib/gitlab.d.ts +35 -0
- package/src/lib/gitlab.js +98 -0
- package/src/lib/gitlab.js.map +1 -0
- package/src/lib/index.d.ts +2 -0
- package/src/lib/index.js +2 -0
- package/src/lib/index.js.map +1 -1
- package/src/lib/migrate.d.ts +6 -0
- package/src/lib/migrate.js +155 -0
- package/src/lib/migrate.js.map +1 -0
- 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 +126 -0
- package/src/lib/output-style.js.map +1 -0
- package/src/lib/owned-paths.js +22 -1
- package/src/lib/owned-paths.js.map +1 -1
- package/src/lib/plan.d.ts +4 -1
- package/src/lib/plan.js +141 -8
- package/src/lib/plan.js.map +1 -1
- package/src/lib/prompt.d.ts +8 -0
- package/src/lib/prompt.js +27 -0
- package/src/lib/prompt.js.map +1 -0
- package/src/lib/render.d.ts +20 -2
- package/src/lib/render.js +31 -8
- package/src/lib/render.js.map +1 -1
- package/src/lib/sync.d.ts +0 -1
- package/src/lib/sync.js +8 -2
- package/src/lib/sync.js.map +1 -1
- package/src/lib/targets/agents-skills.d.ts +8 -0
- package/src/lib/targets/agents-skills.js +18 -0
- package/src/lib/targets/agents-skills.js.map +1 -0
- package/src/lib/targets/claude-hooks.d.ts +11 -0
- package/src/lib/targets/claude-hooks.js +28 -0
- package/src/lib/targets/claude-hooks.js.map +1 -0
- package/src/lib/targets/claude.d.ts +3 -1
- package/src/lib/targets/claude.js +14 -21
- 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 +33 -0
- package/src/lib/targets/codex-hooks.js.map +1 -0
- package/src/lib/targets/codex.d.ts +5 -3
- package/src/lib/targets/codex.js +9 -8
- package/src/lib/targets/codex.js.map +1 -1
- package/src/lib/targets/copilot.d.ts +3 -3
- package/src/lib/targets/copilot.js +6 -29
- package/src/lib/targets/copilot.js.map +1 -1
- package/src/lib/targets/cursor.d.ts +3 -3
- package/src/lib/targets/cursor.js +7 -12
- package/src/lib/targets/cursor.js.map +1 -1
- package/src/lib/targets/git-hooks.d.ts +24 -0
- package/src/lib/targets/git-hooks.js +70 -0
- package/src/lib/targets/git-hooks.js.map +1 -0
- package/src/lib/targets/hooks-shared.d.ts +37 -0
- package/src/lib/targets/hooks-shared.js +95 -0
- package/src/lib/targets/hooks-shared.js.map +1 -0
- package/src/lib/targets/shared.d.ts +22 -13
- package/src/lib/targets/shared.js +32 -15
- package/src/lib/targets/shared.js.map +1 -1
- package/src/lib/timetrack-command.d.ts +11 -0
- package/src/lib/timetrack-command.js +199 -0
- package/src/lib/timetrack-command.js.map +1 -0
- package/src/lib/timetrack.d.ts +86 -0
- package/src/lib/timetrack.js +112 -0
- package/src/lib/timetrack.js.map +1 -0
- package/src/lib/targets/neutral.d.ts +0 -8
- package/src/lib/targets/neutral.js +0 -29
- package/src/lib/targets/neutral.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,107 @@
|
|
|
1
1
|
# @ethlete/agent-rules
|
|
2
2
|
|
|
3
|
+
## 0.1.0-next.10
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#3067](https://github.com/ethlete-io/ethdk/pull/3067) [`226fd3d`](https://github.com/ethlete-io/ethdk/commit/226fd3d0b52f1a131ccbaa417ffe96682752d3f8) Thanks [@github-actions](https://github.com/apps/github-actions)! - New `ethlete-agents output-style` command: it installs the `ste-clarity` ASD-STE100 output style into Claude Code's user config and switches to it. Claude Code only.
|
|
8
|
+
|
|
9
|
+
- [#3067](https://github.com/ethlete-io/ethdk/pull/3067) [`3657156`](https://github.com/ethlete-io/ethdk/commit/36571560c755468459a87da9d9ec5764d976ee96) Thanks [@github-actions](https://github.com/apps/github-actions)! - `ethlete-agents timetrack instance` reports the Jira instance's own levels and the custom fields a
|
|
10
|
+
branch subject could go in, so a setup step reads the answer instead of guessing it.
|
|
11
|
+
|
|
12
|
+
## 0.1.0-next.9
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- [`ae165cc`](https://github.com/ethlete-io/ethdk/commit/ae165cc4123e3f2abaa88c5cfd8262b13aac81d1) Thanks [@TomTomB](https://github.com/TomTomB)! - New `api-source` skill reads the API repo of the app you are in, from the local config's new `apiRepoPaths` map (`{ "hub": "../fut-hub-backend" }`).
|
|
17
|
+
|
|
18
|
+
- [`f132d0b`](https://github.com/ethlete-io/ethdk/commit/f132d0b64e322c5823c9f50adeedecf388c5aa65) Thanks [@TomTomB](https://github.com/TomTomB)! - `ethlete-agents timetrack` reaches Jira through the running Timetrack app, so no repository holds a
|
|
19
|
+
token any more — the `jira` credentials in the local config and the `JIRA_*` variables are gone.
|
|
20
|
+
|
|
21
|
+
- [#3066](https://github.com/ethlete-io/ethdk/pull/3066) [`fef4586`](https://github.com/ethlete-io/ethdk/commit/fef45868b10b0a0f01efff741958d65d9e405a31) Thanks [@github-actions](https://github.com/apps/github-actions)! - `git-flow`: add `conformingNameFor()`, which names what a non-conforming branch should be renamed to, and `git-flow repair` now handles a keyless branch it previously refused.
|
|
22
|
+
|
|
23
|
+
- [#3066](https://github.com/ethlete-io/ethdk/pull/3066) [`fef4586`](https://github.com/ethlete-io/ethdk/commit/fef45868b10b0a0f01efff741958d65d9e405a31) Thanks [@github-actions](https://github.com/apps/github-actions)! - `git-flow`: export `featureBranchesFor()` and `nestedSpecFor()`, so a host can plan a nested branch without running the CLI.
|
|
24
|
+
|
|
25
|
+
## 0.1.0-next.8
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- [#3058](https://github.com/ethlete-io/ethdk/pull/3058) [`7074ffc`](https://github.com/ethlete-io/ethdk/commit/7074ffcb99812faed82a4e32fa3f8a1a43fcaf9d) Thanks [@github-actions](https://github.com/apps/github-actions)! - The `sdk-docs` skill points agents at the docs site's `llms.txt` index and the `.md` suffix on any page URL, so a page can be found and read without guessing a URL from the hardcoded domain list.
|
|
30
|
+
|
|
31
|
+
- [#3058](https://github.com/ethlete-io/ethdk/pull/3058) [`86fce5b`](https://github.com/ethlete-io/ethdk/commit/86fce5b87770ef4d5b069e59fec745eae93fda7b) Thanks [@github-actions](https://github.com/apps/github-actions)! - The `sdk-source` skill points at `apps/storybook/`, the SDK repo's renamed Storybook host.
|
|
32
|
+
|
|
33
|
+
## 0.1.0-next.7
|
|
34
|
+
|
|
35
|
+
### Minor Changes
|
|
36
|
+
|
|
37
|
+
- [#3056](https://github.com/ethlete-io/ethdk/pull/3056) [`8aec5ff`](https://github.com/ethlete-io/ethdk/commit/8aec5ff1a3ea6dd459d0e00bc691468019dcaca6) Thanks [@github-actions](https://github.com/apps/github-actions)! - Generated files no longer stamp the package version into their banner, so a release bump alone no longer reports every repo as out of sync - only real content changes do.
|
|
38
|
+
|
|
39
|
+
### Patch Changes
|
|
40
|
+
|
|
41
|
+
- [#3056](https://github.com/ethlete-io/ethdk/pull/3056) [`b5f72d6`](https://github.com/ethlete-io/ethdk/commit/b5f72d6bf35dd0e49cf14588b651012fb5d6a7c5) Thanks [@github-actions](https://github.com/apps/github-actions)! - The git-commit guide now presents its format as the repo's own convention unless a commitlint config is actually there, instead of pointing every repo at a `commitlint.config.js` it may not have.
|
|
42
|
+
|
|
43
|
+
## 0.1.0-next.6
|
|
44
|
+
|
|
45
|
+
### Minor Changes
|
|
46
|
+
|
|
47
|
+
- [#3055](https://github.com/ethlete-io/ethdk/pull/3055) [`86cd6e9`](https://github.com/ethlete-io/ethdk/commit/86cd6e97072d38436650ddc94a15527da34fa946) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add the git-flow branch convention: a `git-flow` skill, `ethlete-agents git-flow start|check|repair|explain`, opt-in git hooks, and the parser at `@ethlete/agent-rules/git-flow`.
|
|
48
|
+
|
|
49
|
+
### Patch Changes
|
|
50
|
+
|
|
51
|
+
- [#3055](https://github.com/ethlete-io/ethdk/pull/3055) [`01b0797`](https://github.com/ethlete-io/ethdk/commit/01b0797d80df17e740419402034bc3eec739daaf) Thanks [@github-actions](https://github.com/apps/github-actions)! - The context-warning hook now points at `/ethlete-handoff`, the name the generated skill actually has, instead of a `/handoff` command that does not exist in a consumer repo.
|
|
52
|
+
|
|
53
|
+
## 0.1.0-next.5
|
|
54
|
+
|
|
55
|
+
### Minor Changes
|
|
56
|
+
|
|
57
|
+
- [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`6e19999`](https://github.com/ethlete-io/ethdk/commit/6e199997f51b88aaa1860a56a6b96be057ba1205) Thanks [@github-actions](https://github.com/apps/github-actions)! - The `context-warning` hook now runs under Codex as well as Claude Code, registered in
|
|
58
|
+
`.codex/hooks.json` whenever the `codex` target is on.
|
|
59
|
+
|
|
60
|
+
- [#3049](https://github.com/ethlete-io/ethdk/pull/3049) [`a606dda`](https://github.com/ethlete-io/ethdk/commit/a606dda0695ac8cc4370816bf3ff1c0814436091) Thanks [@TomTomB](https://github.com/TomTomB)! - Add the `figma-export` skill, guiding agents through reconciling a component against a Figma "copy as CSS" export.
|
|
61
|
+
|
|
62
|
+
### Patch Changes
|
|
63
|
+
|
|
64
|
+
- [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`fc56189`](https://github.com/ethlete-io/ethdk/commit/fc56189450a45f2b5819d40945a71205a6d67ba0) Thanks [@github-actions](https://github.com/apps/github-actions)! - The `query` skill now says to prefer `withArgs` over passing `args` to `execute()`, and when the imperative form is still right.
|
|
65
|
+
|
|
66
|
+
- [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`a16cc69`](https://github.com/ethlete-io/ethdk/commit/a16cc698a3cd3f14d0419d8f9710929fb41b4711) Thanks [@github-actions](https://github.com/apps/github-actions)! - Figma export skill: read an SVG frame as well as the CSS dump, with a `dump-figma-svg.py`
|
|
67
|
+
that prints its box tree and measures the auto-layout gaps.
|
|
68
|
+
|
|
69
|
+
## 0.1.0-next.4
|
|
70
|
+
|
|
71
|
+
### Minor Changes
|
|
72
|
+
|
|
73
|
+
- [#3045](https://github.com/ethlete-io/ethdk/pull/3045) [`fcd14f0`](https://github.com/ethlete-io/ethdk/commit/fcd14f09b4b09f81b5bde9f128a0fac4b0e2245c) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add `disableAutoHandoffSave` to `ethlete-agents.config.local.json`, to opt out of the context-warning hook's auto-mode auto-save at the critical tier while keeping its normal warnings.
|
|
74
|
+
|
|
75
|
+
### Patch Changes
|
|
76
|
+
|
|
77
|
+
- [#3045](https://github.com/ethlete-io/ethdk/pull/3045) [`eb1b0a9`](https://github.com/ethlete-io/ethdk/commit/eb1b0a9cfb4e868b13a2b8eb6fd13221a6e0a654) Thanks [@github-actions](https://github.com/apps/github-actions)! - `context-warning` hook: in auto mode, the critical-tier warning now saves a `/handoff` immediately instead of just recommending it.
|
|
78
|
+
|
|
79
|
+
## 0.1.0-next.3
|
|
80
|
+
|
|
81
|
+
### Patch Changes
|
|
82
|
+
|
|
83
|
+
- [`ca0bf2f`](https://github.com/ethlete-io/ethdk/commit/ca0bf2f09cd5bd925da52bdb17c93bb62bda8735) Thanks [@TomTomB](https://github.com/TomTomB)! - The `comments` rule is now an allowlist: four kinds of comment are allowed and everything else gets deleted.
|
|
84
|
+
|
|
85
|
+
## 0.1.0-next.2
|
|
86
|
+
|
|
87
|
+
### Minor Changes
|
|
88
|
+
|
|
89
|
+
- [#3043](https://github.com/ethlete-io/ethdk/pull/3043) [`a311f80`](https://github.com/ethlete-io/ethdk/commit/a311f80455bc9cc9a925fe8f72ac945a1b057315) Thanks [@github-actions](https://github.com/apps/github-actions)! - New `sdk-source` and `sdk-local-build` skills let an agent read the SDK's own sources and test an unreleased build via `file:`, from the checkout named by the local config's new `sdkSourcePath`.
|
|
90
|
+
|
|
91
|
+
### Patch Changes
|
|
92
|
+
|
|
93
|
+
- [#3043](https://github.com/ethlete-io/ethdk/pull/3043) [`9627646`](https://github.com/ethlete-io/ethdk/commit/96276462e1c2ecde5394b8b1eafcebbb9f56a973) Thanks [@github-actions](https://github.com/apps/github-actions)! - Styleguide: changeset notes are now capped at one to two sentences, with mechanism and API inventories
|
|
94
|
+
explicitly sent to the docs instead.
|
|
95
|
+
|
|
96
|
+
## 0.1.0-next.1
|
|
97
|
+
|
|
98
|
+
### Minor Changes
|
|
99
|
+
|
|
100
|
+
- [#3042](https://github.com/ethlete-io/ethdk/pull/3042) [`28a58eb`](https://github.com/ethlete-io/ethdk/commit/28a58ebc56420b7e067d8c56108b39601d7b367e) Thanks [@github-actions](https://github.com/apps/github-actions)! - - Skills now compile to the cross-tool `.agents/skills/ethlete-*/SKILL.md` format, discovered natively by Codex, Cursor and Copilot; the `.agents/ethlete/` pointer tree is pruned on sync.
|
|
101
|
+
- New `ethlete-agents migrate` converts a repo to the `AGENTS.md`-canonical layout: `CLAUDE.md` becomes an `@AGENTS.md` import and hand-written skills move to `.agents/skills` with symlinks.
|
|
102
|
+
- New opt-in `hooks` config: `context-warning` warns (and instructs Claude) before the context crosses the 200k long-context pricing boundary, recommending `/handoff`.
|
|
103
|
+
- A gitignored `ethlete-agents.config.local.json` (`"disableHooks": true` or a list of hook names) disables generated hooks per machine at runtime — committed files never change, and `sync`/`check` warn about unsupported keys or unknown hook names in it.
|
|
104
|
+
|
|
3
105
|
## 0.1.0-next.0
|
|
4
106
|
|
|
5
107
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -23,17 +23,44 @@ npx ethlete-agents check # exits non-zero when the generated files are stale
|
|
|
23
23
|
|
|
24
24
|
## What gets written
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
`.github/copilot-instructions.md`
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
Skills are compiled once into `.agents/skills/ethlete-*/SKILL.md` - the cross-tool
|
|
27
|
+
[Agent Skills](https://agentskills.io) format that Codex, Cursor, Copilot and VS Code
|
|
28
|
+
discover natively (each skill's body loads on demand from its `description`
|
|
29
|
+
frontmatter). Claude Code only scans `.claude/skills/`, so the claude target writes its
|
|
30
|
+
own copies there. Rules are always-loaded and go into each tool's native mechanism:
|
|
31
|
+
|
|
32
|
+
| | Claude Code | Cursor | Copilot | Codex |
|
|
33
|
+
| ------------------- | ----------------------------------- | --------------------------------------------------- | ---------------------------------------------- | ----------------------------------- |
|
|
34
|
+
| Always-loaded rules | `.claude/rules/ethlete/*.md` | `.cursor/rules/ethlete-*.mdc` (`alwaysApply: true`) | inlined into `.github/copilot-instructions.md` | inlined into `AGENTS.md` |
|
|
35
|
+
| On-demand skills | `.claude/skills/ethlete-*/SKILL.md` | `.agents/skills/ethlete-*/SKILL.md` | `.agents/skills/ethlete-*/SKILL.md` | `.agents/skills/ethlete-*/SKILL.md` |
|
|
36
|
+
|
|
37
|
+
Marker-block files (`AGENTS.md`, `.github/copilot-instructions.md`) are only rewritten
|
|
38
|
+
between `<!-- ethlete:agent-rules:start -->` and `:end` - everything you wrote around
|
|
39
|
+
them survives.
|
|
40
|
+
|
|
41
|
+
## Migrating a repo to the AGENTS.md layout
|
|
42
|
+
|
|
43
|
+
`AGENTS.md` is the cross-tool standard, and Claude Code officially supports reading it
|
|
44
|
+
through a one-line `CLAUDE.md` import. To restructure a whole repo around that:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx ethlete-agents migrate --dry-run # prints the plan
|
|
48
|
+
npx ethlete-agents migrate
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
- `CLAUDE.md` content moves to the top of `AGENTS.md`; `CLAUDE.md` becomes `@AGENTS.md`.
|
|
52
|
+
- Hand-written `.claude/skills/<name>` directories move to `.agents/skills/<name>`, with
|
|
53
|
+
a symlink left behind so Claude Code still finds them. (Symlinks need Developer Mode
|
|
54
|
+
on Windows checkouts.)
|
|
55
|
+
- A short layout note is added to `AGENTS.md` so agents know the symlinked skills are
|
|
56
|
+
the same files, not duplicates - skipped if your `AGENTS.md` already explains it.
|
|
57
|
+
- The config gains the `codex` target and `claudeMdImportsAgentsMd: true`, which stops
|
|
58
|
+
the claude target from writing `.claude/rules/ethlete/` - the rules already reach
|
|
59
|
+
Claude through the `AGENTS.md` marker block, and a second copy would load twice.
|
|
60
|
+
- A `sync` runs, which also prunes output from older layouts (`.agents/ethlete/`,
|
|
61
|
+
`.github/instructions/ethlete-*`).
|
|
62
|
+
|
|
63
|
+
The command is idempotent - every step detects the migrated state and skips itself.
|
|
37
64
|
|
|
38
65
|
Every generated file carries a `DO NOT EDIT` banner. Files that disappear from the
|
|
39
66
|
package are pruned on the next `sync`; nothing outside an `ethlete` directory or an
|
|
@@ -47,7 +74,6 @@ Prettier rewrites them and `check` then reports drift on every run:
|
|
|
47
74
|
/.claude
|
|
48
75
|
/.agents
|
|
49
76
|
/.cursor/rules/ethlete-*
|
|
50
|
-
/.github/instructions/ethlete-*
|
|
51
77
|
```
|
|
52
78
|
|
|
53
79
|
## Configuration
|
|
@@ -69,19 +95,335 @@ Prettier rewrites them and `check` then reports drift on every run:
|
|
|
69
95
|
}
|
|
70
96
|
```
|
|
71
97
|
|
|
72
|
-
- **`targets`** - `"auto"` (default) emits
|
|
73
|
-
|
|
98
|
+
- **`targets`** - `"auto"` (default) always emits `codex` (`AGENTS.md` plus
|
|
99
|
+
`.agents/skills/` is the cross-tool baseline) and adds `claude`, `cursor` or `copilot`
|
|
100
|
+
when their directory exists; or list an explicit subset.
|
|
74
101
|
- **`profile`** - `"consumer"` (default) emits `scope: consumer` and `scope: both`
|
|
75
102
|
content. `"sdk"` emits only `both`; the SDK repo uses it so its own hand-written,
|
|
76
103
|
authoring-side guides are not overwritten by the consumer-side versions.
|
|
77
104
|
- **`vars`** - values for the template tokens a guide declares. Defaults live in
|
|
78
105
|
`content/defaults.json`; a guide whose variable has no default and no value is
|
|
79
|
-
skipped with a warning rather than emitted with a dangling placeholder.
|
|
106
|
+
skipped with a warning rather than emitted with a dangling placeholder. Some are
|
|
107
|
+
derived from the repo instead of defaulted - the `gitFlow*` ones from the `gitFlow`
|
|
108
|
+
block, and `commitRuleSource` / `commitValidation` from whether a commitlint config
|
|
109
|
+
exists (`commitlint.config.*`, `.commitlintrc*`, or a `commitlint` key in
|
|
110
|
+
`package.json`). Without one, the git-commit guide presents the format as the repo's
|
|
111
|
+
convention and never mentions a `commitlint` run - an agent that goes looking for a
|
|
112
|
+
promised validator and finds nothing reports the discrepancy instead of just
|
|
113
|
+
committing. Setting either one in `vars` overrides the detection.
|
|
80
114
|
- **`exclude`** - content names to skip entirely.
|
|
115
|
+
- **`claudeMdImportsAgentsMd`** - set (usually by `migrate`) when `CLAUDE.md` is an
|
|
116
|
+
`@AGENTS.md` import or symlink; the claude target then skips `.claude/rules/ethlete/`
|
|
117
|
+
so the rules don't load twice. `sync` warns when the flag is set but the import is
|
|
118
|
+
missing.
|
|
81
119
|
|
|
82
120
|
Content that declares `requires` is only emitted when those packages are installed, so
|
|
83
121
|
a repo without `@ethlete/query` never sees the query guide.
|
|
84
122
|
|
|
123
|
+
## Git flow
|
|
124
|
+
|
|
125
|
+
The branch convention lives in the same config, as one machine-readable grammar that the
|
|
126
|
+
CLI, a git hook, a CI job and `@ethlete/timetrack` all read:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"gitFlow": {
|
|
131
|
+
"keyPrefixes": ["FIP"],
|
|
132
|
+
"baseBranches": { "development": "next", "production": "main" }
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
npx ethlete-agents git-flow start FIP-2177 # name it and branch off the right base
|
|
139
|
+
npx ethlete-agents git-flow check # the current branch
|
|
140
|
+
npx ethlete-agents git-flow check "$SOURCE" --target "$TARGET"
|
|
141
|
+
npx ethlete-agents git-flow check --all # adoption report
|
|
142
|
+
npx ethlete-agents git-flow repair dev-game-codes --key FIP-2900
|
|
143
|
+
npx ethlete-agents git-flow explain feat/FIP-2177-user-management
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
The shapes:
|
|
147
|
+
|
|
148
|
+
| Shape | Branch from | Merges into |
|
|
149
|
+
| ------------------------------------------ | ----------------------- | ------------------------------ |
|
|
150
|
+
| `feat/<KEY>-<subject>` | development | development |
|
|
151
|
+
| `sub/feat/<KEY>-<subject>/<KEY>-<subject>` | the main feature branch | the main feature branch |
|
|
152
|
+
| `release/<YYYY.MM.DD>` | development | development **and** production |
|
|
153
|
+
| `sub/release/<YYYY.MM.DD>/<KEY>-<subject>` | the release branch | the release branch |
|
|
154
|
+
| `hotfix/<KEY>-<subject>` | production | production |
|
|
155
|
+
|
|
156
|
+
**Why nested branches carry a `sub/` prefix.** Git refuses a ref that is both a branch and
|
|
157
|
+
a directory of branches, so `feat/FIP-2177-user-management/FIP-2178-reset` cannot exist
|
|
158
|
+
while `feat/FIP-2177-user-management` does - the push is rejected with `refname conflict`.
|
|
159
|
+
The prefix moves the nested tree out of the way while keeping the parent's full path inside
|
|
160
|
+
the child's name, so the merge request target is still derivable from the name alone. The
|
|
161
|
+
unprefixed spelling still parses, reports why it cannot exist, and `repair` moves it.
|
|
162
|
+
Configurable as `subPrefix`.
|
|
163
|
+
|
|
164
|
+
- **`enforcement`** - `"advisory"` (default) reports everything and blocks nothing, so a
|
|
165
|
+
repo can adopt the convention before it gates on it. `"gated"` applies each rule's
|
|
166
|
+
`severity`. A direct push to a base branch is blocked in both modes, and
|
|
167
|
+
`wrong-mr-target` can be raised to `"error"` on its own without ending the naming
|
|
168
|
+
grace period.
|
|
169
|
+
- **`keyPrefixes`** - the project's issue prefixes. Leave it empty and anything shaped
|
|
170
|
+
like `keyPattern` counts, which reads `chore/angular-22` as issue `ANGULAR-22`.
|
|
171
|
+
- **`severity`** - per rule: `unknown-type`, `missing-key`, `key-case`,
|
|
172
|
+
`missing-subject`, `type-alias`, `deprecated-prefix`, `release-date`,
|
|
173
|
+
`wrong-mr-target`, `protected-push`.
|
|
174
|
+
- **`deprecatedShapes`** - legacy spellings that still classify correctly and only earn a
|
|
175
|
+
rename suggestion. `dev-*` ships as the old spelling of a main feature branch.
|
|
176
|
+
|
|
177
|
+
The grammar is also importable on its own - `@ethlete/agent-rules/git-flow` has no
|
|
178
|
+
dependencies and touches no Node built-ins, so it runs in a browser:
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
import { parseBranch, planStart, resolveGitFlowConfig } from '@ethlete/agent-rules/git-flow';
|
|
182
|
+
|
|
183
|
+
const { storyKey, taskKey, findings } = parseBranch({ branch, config: resolveGitFlowConfig() });
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### `start` - the prospective flow
|
|
187
|
+
|
|
188
|
+
`git-flow start <KEY>` reads the issue from Jira, computes the name from the grammar and
|
|
189
|
+
creates the branch off the correct base. It prints the plan first and asks before writing;
|
|
190
|
+
`--dry-run` stops after the plan and `--yes` skips the question. It refuses on a dirty
|
|
191
|
+
working tree, when the branch already exists, and when the base branch is nowhere to be
|
|
192
|
+
found.
|
|
193
|
+
|
|
194
|
+
A Task with a parent Story nests under that Story's feature branch, which therefore has to
|
|
195
|
+
exist already - `start` says so rather than inventing a parent. `--of <branch>` picks the
|
|
196
|
+
parent explicitly, `--hotfix` branches off production, `--release <date>` makes a release
|
|
197
|
+
branch, and `--subject <text>` skips Jira entirely.
|
|
198
|
+
|
|
199
|
+
The issue is read through the Timetrack app - see [Jira, through Timetrack](#jira-through-timetrack).
|
|
200
|
+
No repository holds a Jira credential, so the only thing the committed config still says about
|
|
201
|
+
Jira is how an issue type becomes a branch type:
|
|
202
|
+
|
|
203
|
+
```json
|
|
204
|
+
{
|
|
205
|
+
"jira": {
|
|
206
|
+
"typeByIssueType": { "Bug": "fix" }
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
- **`typeByIssueType`** - the branch type per Jira issue type; anything unlisted becomes
|
|
212
|
+
`feat`. `--type` overrides it per call.
|
|
213
|
+
|
|
214
|
+
The branch subject comes from the instance's own subject field, which Timetrack resolves
|
|
215
|
+
because the field id is a property of the instance rather than of this repo. An issue that
|
|
216
|
+
sets no subject falls back to its summary, and the printed plan says which of the two it used.
|
|
217
|
+
|
|
218
|
+
### `repair` - renaming a branch that does not conform
|
|
219
|
+
|
|
220
|
+
`git-flow repair [ref]` derives the conforming name (`--key FIP-2900` when the old name
|
|
221
|
+
carries no issue key, `--to <branch>` to override), renames the branch locally and on the
|
|
222
|
+
remote, and retargets the open merge requests aimed at it through the GitLab API.
|
|
223
|
+
`GITLAB_TOKEN` needs the `api` scope.
|
|
224
|
+
|
|
225
|
+
Everything is checked before the first mutation, and it refuses rather than half-finishing:
|
|
226
|
+
|
|
227
|
+
- An open merge request whose **source** is the branch blocks the repair. GitLab cannot
|
|
228
|
+
move a merge request to another source branch, and closing it would lose its discussion -
|
|
229
|
+
merge or close it first.
|
|
230
|
+
- A branch that is pushed but whose merge requests cannot be listed (no token, or a remote
|
|
231
|
+
that is not GitLab) blocks too. `--no-mr-check` asserts that none point at it.
|
|
232
|
+
- If a retarget fails halfway, the old branch is still there and the recovery commands are
|
|
233
|
+
printed.
|
|
234
|
+
|
|
235
|
+
## Jira, through Timetrack
|
|
236
|
+
|
|
237
|
+
A Jira token in every repository is a secret nobody can rotate. There is one on this machine
|
|
238
|
+
instead, in the Timetrack app's keychain entry, and every repository asks the running app:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
npx ethlete-agents timetrack status # is it reachable, and what does it hold?
|
|
242
|
+
npx ethlete-agents timetrack issue FIP-2177 # summary, type, parent, branch subject
|
|
243
|
+
npx ethlete-agents timetrack search "password" # open issues of the picked projects
|
|
244
|
+
npx ethlete-agents timetrack project # which project does this repo log into?
|
|
245
|
+
npx ethlete-agents timetrack create --summary "…" # file a ticket with the instance's settings
|
|
246
|
+
npx ethlete-agents timetrack log --issue FIP-2177 --minutes 45
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
`--json` prints the raw answer instead of lines. `git-flow start` uses the same channel.
|
|
250
|
+
|
|
251
|
+
**How it connects.** The app binds a loopback socket and writes its port and a fresh token
|
|
252
|
+
into `agent.json` in its own data directory (`~/.local/share/io.ethlete.timetrack/` on Linux,
|
|
253
|
+
`~/Library/Application Support/…` on macOS, `%APPDATA%\…` on Windows), readable by its owner
|
|
254
|
+
alone. The token lives no longer than the run, so a caller left over from an earlier one is
|
|
255
|
+
refused rather than trusted, and a request carrying an `Origin` header is refused outright -
|
|
256
|
+
a page the user happens to have open must not reach Jira through a port it guessed.
|
|
257
|
+
`TIMETRACK_AGENT_DISCOVERY` names the file for a machine that keeps it elsewhere.
|
|
258
|
+
|
|
259
|
+
**What the app answers, not this package.** The instance, the credentials, the picked
|
|
260
|
+
projects, the subject field and the ticket shape are all settings there. That is what makes
|
|
261
|
+
`create` file a ticket indistinguishable from one the app filed, and it is why none of them
|
|
262
|
+
appear in a repo's config any more.
|
|
263
|
+
|
|
264
|
+
**`log` writes to the day, not to Tempo.** It adds the same row the app's own timeline draws
|
|
265
|
+
for work nothing observed, and the user reviews the day before syncing it. A worklog posted
|
|
266
|
+
behind the review would double-book against whatever the evidence already proposed for that
|
|
267
|
+
hour.
|
|
268
|
+
|
|
269
|
+
**When the app is not running** every command says so and exits non-zero. There is no
|
|
270
|
+
fallback to an environment variable on purpose - a fallback is how the per-repo secret comes
|
|
271
|
+
back.
|
|
272
|
+
|
|
273
|
+
## Hooks (opt-in)
|
|
274
|
+
|
|
275
|
+
Hooks run commands on the developer's machine, so none are emitted by default - opt in
|
|
276
|
+
per hook in the config:
|
|
277
|
+
|
|
278
|
+
```json
|
|
279
|
+
{
|
|
280
|
+
"hooks": ["context-warning"]
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
They are emitted for whichever of the `claude` and `codex` targets is enabled:
|
|
285
|
+
|
|
286
|
+
| Target | Script | Registered in |
|
|
287
|
+
| -------- | ------------------------ | ----------------------- |
|
|
288
|
+
| `claude` | `.claude/hooks/ethlete/` | `.claude/settings.json` |
|
|
289
|
+
| `codex` | `.codex/hooks/ethlete/` | `.codex/hooks.json` |
|
|
290
|
+
|
|
291
|
+
Your own entries in those files are left untouched; removing the name from `hooks`
|
|
292
|
+
unregisters and deletes the script again. Codex only loads project-local hooks once the
|
|
293
|
+
`.codex/` layer is trusted, and honours `[features] hooks = false`.
|
|
294
|
+
|
|
295
|
+
Available hooks:
|
|
296
|
+
|
|
297
|
+
- **`context-warning`** - warns once per tier (and instructs the agent) when the session
|
|
298
|
+
context crosses 70% / 85% of the token budget, recommending a handoff. Under Claude the
|
|
299
|
+
budget is capped at the 200k long-context pricing boundary: on 1M-window models every
|
|
300
|
+
request past 200k input tokens bills the whole context at a premium rate, so the
|
|
301
|
+
warnings fire at ~140k/~170k instead of deep into the expensive range. Codex has no
|
|
302
|
+
such boundary, so its budget is the model's own reported context window and the
|
|
303
|
+
warnings are pure occupancy.
|
|
304
|
+
|
|
305
|
+
Two things are Claude-only: the separate user-facing line (Codex documents only
|
|
306
|
+
`additionalContext`, so there the warning is folded into the text the model is told to
|
|
307
|
+
relay), and the auto-mode escalation that writes the handoff file unprompted - Codex's
|
|
308
|
+
`permission_mode` values are undocumented, so no value enables it.
|
|
309
|
+
|
|
310
|
+
Hooks can be turned off per machine - see the local config below.
|
|
311
|
+
|
|
312
|
+
## Git hooks (opt-in)
|
|
313
|
+
|
|
314
|
+
Separate from the agent hooks above, and opt-in for the same reason - a generated block
|
|
315
|
+
that can reject a push is a higher-stakes artifact than a markdown one:
|
|
316
|
+
|
|
317
|
+
```json
|
|
318
|
+
{
|
|
319
|
+
"gitHooks": ["pre-push", "post-checkout"]
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Each one is written as an `# ethlete:git-flow:start` … `end` block **appended** to your
|
|
324
|
+
`.husky/<name>`, so an existing hook there (a git-lfs hook, typically) keeps working and
|
|
325
|
+
keeps reading stdin first - which is why the block never reads stdin itself. Removing the
|
|
326
|
+
name from `gitHooks` takes the block back out and leaves the rest of the file alone.
|
|
327
|
+
|
|
328
|
+
- **`pre-push`** - runs `git-flow check --push` on the current branch. In `advisory` mode
|
|
329
|
+
only a direct push to a base branch can actually stop it.
|
|
330
|
+
- **`post-checkout`** - reports a non-conforming name on a branch that is on no remote yet,
|
|
331
|
+
which is the whole window in which renaming it is free.
|
|
332
|
+
|
|
333
|
+
Only `.husky/` is written, never `.git/hooks/`: the generated files are committed and CI's
|
|
334
|
+
`check` diffs them, so a hook outside the working tree could never be in sync. Without a
|
|
335
|
+
`.husky/` directory `sync` warns and writes nothing. The block calls
|
|
336
|
+
`node_modules/.bin/ethlete-agents` directly rather than through `npx`, so a repo where the
|
|
337
|
+
package is missing gets silence instead of a registry lookup that would fail the push.
|
|
338
|
+
`ETHLETE_GIT_FLOW_SKIP=1` silences both hooks on one machine.
|
|
339
|
+
|
|
340
|
+
## CI job
|
|
341
|
+
|
|
342
|
+
On GitLab, the merge request target is the half no local hook can see. The job needs no
|
|
343
|
+
configuration beyond the predefined variables:
|
|
344
|
+
|
|
345
|
+
```yaml
|
|
346
|
+
Git Flow:
|
|
347
|
+
stage: Checks
|
|
348
|
+
rules:
|
|
349
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
350
|
+
allow_failure: true
|
|
351
|
+
script:
|
|
352
|
+
- >
|
|
353
|
+
npx ethlete-agents git-flow check "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME"
|
|
354
|
+
--target "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
`allow_failure: true` on top of `advisory` mode is deliberate belt and braces: the job
|
|
358
|
+
reports for a whole grace period before it can ever be the reason a merge request is red.
|
|
359
|
+
|
|
360
|
+
## Output styles (Claude Code)
|
|
361
|
+
|
|
362
|
+
An output style replaces Claude Code's own answer style for a whole session. This package
|
|
363
|
+
ships one - **`ste-clarity`**, which writes every answer in ASD-STE100 Simplified Technical
|
|
364
|
+
English - and installs it into the machine's Claude config rather than into a repo, because
|
|
365
|
+
that is where Claude Code reads styles from:
|
|
366
|
+
|
|
367
|
+
```bash
|
|
368
|
+
npx ethlete-agents output-style # install ste-clarity and switch to it
|
|
369
|
+
npx ethlete-agents output-style --dry-run # print what would change
|
|
370
|
+
npx ethlete-agents output-style --remove # take it back out
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
Two files, both under `~/.claude` (or `$CLAUDE_CONFIG_DIR`, or `--config-dir <path>`):
|
|
374
|
+
|
|
375
|
+
| File | What changes |
|
|
376
|
+
| ------------------------------ | ------------------------------------------------------------------ |
|
|
377
|
+
| `output-styles/ste-clarity.md` | The style itself, written whole |
|
|
378
|
+
| `settings.json` | `"outputStyle": "ste-clarity"` - every other setting is left alone |
|
|
379
|
+
|
|
380
|
+
- **`--no-activate`** writes the style file but not the setting, so switching to it is then
|
|
381
|
+
`/output-style ste-clarity` inside a session.
|
|
382
|
+
- A style file this command did not write is never overwritten or deleted - it says so and
|
|
383
|
+
stops, and `--force` is the way through. A copy of the same style that differs only in
|
|
384
|
+
layout still counts as its own.
|
|
385
|
+
- Nothing here is repo-local, so `sync` and `check` neither write nor diff it. `--remove`
|
|
386
|
+
clears `outputStyle` only while it still points at that style.
|
|
387
|
+
|
|
388
|
+
**Claude Code only.** Codex has no output-style mechanism - everything it is told comes
|
|
389
|
+
from `AGENTS.md`, which `sync` already writes.
|
|
390
|
+
|
|
391
|
+
## Per-machine local config
|
|
392
|
+
|
|
393
|
+
A gitignored `ethlete-agents.config.local.json` at the repo root holds the values that
|
|
394
|
+
differ per developer, without touching any committed file:
|
|
395
|
+
|
|
396
|
+
```json
|
|
397
|
+
{
|
|
398
|
+
"disableHooks": true,
|
|
399
|
+
"sdkSourcePath": "/absolute/path/to/ethlete-sdk",
|
|
400
|
+
"apiRepoPaths": { "hub": "../fut-hub-backend" }
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
- **`disableHooks`** - `true` disables every generated hook; an array
|
|
405
|
+
(`["context-warning"]`) just the named ones. The hook scripts read the file at
|
|
406
|
+
runtime, so toggling takes effect on the next prompt - no `sync` needed.
|
|
407
|
+
- **`disableAutoHandoffSave`** - keeps the `context-warning` hook's tiered warnings but
|
|
408
|
+
drops the auto-mode escalation: at the critical tier it recommends `/ethlete-handoff`
|
|
409
|
+
instead of saving the handoff file itself.
|
|
410
|
+
- **`sdkSourcePath`** - a local `ethlete-sdk` checkout. The `sdk-source` and
|
|
411
|
+
`sdk-local-build` skills read it when the agent needs the SDK's own sources, or has to
|
|
412
|
+
build the SDK and install it here through a `file:` dependency. A relative path is
|
|
413
|
+
resolved from the repo root.
|
|
414
|
+
- **`apiRepoPaths`** - one checkout per app, keyed by the app's project name
|
|
415
|
+
(`{ "hub": "../fut-hub-backend" }`). The `api-source` skill reads it to confirm a
|
|
416
|
+
response shape, a status code or an enum in the API's own source instead of guessing it
|
|
417
|
+
from the client. Relative paths resolve from the repo root; a map with a single entry is
|
|
418
|
+
used for whatever app is in play.
|
|
419
|
+
|
|
420
|
+
Everything in this file is read at runtime, never by `sync`: the generated files stay
|
|
421
|
+
identical on every machine and in CI, which is what lets `check` diff them. That is also
|
|
422
|
+
why the file takes nothing beyond these keys - `sync`/`check` warn about unknown keys,
|
|
423
|
+
about an `sdkSourcePath` that is missing or is not an SDK checkout, and about an
|
|
424
|
+
`apiRepoPaths` entry that is not a directory. Add the filename to your repo's
|
|
425
|
+
`.gitignore`.
|
|
426
|
+
|
|
85
427
|
## Authoring content
|
|
86
428
|
|
|
87
429
|
`content/rules/<name>.md` for short, always-loaded rules; `content/skills/<name>/SKILL.md`
|
|
@@ -94,11 +436,16 @@ description: Read before writing any color, background or border CSS.
|
|
|
94
436
|
kind: skill # rule | skill
|
|
95
437
|
scope: consumer # consumer | sdk | both
|
|
96
438
|
requires: ['@ethlete/core'] # optional
|
|
97
|
-
paths: ['**/*.css'] # optional; becomes Claude `paths
|
|
439
|
+
paths: ['**/*.css'] # optional; becomes Claude `paths` and Cursor `globs` on rules
|
|
98
440
|
vars: [docsBaseUrl] # optional
|
|
99
441
|
---
|
|
100
442
|
```
|
|
101
443
|
|
|
444
|
+
`content/output-styles/<name>.md` is a third kind, and the only one this package does not
|
|
445
|
+
compile: it is a Claude Code output style verbatim, so its frontmatter is Claude's
|
|
446
|
+
(`name`, `description`, `keep-coding-instructions`) and `output-style` installs the file
|
|
447
|
+
as it is, apart from a marker line that records where it came from.
|
|
448
|
+
|
|
102
449
|
In a body, `{% varName %}` substitutes a variable, `{% skill:other-name %}` links to
|
|
103
450
|
another guide the way the current target expects, and `{% resource:file.mjs %}` links to
|
|
104
451
|
a bundled file. The delimiter is `{% … %}`, not `{{ … }}`, so Angular templates in
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
if [ "$3" = "1" ] && [ -z "$ETHLETE_GIT_FLOW_SKIP" ] && [ -x node_modules/.bin/ethlete-agents ]; then
|
|
2
|
+
ethlete_branch=$(git rev-parse --abbrev-ref HEAD)
|
|
3
|
+
|
|
4
|
+
# Only while the branch is on no remote: that is the whole window in which renaming it is free.
|
|
5
|
+
if [ -z "$(git for-each-ref --format='%(refname)' "refs/remotes/*/$ethlete_branch")" ]; then
|
|
6
|
+
node_modules/.bin/ethlete-agents git-flow check || true
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
unset ethlete_branch
|
|
10
|
+
fi
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Never `npx`: it reaches the registry when the package is absent, and a network error here would
|
|
2
|
+
# reject the push. A missing binary must make this block do nothing at all.
|
|
3
|
+
if [ -z "$ETHLETE_GIT_FLOW_SKIP" ] && [ -x node_modules/.bin/ethlete-agents ]; then
|
|
4
|
+
node_modules/.bin/ethlete-agents git-flow check --push || exit 1
|
|
5
|
+
fi
|