daedalus-cli 3.25.0 → 3.25.1
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
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [3.25.1](https://github.com/bgill55/daedalus/compare/v3.25.0...v3.25.1) (2026-08-09)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **build:** copy skill playbooks to dist so they ship to npm users ([#86](https://github.com/bgill55/daedalus/issues/86)) ([56d6aa4](https://github.com/bgill55/daedalus/commit/56d6aa4cc0acd092694ca80b421d7592e8f48991)), closes [#85](https://github.com/bgill55/daedalus/issues/85)
|
|
7
|
+
|
|
1
8
|
# [3.25.0](https://github.com/bgill55/daedalus/compare/v3.24.0...v3.25.0) (2026-08-09)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: add-slash-command
|
|
3
|
+
description: How to add a new slash command to Daedalus (src/commands), including the docs-sync step that breaks CI if skipped.
|
|
4
|
+
trigger: add a command|new /command|create a slash command|add /command|/command
|
|
5
|
+
safety: instructions
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Adding a Slash Command to Daedalus
|
|
9
|
+
|
|
10
|
+
Commands live in `src/commands/` and are aggregated in `src/commands/index.ts`.
|
|
11
|
+
ESM only, named exports, `.js` extension on imports, no comments unless necessary.
|
|
12
|
+
|
|
13
|
+
## Command shape
|
|
14
|
+
`src/commands/types.ts` defines `Command`:
|
|
15
|
+
```ts
|
|
16
|
+
export interface Command {
|
|
17
|
+
name: string; // '/spinner'
|
|
18
|
+
aliases?: string[]; // ['spin']
|
|
19
|
+
description: string;
|
|
20
|
+
usage?: string;
|
|
21
|
+
helpText?: string;
|
|
22
|
+
execute: (args: string, ctx: CommandContext) => Promise<boolean | void>;
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Steps
|
|
27
|
+
1. Create `src/commands/<name>.ts` exporting `export const <name>Commands: Command[]`.
|
|
28
|
+
Inside `execute`, use `ctx.config` (typed `DaedalusConfig`), `ctx.configDir`, `ctx.router`.
|
|
29
|
+
2. To persist a config change, mirror `/config` (src/commands/dev.ts ~line 964):
|
|
30
|
+
```ts
|
|
31
|
+
const { saveConfig, ConfigSchema } = await import('../config/index.js');
|
|
32
|
+
ctx.config.ui.spinner = arg;
|
|
33
|
+
const validated = ConfigSchema.parse(ctx.config);
|
|
34
|
+
ctx.config = validated;
|
|
35
|
+
saveConfig(validated);
|
|
36
|
+
if (ctx.router && typeof ctx.router.updateConfig === 'function') {
|
|
37
|
+
ctx.router.updateConfig(ctx.config.router);
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
Validate input BEFORE mutating; reject unknown values with a friendly message.
|
|
41
|
+
3. Register in `src/commands/index.ts`:
|
|
42
|
+
`import { <name>Commands } from './<name>.js';` then spread `...<name>Commands,` into `commandsList`.
|
|
43
|
+
4. CRITICAL — docs will break CI if you skip this. `src/docs.test.ts` has two tests
|
|
44
|
+
that fail unless the command is in BOTH the docs generator and the test's own copy:
|
|
45
|
+
- `scripts/sync-docs.ts`: add the command to `COMMAND_GROUPS` (array) AND `COMMAND_USAGES` (map).
|
|
46
|
+
- `src/docs.test.ts`: add the SAME entries to its duplicate `COMMAND_GROUPS` + `COMMAND_USAGES`.
|
|
47
|
+
- Then run `npm run sync-docs` to regenerate README.md + docs/configuration-reference.md.
|
|
48
|
+
The usual failure: a missing `COMMAND_USAGES` entry → test says "commands table is out of sync".
|
|
49
|
+
5. Add `src/commands/<name>.test.ts`. For config-persisting commands, `vi.mock('../config/index.js')`
|
|
50
|
+
with `{ ConfigSchema: { parse: (c) => c }, saveConfig: vi.fn() }` so no real disk write;
|
|
51
|
+
assert `saveConfig` called and `ctx.router.updateConfig` fired.
|
|
52
|
+
|
|
53
|
+
## Verify before commit
|
|
54
|
+
```
|
|
55
|
+
npx tsc --noEmit
|
|
56
|
+
npm run lint
|
|
57
|
+
npm test
|
|
58
|
+
```
|
|
59
|
+
`docs.test.ts` is the easy one to break — always run `npm run sync-docs` after touching groups/usages.
|
|
60
|
+
|
|
61
|
+
## PR + release notes
|
|
62
|
+
- PR title scope with a comma (`fix(tools,router):`) is rejected by the title guard; use a single scope.
|
|
63
|
+
- `require()`-style imports in test files trip `no-require-imports`; use ESM imports.
|
|
64
|
+
- The Release workflow may not auto-trigger on squash-merge; dispatch manually:
|
|
65
|
+
`gh workflow run release.yml`.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fix-typescript-build
|
|
3
|
+
description: How to fix a failing `tsc`/`npm run build` (type-check) run in a project, batching fixes into sprints to preserve context.
|
|
4
|
+
trigger: fix the build|type errors|typescript errors|tsc errors|build is broken|build fails|npm run build|fix the type errors
|
|
5
|
+
safety: instructions
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Fixing a TypeScript Build (npm run build / tsc)
|
|
9
|
+
|
|
10
|
+
The project's `build` script is usually `tsc --noEmit` (a type-check, not a bundle).
|
|
11
|
+
A failing build means type errors. Fix them deliberately — do NOT blast the whole
|
|
12
|
+
codebase in one giant turn (that burns the context window and makes review impossible).
|
|
13
|
+
|
|
14
|
+
> Prefer `npm run build` over `npx tsc`. `npx tsc` is not a declared dependency in
|
|
15
|
+
> most projects, so `npx` will try to download the `tsc` package from the registry —
|
|
16
|
+
> that download is slow and flaky (and can be killed by the terminal's process-group
|
|
17
|
+
> isolation on Windows). `npm run build` uses the project's local TypeScript.
|
|
18
|
+
|
|
19
|
+
## Process
|
|
20
|
+
1. Get the full error list first. Run `npm run build` (the project's `build` script).
|
|
21
|
+
Only fall back to `npx tsc --noEmit` if the project has no `build` script. Capture
|
|
22
|
+
EVERY error line. Do not guess — read the actual compiler output.
|
|
23
|
+
2. Group errors by file. Most real projects concentrate errors in a few files.
|
|
24
|
+
Present the grouped summary to the user and STOP to confirm scope before editing
|
|
25
|
+
(audit/review etiquette: list findings, then ask which to fix).
|
|
26
|
+
3. Once confirmed, FIX FILE-SCOPED. For each target file:
|
|
27
|
+
- Read the file, make the minimal change (rename an unused param to `_x`,
|
|
28
|
+
switch `obj.key` to `obj['key']` when the type is an index signature, etc.).
|
|
29
|
+
- The syntax checker will NOT false-revert a valid edit just because the file
|
|
30
|
+
already had other errors — it diffs pre- vs post-edit diagnostics. So fix one
|
|
31
|
+
file at a time confidently; a valid edit won't be blamed for pre-existing errors.
|
|
32
|
+
4. Re-run `npm run build` after each file (or each small batch) to confirm the
|
|
33
|
+
errors for that file are gone. Iterate until the build is clean.
|
|
34
|
+
5. Run the test suite (`npm test`) to confirm nothing broke. Report the final state.
|
|
35
|
+
|
|
36
|
+
## Context-window discipline (important)
|
|
37
|
+
- Break the work into SPRINTS: e.g. Sprint 1 = fix `validation.ts`, Sprint 2 =
|
|
38
|
+
fix `server.ts`. After each sprint, the build gets greener and you checkpoint.
|
|
39
|
+
- Keep each turn's edits SMALL (one file, few lines). Do NOT dump a 100-line rewrite
|
|
40
|
+
of a file that only needed 3 lines changed — that is what burns context and trips
|
|
41
|
+
the patch tooling.
|
|
42
|
+
- Use the `todo` tool to track sprints so progress survives across turns.
|
|
43
|
+
|
|
44
|
+
## Common error patterns
|
|
45
|
+
- `TS6133` unused variable/param → prefix with `_` (respects `noUnusedLocals`/`noUnusedParameters`).
|
|
46
|
+
- `TS4111` / `noPropertyAccessFromIndexSignature` → use bracket access `prompt['id']`
|
|
47
|
+
instead of dot access `prompt.id` when the type is `Record<string, unknown>`.
|
|
48
|
+
- `exactOptionalPropertyTypes` → don't assign `string | undefined` to an optional
|
|
49
|
+
`id?: string`; assign conditionally (`if (id !== undefined) result.id = id;`).
|
|
50
|
+
- `TS2345` type mismatch → fix the actual type, don't cast with `as any` (casts hide
|
|
51
|
+
real bugs and the project lints against `any`).
|
|
52
|
+
|
|
53
|
+
## Verify
|
|
54
|
+
- `npm run build` exits 0.
|
|
55
|
+
- `npm test` passes.
|
|
56
|
+
- State the final error count (0) and which files you touched.
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: grade-and-fix-daedalus
|
|
3
|
+
description: How to grade a Daedalus run (or pasted agent transcript), root-cause the failure, and ship the fix to Daedalus CORE as a stacked PR — without modifying the prompt-vault sandbox (read-only grading). Covers recurring bug archetypes (Unicode punctuation patch mismatch, syntax-vs-type mislabel, emoji box misalignment, half-edited files, loop/false-completion guards, and the v3.25.0 pre-flight dependency gate where "every patch reverts" is the prevention gate working, not a broken guardrail). Includes tsx repro and the verified ship flow.
|
|
4
|
+
trigger: fix this daedalus bug|why did the patch fail|grade this run|ship the fix|every patch reverts|patch keeps reverting|type error introduced by patch|pre-flight|prevention over revert|daedalus core resilience
|
|
5
|
+
safety: instructions
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Grade a Daedalus run and ship the core fix (stacked PR)
|
|
9
|
+
|
|
10
|
+
This skill covers how to grade a Daedalus run (or read a pasted agent transcript),
|
|
11
|
+
root-cause the failure, fix it in `src/...`, and ship it as a stacked PR. The
|
|
12
|
+
prompt-vault sandbox stays READ-ONLY except for one user-explicit exception.
|
|
13
|
+
|
|
14
|
+
## Hard rules (standing)
|
|
15
|
+
|
|
16
|
+
- **Grade, don't fix the sandbox.** `prompt-vault` (+ `social_media_manager`) are
|
|
17
|
+
TEST-ONLY. You READ/GRADE them. You do NOT edit them to "help" Daedalus — that
|
|
18
|
+
defeats the purpose. The ONE exception: a user-explicit "just this once, fix this
|
|
19
|
+
error in the test project" — otherwise the sandbox is passive.
|
|
20
|
+
- **Fixes go to Daedalus CORE** (`src/...`), never the sandbox. A graded run that
|
|
21
|
+
exposes a guardrail gap is a core bug; ship it as a PR.
|
|
22
|
+
- **Run Daedalus from SOURCE** (`npx tsx src/index.ts`) — the published bin is stale.
|
|
23
|
+
Banner version lagging package.json is cosmetic.
|
|
24
|
+
- **`search_files` FAILS on `D:\` paths** (MSYS IO error). Use `terminal` with
|
|
25
|
+
`grep`/`ls`/`git` for anything under D:\.
|
|
26
|
+
- **Verify with real tool calls, not theory.** Reproduce the bug by importing the
|
|
27
|
+
actual function and calling it (tsx repro), then prove the fix the same way. Do
|
|
28
|
+
NOT assert "the guard is wrong" without a repro.
|
|
29
|
+
- **Skills are auto-discovered** from this `src/skills/` dir (see `src/skills/index.ts`):
|
|
30
|
+
any subdir with a `SKILL.md` whose frontmatter has a `trigger` field is matched
|
|
31
|
+
keyword-style against the user's request and injected into the prompt. Keep the
|
|
32
|
+
`trigger` field populated with pipe-separated phrases.
|
|
33
|
+
|
|
34
|
+
## Recurring bug archetypes (with exact fixes that shipped)
|
|
35
|
+
|
|
36
|
+
These are the failure modes seen grading real Daedalus runs. Each maps to a specific
|
|
37
|
+
root cause and a specific fix location.
|
|
38
|
+
|
|
39
|
+
### 1. Patch fails on a Unicode punctuation mismatch (en-dash vs hyphen)
|
|
40
|
+
- **Symptom:** agent's `old_string` uses a regular hyphen `-` but the file has an
|
|
41
|
+
en-dash `–` (U+2013) in a comment; Daedalus reports "Old string not found" and the
|
|
42
|
+
edit never lands. Looks like "every patch fails" but it's a 1-char invisible mismatch.
|
|
43
|
+
- **Root cause:** `patchFile` (`src/tools/builtin/files.ts`) matches `old_string`
|
|
44
|
+
exactly, and the fuzzy fallback `fuzzyWhitespacePatch` only normalizes whitespace,
|
|
45
|
+
not Unicode punctuation. en-dash/hyphen/smart-quotes/NBSP are invisible to a human
|
|
46
|
+
but distinct bytes.
|
|
47
|
+
- **Fix (v3.20.7):** added `normalizeUnicode()` in `patch-utils.ts` mapping en/em-dash
|
|
48
|
+
-> hyphen, smart quotes -> straight, NBSP -> space (all 1:1 so original bytes stay
|
|
49
|
+
intact), folded into `normalizeWhitespace()`; the exact `indexOf` path in `files.ts`
|
|
50
|
+
also tries a unicode-normalized match. Mappings must be 1:1 (no length-changing
|
|
51
|
+
entries like ellipsis `…`->`...`, or the index-slice math breaks).
|
|
52
|
+
|
|
53
|
+
### 2. "Syntax error introduced by patch" is actually a TYPE error
|
|
54
|
+
- **Symptom:** user sees "every one-line change is a syntax error" and is confused.
|
|
55
|
+
- **Root cause:** `syntaxCheck` returns diagnostics that include TypeScript type errors
|
|
56
|
+
(TS2304 "Cannot find name 'X'", TS2322, etc.) — genuine TYPE errors, not syntax — but
|
|
57
|
+
`files.ts` wrapped them all with a hardcoded `"Syntax error introduced by patch"`
|
|
58
|
+
prefix. A type error (file parses fine, a downstream reference broke) is NOT a syntax
|
|
59
|
+
error (structurally broken file). The mislabel is what made it look like the model
|
|
60
|
+
couldn't change one line.
|
|
61
|
+
- **Fix (v3.20.8):** `syntaxCheck` now self-labels — genuine transpile/parse breaks
|
|
62
|
+
(.js `--check`, the transpile stage) return `"Syntax error introduced by patch —
|
|
63
|
+
reverted."`; tsc type-check failures return `"Type error introduced by patch —
|
|
64
|
+
reverted."`. JSON/YAML keep their specific labels. `formatDiagnostic` now emits the
|
|
65
|
+
FULL file path + line:col (was basename only). `files.ts` no longer prepends the
|
|
66
|
+
misleading prefix.
|
|
67
|
+
|
|
68
|
+
### 3. Assistant box misaligned / reply spills outside the frame
|
|
69
|
+
- **Symptom:** the `⚡ Daedalus` box top/bottom rules don't line up; long body lines
|
|
70
|
+
overflow the right edge.
|
|
71
|
+
- **Root cause:** (a) the `⚡` emoji is 2 terminal cells wide but was counted as 1, so
|
|
72
|
+
the top border's dash fill overshot by a column; (b) padding used `string.length`
|
|
73
|
+
instead of display (cell) width, so wide glyphs under/over-padded; (c) curved corners
|
|
74
|
+
(╭╮╰╯) + side rails (│) made the alignment math fragile.
|
|
75
|
+
- **Fix (v3.20.9, per user request for "two straight lines, no curves, no side rails"):**
|
|
76
|
+
dropped the curves and rails; both rules + body lines now build from a single
|
|
77
|
+
`displayWidth()`-aware helper (`isWide()` flags CJK/emoji/wide as 2 cells,
|
|
78
|
+
box-drawing stays 1) so everything measures exactly `_lastBoxW` cells. Bottom stat
|
|
79
|
+
line truncates with `…` and reserves 1 cell for it.
|
|
80
|
+
|
|
81
|
+
### 4. Half-edited file causes repeated "port is undefined" / type errors
|
|
82
|
+
- **Symptom:** a prior failed run left the file mid-edit (e.g. signature changed but
|
|
83
|
+
the old `if (port) { app.listen }` block + call site still reference `port`). Any new
|
|
84
|
+
patch to the signature fails type-check; the guard correctly reverts, and the model
|
|
85
|
+
loops on a stale view.
|
|
86
|
+
- **Root cause:** NOT a guard bug — the guard correctly refused a build-breaking patch.
|
|
87
|
+
The trap is the half-edited disk state. Fixing it means either (a) re-reading the
|
|
88
|
+
current file and fixing all references together, or (b) the v3.20.5 removed-symbol
|
|
89
|
+
hint, which detects when an introduced TS2304 refers to a symbol the patch deleted
|
|
90
|
+
and says exactly which lines still reference it.
|
|
91
|
+
- **Lesson:** when "every patch fails," first `git status`/`git diff` the sandbox to
|
|
92
|
+
check for a half-applied state before assuming the guard is broken.
|
|
93
|
+
|
|
94
|
+
### 5. Loop / false-completion (the v3.20.4 guards)
|
|
95
|
+
- Patch-failure streak breaker: global `context.patchFailureTotal` counter (not
|
|
96
|
+
per-path) trips at 3 -> `[PATCH CIRCUIT BREAKER]` hard stop, forces terminal
|
|
97
|
+
turn-close.
|
|
98
|
+
- On-disk completion guard (`detectFalseCompletionOnDisk` in `completion-guard.ts`): if
|
|
99
|
+
the agent claims "fixed X" but `git diff`/disk shows no change, block the turn with a
|
|
100
|
+
SYSTEM WARNING. This is the strict false-report mandate — never accept an empty diff
|
|
101
|
+
"done."
|
|
102
|
+
|
|
103
|
+
### 6. "Every patch reverts" — it's the PRE-FLIGHT gate working (prevention over revert)
|
|
104
|
+
- **Symptom:** user reports "Daedalus can't edit a single file without an error / every
|
|
105
|
+
patch throws a type error and reverts." Looks like the patch tool is broken. It is NOT.
|
|
106
|
+
- **Root cause (the helmet incident, v3.25.0):** a patch imports a dependency whose
|
|
107
|
+
types don't resolve in the project — e.g. `helmet@8` installed but `@types/helmet`
|
|
108
|
+
MISSING. The `import helmet from 'helmet'` is therefore untyped (`any`), and under
|
|
109
|
+
`strict` the options object literal (`policy: 'require-corp'`, etc.) generates real TS
|
|
110
|
+
errors that the patch DID introduce. The post-write `syntaxCheck` correctly reverts.
|
|
111
|
+
The agent then re-proposes the SAME broken diff 3x, trips the circuit breaker, and
|
|
112
|
+
sometimes goes on an unrelated side-quest (installing swagger, running bare `tsc`
|
|
113
|
+
which throws its own noise).
|
|
114
|
+
- **The real fix is PREVENTION, not revert (standing mandate: "clean code from the
|
|
115
|
+
get-go, resolve issues before patching").** Shipped in v3.25.0 as
|
|
116
|
+
`preflightDependencyCheck()` in `src/tools/builtin/patch-utils.ts`, wired into all
|
|
117
|
+
three write paths in `files.ts` (writeFile, patchFile autoapply-all, patchFile
|
|
118
|
+
interactive) — BEFORE the disk write + post-write `syntaxCheck`. It scans the proposed
|
|
119
|
+
content's import specifiers and resolves each against the project's installed
|
|
120
|
+
`node_modules` + tsconfig (bundled `types`/`typings`, `@types/<pkg>` companion, or a
|
|
121
|
+
`@types/*` pkg). If a dependency has no usable type declarations, the patch is REFUSED
|
|
122
|
+
PRE-WRITE with an actionable fix: `npm install --save-dev @types/<pkg>`, then re-patch.
|
|
123
|
+
It never touches disk, never reverts, never hits the circuit breaker. Also added a
|
|
124
|
+
system-prompt rule "Resolve dependencies BEFORE patching" telling the agent to verify
|
|
125
|
+
types resolve and install missing `@types` as a PREREQUISITE patch first.
|
|
126
|
+
- **Grading takeaway:** when a user says "every patch fails," FIRST check whether it's
|
|
127
|
+
the pre-flight gate catching a missing `@types` / missing dep (gate working correctly)
|
|
128
|
+
vs. a genuinely broken guardrail. The pre-flight message names the exact missing
|
|
129
|
+
package + the install command. If the agent is looping 3x into the breaker, the bug is
|
|
130
|
+
in the agent's RECOVERY logic (re-proposing the same broken diff instead of resolving
|
|
131
|
+
the dependency), which is fixed by this gate — not by weakening the revert net.
|
|
132
|
+
- **Pinned test cases (in `src/tools/builtin/patch-utils.test.ts`):** resolvable import
|
|
133
|
+
passes; missing-types flagged pre-write with `npm install --save-dev @types/<pkg>`
|
|
134
|
+
hint; `@types` companion resolves; relative imports ignored.
|
|
135
|
+
|
|
136
|
+
## Step 1 — Reproduce the bug against REAL code (don't theorize)
|
|
137
|
+
|
|
138
|
+
Write a throwaway `.mts` repro that imports the actual function and calls it. Example
|
|
139
|
+
for the en-dash / type-error cases:
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
// repro.mts (run: npx tsx repro.mts ; then rm -f repro.mts)
|
|
143
|
+
import { patchFile } from './src/tools/builtin/files.js';
|
|
144
|
+
import fs from 'fs';
|
|
145
|
+
const file = 'D:/prompt-vault/src/server.ts';
|
|
146
|
+
const ctx: any = {
|
|
147
|
+
sessionId: 'r', projectRoot: 'D:/prompt-vault', projectHash: 'x', activeFiles: new Map(),
|
|
148
|
+
agentRole: 'test', abortSignal: new AbortController().signal, autoApplyEdits: 'all',
|
|
149
|
+
patchHistory: [], patchFailureStreak: new Map(), patchFailureTotal: 0,
|
|
150
|
+
sessionReadCache: new Map(),
|
|
151
|
+
};
|
|
152
|
+
// case: remove param but leave usages -> should report TYPE error, not syntax
|
|
153
|
+
const r = await patchFile({ path: file, old_string: 'export function createApp(): Application {',
|
|
154
|
+
new_string: 'export function createApp(): Application {' }, ctx);
|
|
155
|
+
console.log((r.error || '').split('\n').slice(0, 4).join('\n'));
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
For the box: capture `console.log` into an array, render a block with a forced
|
|
159
|
+
`process.stdout.columns = 80`, and assert `displayWidth(line) === 80 - 6` for both
|
|
160
|
+
rules.
|
|
161
|
+
|
|
162
|
+
**Keep repro files SMALL** — the patch tool streams time out on large payloads. If a
|
|
163
|
+
`patch`/`write_file` call is large, split it into multiple smaller calls.
|
|
164
|
+
|
|
165
|
+
## Step 2 — Fix in core, keep tests green
|
|
166
|
+
|
|
167
|
+
- Match Daedalus conventions: named exports only, `.js` ESM import extensions, no
|
|
168
|
+
source comments unless necessary, Zod config schemas. Tests co-located as
|
|
169
|
+
`*.test.ts`, vitest.
|
|
170
|
+
- Add/update a unit test that pins the exact behavior (e.g. en-dash patch now matches;
|
|
171
|
+
type error labeled "Type error"; box rules exactly `_lastBoxW`). The alignment test
|
|
172
|
+
must assert CELL width (`displayWidth`), not JS `.length` — emoji make `.length`
|
|
173
|
+
wrong.
|
|
174
|
+
- Verify locally BEFORE pushing:
|
|
175
|
+
```bash
|
|
176
|
+
npx tsc --noEmit # expect 0 errors
|
|
177
|
+
npm run lint # 0 errors (pre-existing warnings are fine)
|
|
178
|
+
npm test # full suite green
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Step 3 — Ship as a stacked PR (verified flow)
|
|
182
|
+
|
|
183
|
+
Use the `daedalus-stacked-prs` skill for the mechanics. The proven sequence:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
cd D:/Daedalus
|
|
187
|
+
git checkout -b fix/<short-slug>
|
|
188
|
+
# edit src/... + tests
|
|
189
|
+
npx tsc --noEmit && npm run lint && npm test # gate locally first
|
|
190
|
+
git add <files> && git commit -q -m "fix(tools): <conventional commit, single scope>
|
|
191
|
+
|
|
192
|
+
<why + what + verification, ~3 short paras>"
|
|
193
|
+
git push -u origin fix/<short-slug>
|
|
194
|
+
gh pr create --title "fix(tools): <same as commit subject>" --body "<PR body>"
|
|
195
|
+
# wait for ALL THREE CI lanes, not just one:
|
|
196
|
+
for i in $(seq 1 15); do
|
|
197
|
+
pend=$(gh pr checks <N> 2>&1 | grep -c pending); [ "$pend" -eq 0 ] && break; sleep 12
|
|
198
|
+
done
|
|
199
|
+
gh pr checks <N> # confirm Test (ubuntu) + Test (windows) + Test (macos) all pass
|
|
200
|
+
gh pr merge <N> --squash
|
|
201
|
+
git fetch origin && git checkout main && git reset --hard origin/main
|
|
202
|
+
git branch -D fix/<short-slug>; git push origin --delete fix/<short-slug>
|
|
203
|
+
# wait for semantic-release, then confirm the tag + npm version:
|
|
204
|
+
for i in $(seq 1 20); do
|
|
205
|
+
st=$(gh run list --repo bgill55/daedalus --limit 1 --json status --jq '.[0].status')
|
|
206
|
+
[ "$st" = completed ] && break; sleep 10
|
|
207
|
+
done
|
|
208
|
+
git fetch --tags origin; npm view daedalus-cli version
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**CI facts:** `Test (windows-latest)` has been FLAKY in the past (terminal/API tests,
|
|
212
|
+
env-only, no model server) — if it's red but the other two lanes are green and the
|
|
213
|
+
failure is clearly env-only, re-run that single job. Don't merge on a red core test.
|
|
214
|
+
**Release:** `gh pr merge --squash` does NOT auto-trigger release — after merge, the
|
|
215
|
+
`release.yml` workflow runs `npx semantic-release` and publishes `daedalus-cli`. Confirm
|
|
216
|
+
the new `v3.2X.Y` tag + npm version. Stacked PRs are FREE (all repos) — one stack +
|
|
217
|
+
single async merge = one release.
|
|
218
|
+
|
|
219
|
+
## Pitfalls
|
|
220
|
+
|
|
221
|
+
- Do NOT modify the prompt-vault sandbox (except the one user-approved exception). Grade
|
|
222
|
+
read-only; ship to core.
|
|
223
|
+
- The "Syntax error" label is misleading by design-history — if you see it, check whether
|
|
224
|
+
it's actually a TS type error (the v3.20.8 fix separates them). If a user reports
|
|
225
|
+
"every patch is a syntax error," first check for a half-edited file (archetype 4).
|
|
226
|
+
- Unicode dash/quote mismatches are invisible in a paste — verify the actual file bytes
|
|
227
|
+
with `sed -n 'Np' file | cat -A` or `hexdump` before blaming the patch tool.
|
|
228
|
+
- `patch`/`write_file` calls have a stream timeout on large payloads — split big edits
|
|
229
|
+
into multiple small calls.
|
|
230
|
+
- Box alignment must be measured in CELL width (`displayWidth`), never JS `.length` —
|
|
231
|
+
emoji (⚡) is 2 cells.
|
|
232
|
+
- PR title MUST be a valid conventional commit with a single scope or the
|
|
233
|
+
`PR Title (conventional-commits)` CI check fails.
|
|
234
|
+
- `git reset --hard` / `git push --delete` are flagged by smart approval — that's
|
|
235
|
+
expected; they're part of the clean-branch flow.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "daedalus-cli",
|
|
3
|
-
"version": "3.25.
|
|
3
|
+
"version": "3.25.1",
|
|
4
4
|
"description": "Local-first AI coding CLI with embedded model router, multi-agent orchestration, and codebase indexing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"start": "tsx src/index.ts",
|
|
22
22
|
"bot": "tsx src/bot/index.ts",
|
|
23
23
|
"dev": "tsx watch src/index.ts",
|
|
24
|
-
"build": "tsc",
|
|
24
|
+
"build": "tsc && node scripts/copy-skills.mjs",
|
|
25
25
|
"lint": "eslint src --ext .ts",
|
|
26
26
|
"prepublishOnly": "npm run build",
|
|
27
27
|
"test": "vitest run",
|