@evo-dev/evodev 0.0.1-alpha.6 → 0.0.1-alpha.8
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/dist/.claude-plugin/marketplace.json +2 -2
- package/dist/index.js +79 -5
- package/dist/plugins/evodev/.claude-plugin/plugin.json +1 -1
- package/dist/plugins/evodev/.codex-plugin/plugin.json +1 -1
- package/dist/plugins/evodev/hooks/hooks.ts +55 -2
- package/dist/plugins/evodev/package.json +1 -1
- package/package.json +2 -2
- package/dist/.agents/skills/evodev-release/SKILL.md +0 -183
- package/dist/.agents/skills/grilling/SKILL.md +0 -10
- package/dist/evodev +0 -11
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
"name": "EvoDev"
|
|
5
5
|
},
|
|
6
6
|
"description": "EvoDev Claude Code hook plugins for AI-assisted R&D workflows.",
|
|
7
|
-
"version": "0.0.1-alpha.
|
|
7
|
+
"version": "0.0.1-alpha.8",
|
|
8
8
|
"plugins": [
|
|
9
9
|
{
|
|
10
10
|
"name": "evodev",
|
|
11
11
|
"source": "./packages/plugin",
|
|
12
12
|
"description": "EvoDev hook integration for disciplined AI coding workflows.",
|
|
13
|
-
"version": "0.0.1-alpha.
|
|
13
|
+
"version": "0.0.1-alpha.8",
|
|
14
14
|
"author": {
|
|
15
15
|
"name": "EvoDev"
|
|
16
16
|
},
|
package/dist/index.js
CHANGED
|
@@ -9372,6 +9372,12 @@ var CODEX_STOP_EVENTS_WITHOUT_ADDITIONAL_CONTEXT = new Set([
|
|
|
9372
9372
|
"Stop",
|
|
9373
9373
|
"SubagentStop"
|
|
9374
9374
|
]);
|
|
9375
|
+
var COMPLETION_EVENTS_WITHOUT_DEVELOPMENT_DIAGNOSTICS = new Set([
|
|
9376
|
+
"Stop",
|
|
9377
|
+
"SubagentStop",
|
|
9378
|
+
"TaskCompleted",
|
|
9379
|
+
"TeammateIdle"
|
|
9380
|
+
]);
|
|
9375
9381
|
function createDefaultHookSettings() {
|
|
9376
9382
|
return {
|
|
9377
9383
|
enabled: true,
|
|
@@ -9552,6 +9558,11 @@ async function handleHookRuntime(input) {
|
|
|
9552
9558
|
summary: `Hook ${input.event.type} ignored because EvoDev hooks are disabled.`
|
|
9553
9559
|
};
|
|
9554
9560
|
}
|
|
9561
|
+
if (isActiveClaudeStopHook(input)) {
|
|
9562
|
+
return createRuntimeResult(input, null, {
|
|
9563
|
+
summary: `${input.event.type} re-entry allowed to complete without hook output.`
|
|
9564
|
+
});
|
|
9565
|
+
}
|
|
9555
9566
|
const diagnostics = await recordTeamNativeSessionFromHook(input);
|
|
9556
9567
|
const projectDiagnostics = await recordDiscoveredProjectFromHook(input);
|
|
9557
9568
|
let result;
|
|
@@ -9969,7 +9980,7 @@ ${context}`
|
|
|
9969
9980
|
};
|
|
9970
9981
|
}
|
|
9971
9982
|
function appendDevelopmentHookDiagnostics(input, result) {
|
|
9972
|
-
if (input.teamRuntimeDisplayMode !== "development" || !canDeliverTeamMessagesFromHook(input.target, input.event.type)) {
|
|
9983
|
+
if (input.teamRuntimeDisplayMode !== "development" || COMPLETION_EVENTS_WITHOUT_DEVELOPMENT_DIAGNOSTICS.has(input.event.type) || !canDeliverTeamMessagesFromHook(input.target, input.event.type)) {
|
|
9973
9984
|
return result;
|
|
9974
9985
|
}
|
|
9975
9986
|
return {
|
|
@@ -9977,6 +9988,9 @@ function appendDevelopmentHookDiagnostics(input, result) {
|
|
|
9977
9988
|
output: appendAdditionalContext(result.output, input.event.type, formatDevelopmentHookDiagnostics(input))
|
|
9978
9989
|
};
|
|
9979
9990
|
}
|
|
9991
|
+
function isActiveClaudeStopHook(input) {
|
|
9992
|
+
return input.target === "claude" && (input.event.type === "Stop" || input.event.type === "SubagentStop") && input.rawPayload.stop_hook_active === true;
|
|
9993
|
+
}
|
|
9980
9994
|
function formatDevelopmentHookDiagnostics(input) {
|
|
9981
9995
|
const metadata = Object.entries(input.event.payload.metadata);
|
|
9982
9996
|
const inputFields = Object.keys(input.rawPayload).map((field) => field.replace(/[^A-Za-z0-9._-]/g, "-").slice(0, 80)).filter((field) => field.length > 0).slice(0, 30);
|
|
@@ -18362,7 +18376,7 @@ function planClaudeHookInstallDryRun(input) {
|
|
|
18362
18376
|
{
|
|
18363
18377
|
action: "merge-with-backup",
|
|
18364
18378
|
targetPath: paths3.settingsPath,
|
|
18365
|
-
reason: "would
|
|
18379
|
+
reason: "would reconcile EvoDev-managed user-level hook entries with Claude plugin ownership without touching user-owned hooks"
|
|
18366
18380
|
}
|
|
18367
18381
|
],
|
|
18368
18382
|
warnings: ["Project .claude, .codex, CLAUDE.md, and AGENTS.md are not targeted."],
|
|
@@ -18388,9 +18402,30 @@ function planCodexHookInstallDryRun(input) {
|
|
|
18388
18402
|
async function installClaudeHooks(input) {
|
|
18389
18403
|
const paths3 = input.paths ?? resolveClaudePaths({ homeDir: input.homeDir });
|
|
18390
18404
|
const existing = await readTextIfExists(paths3.settingsPath);
|
|
18405
|
+
const pluginSelector = input.pluginSelector ?? DEFAULT_CLAUDE_PLUGIN_SELECTOR;
|
|
18406
|
+
if (input.pluginManaged === true || isClaudePluginEnabled(existing, pluginSelector)) {
|
|
18407
|
+
const next2 = removeClaudeManagedUserHooks(existing);
|
|
18408
|
+
if (next2 === null) {
|
|
18409
|
+
return {
|
|
18410
|
+
target: "claude",
|
|
18411
|
+
targetPath: paths3.settingsPath,
|
|
18412
|
+
backupPath: null,
|
|
18413
|
+
changed: false,
|
|
18414
|
+
warnings: []
|
|
18415
|
+
};
|
|
18416
|
+
}
|
|
18417
|
+
return writeMergedConfig({
|
|
18418
|
+
target: "claude",
|
|
18419
|
+
path: paths3.settingsPath,
|
|
18420
|
+
existing,
|
|
18421
|
+
next: next2,
|
|
18422
|
+
now: input.now,
|
|
18423
|
+
warnings: []
|
|
18424
|
+
});
|
|
18425
|
+
}
|
|
18391
18426
|
const runtimeCommand = await resolveClaudeUserHookRuntimeCommand({
|
|
18392
18427
|
paths: paths3,
|
|
18393
|
-
pluginSelector
|
|
18428
|
+
pluginSelector
|
|
18394
18429
|
});
|
|
18395
18430
|
const next = mergeClaudeSettingsHooks(existing, createClaudeHookConfig(runtimeCommand).hooks);
|
|
18396
18431
|
return writeMergedConfig({
|
|
@@ -18598,6 +18633,41 @@ function mergeClaudeSettingsHooks(existing, evodevHooks) {
|
|
|
18598
18633
|
return `${JSON.stringify({ ...settings, hooks: nextHooks }, null, 2)}
|
|
18599
18634
|
`;
|
|
18600
18635
|
}
|
|
18636
|
+
function isClaudePluginEnabled(existing, pluginSelector) {
|
|
18637
|
+
if (existing === null)
|
|
18638
|
+
return false;
|
|
18639
|
+
const settings = parseJsonConfig(existing, "Claude settings");
|
|
18640
|
+
const enabledPlugins = isRecord14(settings.enabledPlugins) ? settings.enabledPlugins : {};
|
|
18641
|
+
return enabledPlugins[pluginSelector] === true;
|
|
18642
|
+
}
|
|
18643
|
+
function removeClaudeManagedUserHooks(existing) {
|
|
18644
|
+
if (existing === null)
|
|
18645
|
+
return null;
|
|
18646
|
+
const settings = parseJsonConfig(existing, "Claude settings");
|
|
18647
|
+
if (!isRecord14(settings.hooks))
|
|
18648
|
+
return existing;
|
|
18649
|
+
const nextHooks = {};
|
|
18650
|
+
let changed = false;
|
|
18651
|
+
for (const [eventName, groups] of Object.entries(settings.hooks)) {
|
|
18652
|
+
if (!Array.isArray(groups)) {
|
|
18653
|
+
nextHooks[eventName] = groups;
|
|
18654
|
+
continue;
|
|
18655
|
+
}
|
|
18656
|
+
const retained = groups.filter((group) => !isEvoDevHookGroup(group, "claude"));
|
|
18657
|
+
changed ||= retained.length !== groups.length;
|
|
18658
|
+
if (retained.length > 0 || groups.length === 0)
|
|
18659
|
+
nextHooks[eventName] = retained;
|
|
18660
|
+
}
|
|
18661
|
+
if (!changed)
|
|
18662
|
+
return existing;
|
|
18663
|
+
const nextSettings = { ...settings };
|
|
18664
|
+
if (Object.keys(nextHooks).length === 0)
|
|
18665
|
+
nextSettings.hooks = undefined;
|
|
18666
|
+
else
|
|
18667
|
+
nextSettings.hooks = nextHooks;
|
|
18668
|
+
return `${JSON.stringify(nextSettings, null, 2)}
|
|
18669
|
+
`;
|
|
18670
|
+
}
|
|
18601
18671
|
function parseJsonConfig(existing, label) {
|
|
18602
18672
|
if (existing === null || existing.trim() === "")
|
|
18603
18673
|
return {};
|
|
@@ -20650,7 +20720,11 @@ async function installSelectedCodeAgentHooks(input) {
|
|
|
20650
20720
|
label: "Install Code Agent hooks",
|
|
20651
20721
|
detail: pluginId
|
|
20652
20722
|
});
|
|
20653
|
-
const result = pluginId === "codex" ? await installCodexHooks({ homeDir: input.homeDir, now: input.timestamp }) : await installClaudeHooks({
|
|
20723
|
+
const result = pluginId === "codex" ? await installCodexHooks({ homeDir: input.homeDir, now: input.timestamp }) : await installClaudeHooks({
|
|
20724
|
+
homeDir: input.homeDir,
|
|
20725
|
+
now: input.timestamp,
|
|
20726
|
+
pluginManaged: true
|
|
20727
|
+
});
|
|
20654
20728
|
results.push(result);
|
|
20655
20729
|
emitInitProgress(input.progress, {
|
|
20656
20730
|
status: "done",
|
|
@@ -27768,7 +27842,7 @@ function getHelpText() {
|
|
|
27768
27842
|
].join(`
|
|
27769
27843
|
`);
|
|
27770
27844
|
}
|
|
27771
|
-
var CLI_VERSION = "0.0.1-alpha.
|
|
27845
|
+
var CLI_VERSION = "0.0.1-alpha.8";
|
|
27772
27846
|
function getVersionText() {
|
|
27773
27847
|
return `evodev ${CLI_VERSION}`;
|
|
27774
27848
|
}
|
|
@@ -158,7 +158,7 @@ export function planClaudeHookInstallDryRun(
|
|
|
158
158
|
action: "merge-with-backup",
|
|
159
159
|
targetPath: paths.settingsPath,
|
|
160
160
|
reason:
|
|
161
|
-
"would
|
|
161
|
+
"would reconcile EvoDev-managed user-level hook entries with Claude plugin ownership without touching user-owned hooks",
|
|
162
162
|
},
|
|
163
163
|
],
|
|
164
164
|
warnings: ["Project .claude, .codex, CLAUDE.md, and AGENTS.md are not targeted."],
|
|
@@ -191,12 +191,34 @@ export async function installClaudeHooks(input: {
|
|
|
191
191
|
paths?: ClaudePaths;
|
|
192
192
|
now?: string;
|
|
193
193
|
pluginSelector?: string;
|
|
194
|
+
pluginManaged?: boolean;
|
|
194
195
|
}): Promise<HookInstallResult> {
|
|
195
196
|
const paths = input.paths ?? resolveClaudePaths({ homeDir: input.homeDir });
|
|
196
197
|
const existing = await readTextIfExists(paths.settingsPath);
|
|
198
|
+
const pluginSelector = input.pluginSelector ?? DEFAULT_CLAUDE_PLUGIN_SELECTOR;
|
|
199
|
+
if (input.pluginManaged === true || isClaudePluginEnabled(existing, pluginSelector)) {
|
|
200
|
+
const next = removeClaudeManagedUserHooks(existing);
|
|
201
|
+
if (next === null) {
|
|
202
|
+
return {
|
|
203
|
+
target: "claude",
|
|
204
|
+
targetPath: paths.settingsPath,
|
|
205
|
+
backupPath: null,
|
|
206
|
+
changed: false,
|
|
207
|
+
warnings: [],
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
return writeMergedConfig({
|
|
211
|
+
target: "claude",
|
|
212
|
+
path: paths.settingsPath,
|
|
213
|
+
existing,
|
|
214
|
+
next,
|
|
215
|
+
now: input.now,
|
|
216
|
+
warnings: [],
|
|
217
|
+
});
|
|
218
|
+
}
|
|
197
219
|
const runtimeCommand = await resolveClaudeUserHookRuntimeCommand({
|
|
198
220
|
paths,
|
|
199
|
-
pluginSelector
|
|
221
|
+
pluginSelector,
|
|
200
222
|
});
|
|
201
223
|
const next = mergeClaudeSettingsHooks(existing, createClaudeHookConfig(runtimeCommand).hooks);
|
|
202
224
|
return writeMergedConfig({
|
|
@@ -497,6 +519,37 @@ function mergeClaudeSettingsHooks(
|
|
|
497
519
|
return `${JSON.stringify({ ...settings, hooks: nextHooks }, null, 2)}\n`;
|
|
498
520
|
}
|
|
499
521
|
|
|
522
|
+
function isClaudePluginEnabled(existing: string | null, pluginSelector: string): boolean {
|
|
523
|
+
if (existing === null) return false;
|
|
524
|
+
const settings = parseJsonConfig(existing, "Claude settings");
|
|
525
|
+
const enabledPlugins = isRecord(settings.enabledPlugins) ? settings.enabledPlugins : {};
|
|
526
|
+
return enabledPlugins[pluginSelector] === true;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function removeClaudeManagedUserHooks(existing: string | null): string | null {
|
|
530
|
+
if (existing === null) return null;
|
|
531
|
+
const settings = parseJsonConfig(existing, "Claude settings");
|
|
532
|
+
if (!isRecord(settings.hooks)) return existing;
|
|
533
|
+
|
|
534
|
+
const nextHooks: Record<string, unknown> = {};
|
|
535
|
+
let changed = false;
|
|
536
|
+
for (const [eventName, groups] of Object.entries(settings.hooks)) {
|
|
537
|
+
if (!Array.isArray(groups)) {
|
|
538
|
+
nextHooks[eventName] = groups;
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
const retained = groups.filter((group) => !isEvoDevHookGroup(group, "claude"));
|
|
542
|
+
changed ||= retained.length !== groups.length;
|
|
543
|
+
if (retained.length > 0 || groups.length === 0) nextHooks[eventName] = retained;
|
|
544
|
+
}
|
|
545
|
+
if (!changed) return existing;
|
|
546
|
+
|
|
547
|
+
const nextSettings = { ...settings };
|
|
548
|
+
if (Object.keys(nextHooks).length === 0) nextSettings.hooks = undefined;
|
|
549
|
+
else nextSettings.hooks = nextHooks;
|
|
550
|
+
return `${JSON.stringify(nextSettings, null, 2)}\n`;
|
|
551
|
+
}
|
|
552
|
+
|
|
500
553
|
function parseJsonConfig(existing: string | null, label: string): Record<string, unknown> {
|
|
501
554
|
if (existing === null || existing.trim() === "") return {};
|
|
502
555
|
const parsed = JSON.parse(existing) as unknown;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evo-dev/evodev",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.8",
|
|
4
4
|
"description": "AI Coding infrastructure CLI for real R&D workflows.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"directory": "packages/cli"
|
|
10
10
|
},
|
|
11
11
|
"bin": {
|
|
12
|
-
"evodev": "./dist/
|
|
12
|
+
"evodev": "./dist/index.js"
|
|
13
13
|
},
|
|
14
14
|
"files": ["dist", "package.json"],
|
|
15
15
|
"engines": {
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: evodev-release
|
|
3
|
-
description: Use this skill for EvoDev repository commit and release work: committing local changes, bumping to the next alpha or named version, creating and pushing release tags, triggering GitHub Actions release.yml, publishing @evo-dev/core and @evo-dev/evodev, fixing failed npm trusted-publishing runs, or checking npm dist-tags. Always use this skill when the user says to commit, push, tag, release, publish, bump alpha, or repair the EvoDev release workflow.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# EvoDev Release
|
|
7
|
-
|
|
8
|
-
This skill captures the working EvoDev commit and release path for `/Users/bytedance/project/github/evodev`.
|
|
9
|
-
|
|
10
|
-
EvoDev releases are GitHub Actions driven. Do not run local `npm publish` or `bun publish` unless the user explicitly asks for a local experiment. The normal path is: inspect diff, verify, commit, sync version, commit release, push `main`, push or dispatch release, watch CI, then confirm npm registry state.
|
|
11
|
-
|
|
12
|
-
## Current Release Model
|
|
13
|
-
|
|
14
|
-
- GitHub workflow: `.github/workflows/release.yml`.
|
|
15
|
-
- Publish target packages: `@evo-dev/core` and `@evo-dev/evodev`.
|
|
16
|
-
- Package inspected but not published to npm: `@evo-dev/plugin`.
|
|
17
|
-
- Version sync command: `bun run version:sync -- <version>`.
|
|
18
|
-
- Version check command: `bun run version:check`.
|
|
19
|
-
- Main quality gate: `bun run check`.
|
|
20
|
-
- Release package/smoke gate: `bun run release:dry-run`.
|
|
21
|
-
- Tag trigger: `v<semver>`, for example `v0.0.1-alpha.3`.
|
|
22
|
-
- npm dist-tag mapping:
|
|
23
|
-
- versions containing `-alpha` publish with npm dist-tag `alpha`;
|
|
24
|
-
- versions containing `-beta` publish with `beta`;
|
|
25
|
-
- other prereleases publish with `next`;
|
|
26
|
-
- stable versions publish with `latest`.
|
|
27
|
-
|
|
28
|
-
The release workflow uses npm Trusted Publisher / OIDC, not long-lived npm tokens.
|
|
29
|
-
|
|
30
|
-
Required npm Trusted Publisher settings for both `@evo-dev/core` and `@evo-dev/evodev`:
|
|
31
|
-
|
|
32
|
-
- repository: `limerickgds/evodev`
|
|
33
|
-
- workflow filename: `release.yml`
|
|
34
|
-
- environment: `npm-release`
|
|
35
|
-
- allowed action: `npm publish`
|
|
36
|
-
|
|
37
|
-
The publish job should have `id-token: write`, use `actions/setup-node` with `registry-url: https://registry.npmjs.org`, and run `npm publish` from `packages/core` and `packages/cli`. Do not reintroduce `NPM_CONFIG_TOKEN`, `NPM_TOKEN`, `.npmrc` token writes, `--auth-type=legacy`, or `bun publish` into the normal release path.
|
|
38
|
-
|
|
39
|
-
## Before Changing Anything
|
|
40
|
-
|
|
41
|
-
Collect current evidence first:
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
git status -sb
|
|
45
|
-
git diff --stat
|
|
46
|
-
git log --oneline --decorate -8
|
|
47
|
-
git fetch --tags --prune --quiet
|
|
48
|
-
git tag --sort=-v:refname | head -20
|
|
49
|
-
npm view @evo-dev/evodev versions --json
|
|
50
|
-
npm view @evo-dev/evodev dist-tags --json
|
|
51
|
-
npm view @evo-dev/core dist-tags --json
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
Use registry state, not only local tags, to choose the next version. If npm already has `0.0.1-alpha.N`, the next alpha is normally `0.0.1-alpha.(N+1)` even if the matching git tag is missing.
|
|
55
|
-
|
|
56
|
-
## Commit Flow
|
|
57
|
-
|
|
58
|
-
1. Inspect local changes before staging:
|
|
59
|
-
```bash
|
|
60
|
-
git diff --stat
|
|
61
|
-
git diff -- <relevant files>
|
|
62
|
-
```
|
|
63
|
-
2. Split commits by intent:
|
|
64
|
-
- functional or docs changes first, with a conventional message such as `feat(team): ...` or `fix(release): ...`;
|
|
65
|
-
- version sync as a separate release commit: `chore: release v<version>`.
|
|
66
|
-
3. Stage only intended files. Preserve unrelated user changes.
|
|
67
|
-
4. Use non-interactive git commands:
|
|
68
|
-
```bash
|
|
69
|
-
git add <files>
|
|
70
|
-
git commit -m "<type>(<scope>): <summary>"
|
|
71
|
-
```
|
|
72
|
-
5. After every commit, check:
|
|
73
|
-
```bash
|
|
74
|
-
git status -sb
|
|
75
|
-
git log --oneline --decorate -5
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
## Version Bump Flow
|
|
79
|
-
|
|
80
|
-
Use the repo script instead of editing versions by hand:
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
bun run version:sync -- <version>
|
|
84
|
-
bun run version:check
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
The sync script updates the root workspace package, core package, CLI package, plugin manifests, Claude marketplace metadata, Codex plugin metadata, and `CLI_VERSION`.
|
|
88
|
-
|
|
89
|
-
Before release commit, run:
|
|
90
|
-
|
|
91
|
-
```bash
|
|
92
|
-
bun run check
|
|
93
|
-
bun run release:dry-run
|
|
94
|
-
git diff --check
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
If any gate fails, fix the issue before committing the release. Do not report a release as ready if a gate failed or was skipped without explanation.
|
|
98
|
-
|
|
99
|
-
## Tag-Driven Release Flow
|
|
100
|
-
|
|
101
|
-
For a committed version bump:
|
|
102
|
-
|
|
103
|
-
```bash
|
|
104
|
-
git tag v<version>
|
|
105
|
-
git push origin main
|
|
106
|
-
git push origin v<version>
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
The pushed tag must point at the release commit whose `package.json` version matches the tag. The workflow checks this on tag events.
|
|
110
|
-
|
|
111
|
-
Then watch the GitHub Actions run:
|
|
112
|
-
|
|
113
|
-
```bash
|
|
114
|
-
gh run list --workflow Release --limit 5
|
|
115
|
-
gh run watch <run-id> --exit-status
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
After CI finishes, verify registry state:
|
|
119
|
-
|
|
120
|
-
```bash
|
|
121
|
-
npm view @evo-dev/evodev dist-tags --json
|
|
122
|
-
npm view @evo-dev/core dist-tags --json
|
|
123
|
-
npm view @evo-dev/evodev versions --json
|
|
124
|
-
npm view @evo-dev/core versions --json
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
## Workflow Dispatch Recovery
|
|
128
|
-
|
|
129
|
-
If a tag run used an old broken workflow, do not rewrite a pushed public tag by default.
|
|
130
|
-
|
|
131
|
-
Instead:
|
|
132
|
-
|
|
133
|
-
1. Fix `.github/workflows/release.yml` on `main`.
|
|
134
|
-
2. Commit and push the workflow fix.
|
|
135
|
-
3. Dispatch the fixed workflow for the same version:
|
|
136
|
-
```bash
|
|
137
|
-
gh workflow run release.yml --ref main \
|
|
138
|
-
-f target=both \
|
|
139
|
-
-f publish=true \
|
|
140
|
-
-f tag=alpha \
|
|
141
|
-
-f version=<version>
|
|
142
|
-
```
|
|
143
|
-
4. Watch the new run and confirm npm dist-tags.
|
|
144
|
-
|
|
145
|
-
Use `workflow_dispatch` only when it is clearly safer than mutating a pushed tag, or when the user explicitly asks for manual release.
|
|
146
|
-
|
|
147
|
-
## Trusted Publishing Failure Handling
|
|
148
|
-
|
|
149
|
-
If publish fails with a token error such as missing `NPM_CONFIG_TOKEN` or `NPM_TOKEN`, do not add token checks back. For Trusted Publisher, fix the workflow and npm package configuration:
|
|
150
|
-
|
|
151
|
-
- workflow job needs `permissions.id-token: write`;
|
|
152
|
-
- publish job must use GitHub-hosted runners;
|
|
153
|
-
- npm package Trusted Publisher fields must exactly match repository, workflow filename, and environment;
|
|
154
|
-
- use npm CLI through `npm publish`, not `bun publish`;
|
|
155
|
-
- Node 24 from `actions/setup-node` already provides npm 11.x, which supports trusted publishing.
|
|
156
|
-
|
|
157
|
-
If `release:dry-run` fails only after changing npm versions, avoid unnecessary global npm upgrades. In the current workflow, `actions/setup-node@v6` with Node 24 provides a compatible npm version; keep the dry-run behavior stable.
|
|
158
|
-
|
|
159
|
-
If one package publishes and the second fails, check registry versions before retrying. npm versions are immutable, so rerunning `target=both` may fail on the already-published package. Use `target=core` or `target=cli` only for the missing package when appropriate.
|
|
160
|
-
|
|
161
|
-
## Final Report
|
|
162
|
-
|
|
163
|
-
Report the release outcome with:
|
|
164
|
-
|
|
165
|
-
```text
|
|
166
|
-
VERSION: <version>
|
|
167
|
-
COMMITS:
|
|
168
|
-
- <sha> <message>
|
|
169
|
-
TAG: v<version> pushed | not pushed
|
|
170
|
-
RUN: <GitHub Actions URL and status>
|
|
171
|
-
REGISTRY:
|
|
172
|
-
- @evo-dev/core alpha/latest: <version>
|
|
173
|
-
- @evo-dev/evodev alpha/latest: <version>
|
|
174
|
-
VERIFICATION:
|
|
175
|
-
- bun run version:check: PASS | FAIL | not-run
|
|
176
|
-
- bun run check: PASS | FAIL | not-run
|
|
177
|
-
- bun run release:dry-run: PASS | FAIL | not-run
|
|
178
|
-
WORKTREE: clean | dirty
|
|
179
|
-
FOLLOW-UP:
|
|
180
|
-
- <item or none>
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
Be explicit about whether npm publication actually happened. A pushed git tag is not the same thing as a successful npm dist-tag update.
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: grilling
|
|
3
|
-
description: Interview the user relentlessly about a plan or design. Use when the user wants to stress-test a plan before building, or uses any 'grill' trigger phrases.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer.
|
|
7
|
-
|
|
8
|
-
Ask the questions one at a time, waiting for feedback on each question before continuing. Asking multiple questions at once is bewildering.
|
|
9
|
-
|
|
10
|
-
If a question can be answered by exploring the codebase, explore the codebase instead.
|
package/dist/evodev
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
set -eu
|
|
3
|
-
|
|
4
|
-
if ! command -v node >/dev/null 2>&1; then
|
|
5
|
-
echo "EvoDev CLI requires Node.js >=20 to run." >&2
|
|
6
|
-
echo "Install Node.js, then restart your shell and run: evodev doctor." >&2
|
|
7
|
-
exit 1
|
|
8
|
-
fi
|
|
9
|
-
|
|
10
|
-
SCRIPT_DIR="$(CDPATH= cd "$(dirname "$0")" && pwd)"
|
|
11
|
-
exec node "$SCRIPT_DIR/index.js" "$@"
|