docs(changelog): fix round 4.5b
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
b9d173a7fd
commit
ad053e0e0e
3 changed files with 143 additions and 4 deletions
43
CHANGELOG.md
43
CHANGELOG.md
|
|
@ -30,14 +30,50 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|||
to `scripts/annotate.mjs`, the not-a-gate line and the printed links stay. The printed report now
|
||||
says a Question is answered and Fix and Change notes revise the file.
|
||||
- **`/trekendsession` is operator-only, and the planning and research spawn sites follow the profile.** The model can no longer start `/trekendsession` (`disable-model-invocation: true`). With `--project`, where the resolver runs, `/trekplan` and `/trekresearch` pass the resolved model at their spawn sites, so the `economy` profile gives Sonnet helpers unless the brief's phase signal for that phase names a model; without a resolved model the agent's own `model:` applies (opus for Claude Code's built-in agents), and `/trekexecute`'s step helper and controller stay on opus.
|
||||
- **`~` and `$HOME` in the arguments of `/trekendsession`, `/trekcontinue` and `/trekreview` are no longer expanded** (ARG, fix round 4.5b). The arguments reach the arg parser as text on stdin, not as shell words, so nothing in them is expanded: write the path out (`~/x` stays the three characters `~/x`).
|
||||
|
||||
### Fixed
|
||||
|
||||
Fix round 4.5b (decisions 80 to 87): the round's 39 findings, from the 4.5a review and its execution and three the operator added. Each is fixed, and each has a test seen failing first: on the code at the round's start point (`be0b631`), or, for the 12 ids whose code was already right or lives under `tests/`, under a named mutation (`tests/fix-round-4-5b-red.sh` proves both).
|
||||
|
||||
**Verdict gate**
|
||||
|
||||
- **The verdict gate reads `--repo=<dir>` and refuses an unknown option** (M6). `lib/review/verdict-gate.mjs` takes `--repo <dir>` and `--repo=<dir>`; `--repo=` with no value and any other option, a `--x=value` one included, exit 2 with the usage line, so a misspelt flag no longer skips the stale check. `--json` stays.
|
||||
- **Only a full commit id opens the merge lock** (M11). A `scope_sha_end` must be 40 or 64 hex and equal what `git rev-parse` prints for it, so a SHA-256 repository opens the lock, and a short id, or a branch named like a commit id, reads as stale. The done line (`lib/verification/done-line.mjs`) and the release check (`scripts/release-check.mjs`) take only full commit ids too.
|
||||
- **A failed git call is not measured, not stale** (M4). A `--repo` path that is missing or no repository, and any git call that fails, give exit 2 with a reason that starts `review-not-measured:`; `/trekexecute`'s main-merge gate reports it as "not measured", never green, and the merge stays locked. Handover 6 names the prefix and lists `review_version` 1.1 as current.
|
||||
- **Free text inside the lessons block makes the review stale** (m4). Every line a later commit adds inside Voyage's block in `.claude/rules/voyage-review-lessons.md` must be a valid lesson line or the block's own header line.
|
||||
|
||||
**Park tool**
|
||||
|
||||
- **The park tool moves nothing when it cannot read HEAD** (M7). `lib/util/park-attempt-files.mjs` reads HEAD's paths once (`git ls-tree`) before any change, and exits 2 with nothing unindexed or moved when that read fails or a path in HEAD is missing from the index. Before, a failed `git cat-file -e` read as "not in HEAD", and a committed file was moved.
|
||||
- **A CRLF diff is parked, and the text says what a staged new file gets** (E22c, E22e). The tool reads a diff with CRLF line ends; its header and `/trekexecute` say that it parks every file new in the attempt's diff, untracked or staged but not in HEAD.
|
||||
- **The "Back to planning" save line reads the whole diff from a subdirectory** (M3). Its `git diff` carries `--no-relative`, so `diff.relative=true` no longer leaves files out.
|
||||
|
||||
**Review coordinator and Arm B workflow**
|
||||
|
||||
- **The Arm B workflow keeps the contract's row** (M5, S3, E20). `scripts/trekreview-armB.workflow.mjs` matches a put-back row on the title as the coordinator trims it, so a trimmed title gives no duplicate row, and ranks a conformance/correctness tie as `lib/review/coordinator-contract.mjs` does; the canonical sort of untitled findings is pinned in both.
|
||||
- **The coordinator's text says what the code does with a line number** (M9). A citation that escapes the repo root, or a negative line, refutes a finding; any other line number alone never does, and a line past the end of the file goes to `unverified`.
|
||||
- **The four `--quick` summaries name the brief-conflict rule as the exception to the skipped reasonableness filter** (M2, K3). `/trekreview`'s flag table, the review orchestrator, `docs/command-modes.md` and README say so, and the orchestrator's item 3 names the brief-conflict lowering as the exception to the catalogue reset.
|
||||
|
||||
**Red proof**
|
||||
|
||||
- **One red script for every round** (RS, M1, M1r, E23a, E23b, E23d, E23f). `tests/helpers/red-round.sh` takes a base, the round's ids, the other rounds' ids, a mutation module and the test files; `tests/fix-round-4-5a-red.sh` and `tests/fix-round-4-5b-red.sh` are thin wrappers over it. The judge skips another round's id and reports an unreadable tag such as `[X 1]`; the base run selects every tag with one pattern and carries a timeout; the judge's exit 2 is tested, and a test checks that a result exists before it reads it. The tests the 4.5a discovered-error fix added carry their 4.5a parent tags, so the red script judges them.
|
||||
|
||||
**Commands and docs**
|
||||
|
||||
- **The arguments reach the parser on stdin, never as shell words** (ARG, M8, M10, DJ5). Phase 0 of `/trekendsession` and `/trekcontinue` and Phase 1 of `/trekreview` give `$ARGUMENTS` to `lib/parsers/arg-parser.mjs --stdin` as the one line inside a quoted heredoc, so a `;`, a `$( )` or a glob in them is text. `/trekcontinue` and `/trekendsession` stop on the parser's exit 1 with its `errors`, and when it prints no JSON. `/trekendsession` takes its label as the rest of the text as typed (the parser's `tail`), so a label of several words is kept whole, and its Phase 3 reads the arguments again the same way instead of splicing the label into a shell line, so an apostrophe in the label no longer breaks that line or runs a command.
|
||||
- **The Bash guard blocks a parser heredoc that closes early** (R6). `hooks/scripts/pre-bash-executor.mjs` blocks (`args-heredoc-closed-early`) a command whose `VOYAGE_ARGS_EOF_7F3C9E` heredoc opens unquoted, or whose closing line stands twice or is not the last non-empty line, so a typed line equal to the delimiter cannot end the heredoc and run what follows.
|
||||
- **Every `/trekbrief` exit names Phase 7 with its `auto_result`** (M13, K2). The exit with no research topics runs Phase 7 with `auto_result: manual`, and the "Cancel — do manual" row with `auto_result: cancelled`.
|
||||
- **`/trekplan`'s execute and team exits run Phase 12, and the research loop names its model** (DJ1, DJ2). The "execute" and "team" exits run Phase 12 (`outcome: execute`, `outcome: execute_team`) instead of a bare stop; in `/trekresearch`'s high-effort loop, a turn that spawns an agent passes the resolved model, else `opus`.
|
||||
- **`run_seen` is kept in the progress file** (E14). `/trekexecute` writes it to `progress.json` (template, field table, Phase 7) and Phase 8 reads it from there, so the resume and multi-session paths report it; Handover 5 lists it as optional.
|
||||
- **Applying a lesson writes no pointer through a link or for an ignored file** (DJ4, PTR). `lib/review/recurrence.mjs` skips the `CLAUDE.md` pointer when `CLAUDE.md` is a symlink or git ignores the lessons file, and refuses a lessons file that is a symlink or whose directory lies outside the repo; `/trekexecute` Phase 7.2 commits only the review's paths git does not ignore.
|
||||
- **The research and review texts are said once and pinned exactly** (E17a, E17b, E18a, Da, Db, E16a). The two `/trekresearch` sentences on outbound queries and the F9 triage rows are pinned exactly; the deep-research adapter says where wave 2's contrarian findings merge; README's deep-research parenthesis says "when the engine is active", and the test that no README line stars `security-researcher` reads every line. The next-session validator's refusal of `--state-file` with no value is tested.
|
||||
|
||||
Fix round 4.5a (decisions 57, 67 and 68): the round's 30 findings, where a Voyage control could be bypassed or was too lax, or where the text gave a guarantee no code held. Each is fixed, and each has a test that fails on the code before it, except DJ, whose sentences already stood and whose pins fail when they are deleted (`tests/fix-round-4-5a-red.sh` proves every other id red at the round's start point, and DJ under its two mutations).
|
||||
|
||||
**Execute**
|
||||
|
||||
- **The merge lock refuses a review of an older commit** (R6). `lib/review/verdict-gate.mjs` takes `--repo <dir>`: an ALLOW or WARN review then opens only when its `scope_sha_end` is HEAD, or an ancestor of HEAD whose later commits (side branches included) change nothing but the review lessons and the `CLAUDE.md` pointer; anything else, a failed git call included, exits 2 with a reason that starts `review-stale` (the new `lib/review/reviewed-commit.mjs`). `/trekexecute` Phase 7.2 and the main-merge lock run the gate with `--repo .`, so the merge stays closed with the decline reason `review-stale`, also on `--resume`.
|
||||
- **The merge lock refuses a review of an older commit** (R6). `lib/review/verdict-gate.mjs` takes `--repo <dir>`: an ALLOW or WARN review then opens only when its `scope_sha_end` is HEAD, or an ancestor of HEAD whose later commits (side branches included) change nothing but the review lessons and the `CLAUDE.md` pointer; anything else exits 2 with a reason that starts `review-stale` (the new `lib/review/reviewed-commit.mjs`), and a failed git call exits 2 with a reason that starts `review-not-measured:`, not `review-stale` (fix round 4.5b). `/trekexecute` Phase 7.2 and the main-merge lock run the gate with `--repo .`, so the merge stays closed with the decline reason `review-stale`, also on `--resume`.
|
||||
- **`/trekexecute` runs the brief check it promised** (finding #33). With `--project` and a `brief.md`, Phase 1 runs the brief validator and the phase-model resolver (`lib/profiles/resolver.mjs --resolve-phase-model`) as `/trekplan` does, uses the effort it returns, and halts only on `BRIEF_V51_MISSING_SIGNALS`. Low effort runs the plan as one session, step after step; high effort changes nothing, and the text that set `gates_mode` from the effort and its `gates_mode_flag_override` record are gone.
|
||||
- **`/trekexecute` names and reads `--profile` and `--gates`** (finding #30). The argument hint, the usage block and Phase 1 carry both flags, Phase 1 strips `--profile <name>` before it reads the plan path, and the text says the profile changes no model here: the step helper and the controller stay on opus.
|
||||
- **The completion gate says which of its checks are commands and which are the executor's judgement** (finding #28). It no longer calls the counter check and the audit deterministic, and its two dead line references are gone.
|
||||
|
|
@ -98,11 +134,13 @@ Fix round 4.5a (decisions 57, 67 and 68): the round's 30 findings, where a Voyag
|
|||
|
||||
**Across the round**
|
||||
|
||||
- **The texts next to the fixes say the same** (siblings found during the round): `/trekreview`, the review reference and the Arm B coordinator prompt no longer drop a finding whose rule key is unknown; `/trekbrief` writes its stats record on every exit of its manual and auto paths, says that `--gates` adds one pause before its auto chain, and that the chain ends at the plan; `/trekexecute` says `--gates` changes nothing there, checks the wave marker before a low-effort single session, and names no validator check that does not exist; plan mode goes through the plan approval before it prints the `/trekexecute` line; the gates shim reads `--gates=true` as on.
|
||||
- **The texts next to the fixes say the same** (siblings found during the round): `/trekreview`, the review reference and the Arm B coordinator prompt no longer drop a finding whose rule key is unknown; `/trekbrief` writes its stats record on every exit of its manual and auto paths, says that `--gates` adds one pause before its auto chain, and that the chain ends at the plan; `/trekexecute` says `--gates` changes nothing there, checks the wave marker before a low-effort single session, and names no validator check that does not exist; plan mode goes through the plan approval before it prints the `/trekexecute` line; the commands read only the two-token `--gates <value>` form, and `--gates=true` is the gates shim's own form (`lib/util/autonomy-gate.mjs`), which it reads as `--gates true`.
|
||||
|
||||
### Known issues
|
||||
|
||||
- **A plan's `profile:` field has no writer.** README, `docs/`, `/trekexecute` and `/trekcontinue` say a plan carries or passes on a profile, but no command writes `profile:` to a plan; the plan validator's `MANIFEST_PROFILE_DRIFT` check reads it, and `resolveTrekcontinueProfile` has no caller outside its tests. Left whole for a later hardening part, which chooses between writing the field and taking the promises out.
|
||||
- **Splices and dropped `--x=` options outside fix round 4.5b** (decision 82). The commands' bash blocks still splice `{placeholder}` values into shell lines outside the four places the round closed (the Phase 0 parser lines of `/trekendsession`, `/trekcontinue` and `/trekreview`, and `/trekendsession` Phase 3), for example `"{brief_path}"` in `/trekplan` and the unquoted `{project_dir}` in `/trekendsession` Phase 4; and the release check, the lessons apply (`lib/review/recurrence.mjs`), the next-session validator and the park tool still drop an unknown `--x=` option without a word. One open finding, for fix round 4.5c or 4.5d.
|
||||
- **Two 4.5b findings moved to fix round 4.5c.** M12 (`lib/review/reviewed-commit.mjs` makes four git calls per path per commit; at most two paths per commit reach that loop) goes with 4.5c's single `git cat-file --batch` read, and Dc (the trekcontinue `line_ref` row in `tests/fixtures/jsonl-schemas.md`) with 4.5c's change of `line_ref` to a heading anchor.
|
||||
|
||||
### Doors
|
||||
|
||||
|
|
@ -111,6 +149,7 @@ Fix round 4.5a (decisions 57, 67 and 68): the round's 30 findings, where a Voyag
|
|||
- two-way: skill annotating and its pointers in three commands (order B) — revert the commit; the
|
||||
script, the page, the stored notes and the approval checks are unchanged.
|
||||
- two-way: fix round 4.5a (decisions 57, 67, 68) — a revert restores the old texts and checks
|
||||
- two-way: fix round 4.5b (decisions 80 to 87) — a revert restores the old checks, texts and red script and takes out the Bash guard's heredoc rule; `review.md` keeps `review_version` 1.1 either way.
|
||||
|
||||
## v6.5.0 — 2026-10-18 — Three skills for brief, criteria and review, English labels, and three trial-5 fixes
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@
|
|||
// Untagged tests (prefixes `helpers:`, `step 25:`, `keep:`, `control:`,
|
||||
// `arch:`, `e2e script:`, `red script:`, `CHANGELOG:`) are outside the
|
||||
// round's id list; a `[M1r]` test carries a 4.5b id and is that round's to
|
||||
// judge.
|
||||
// judge. Fix round 4.5b edits some pins here in place where its fixes change
|
||||
// the text they pin (for example the CHANGELOG siblings entry, K4): each keeps
|
||||
// its tag or untagged prefix and still fails at ab6b32c.
|
||||
// #23 code-correctness-reviewer cites a "MANDATORY OVERRIDE rule above"
|
||||
// that is no longer there; the sentence says the rule itself.
|
||||
// #24 research-scout says "Try Tavily first" but its tools held no Tavily
|
||||
|
|
@ -1747,7 +1749,8 @@ const SIBLINGS_ENTRY = '- **The texts next to the fixes say the same** (siblings
|
|||
+ 'record on every exit of its manual and auto paths, says that `--gates` adds one pause before its auto chain, and that the chain '
|
||||
+ 'ends at the plan; `/trekexecute` says `--gates` changes nothing there, checks the wave marker before a low-effort single session, '
|
||||
+ 'and names no validator check that does not exist; plan mode goes through the plan approval before it prints the `/trekexecute` '
|
||||
+ 'line; the gates shim reads `--gates=true` as on.';
|
||||
+ 'line; the commands read only the two-token `--gates <value>` form, and `--gates=true` is the gates shim\'s own form '
|
||||
+ '(`lib/util/autonomy-gate.mjs`), which it reads as `--gates true`.';
|
||||
|
||||
test('CHANGELOG: ### Fixed holds the siblings entry, exactly', () => {
|
||||
assert.ok(roundBullets('### Fixed').includes(SIBLINGS_ENTRY), '### Fixed has no siblings entry with the exact text');
|
||||
|
|
|
|||
|
|
@ -48,6 +48,16 @@
|
|||
// M1 No test name in the 4.5a prose file starts with `found in execution:`;
|
||||
// the tests f6bdc2d added carry their 4.5a parent tag (red under the
|
||||
// M1 mutation, which puts the names back).
|
||||
// CHANGELOG (the round's entry in the existing Unreleased section):
|
||||
// K4 the siblings entry says the commands read only the two-token
|
||||
// `--gates <value>` form and that `--gates=true` is the gates shim's own.
|
||||
// M4 the merge-lock entry says a failed git call is reported as
|
||||
// `review-not-measured:`, not `review-stale`.
|
||||
// M2 ### Fixed records the brief-conflict exception in the four `--quick`
|
||||
// summaries.
|
||||
// ARG ### Fixed names the Bash-guard block on a parser heredoc that closes
|
||||
// early (R6), and ### Changed says `~` and `$HOME` in the arguments are
|
||||
// no longer expanded.
|
||||
// No static import of a new export: the file must load at be0b631.
|
||||
// Fix the SOURCE a pin guards, not the pin.
|
||||
|
||||
|
|
@ -503,3 +513,90 @@ test('[M1] no test name in the 4.5a prose file starts with found in execution:',
|
|||
const untagged = names.filter((n) => n.startsWith('found in execution:'));
|
||||
assert.deepEqual(untagged, [], `${PROSE_4_5A} still names ${untagged.length} test(s) "found in execution:"`);
|
||||
});
|
||||
|
||||
// --- K4 / M4 / M2 / ARG: the round's CHANGELOG entry --------------------------------
|
||||
// The round's entry stands in the existing Unreleased section (no release lies
|
||||
// between 4.5a and 4.5b). The section is found by its title, by the rule
|
||||
// tests/helpers/changelog-section.mjs uses for the 6.4.0 delivery:
|
||||
// `## Unreleased — <title>` before the release, `## vX.Y.Z — <date> — <title>`
|
||||
// after it, exactly once, up to the next `## ` heading. The helper is bound to
|
||||
// the 6.4.0 title, so its rule is repeated here for this section's title.
|
||||
|
||||
const CHANGELOG_TITLE = "The annotating skill, the run coupling and P10's model-free part";
|
||||
const CHANGELOG_HEADING = new RegExp(`^## (?:Unreleased|v\\d+\\.\\d+\\.\\d+ — \\d{4}-\\d{2}-\\d{2}) — ${CHANGELOG_TITLE.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`);
|
||||
|
||||
/** The lines of the round's CHANGELOG section, heading excluded. */
|
||||
function changelogSection() {
|
||||
const lines = read('CHANGELOG.md').split('\n');
|
||||
const at = [];
|
||||
lines.forEach((l, i) => { if (CHANGELOG_HEADING.test(l.replace(/\s+$/, ''))) at.push(i); });
|
||||
assert.equal(at.length, 1, `CHANGELOG.md must hold the "${CHANGELOG_TITLE}" section exactly once (found ${at.length})`);
|
||||
let end = lines.length;
|
||||
for (let i = at[0] + 1; i < lines.length; i++) if (/^## /.test(lines[i])) { end = i; break; }
|
||||
return lines.slice(at[0] + 1, end);
|
||||
}
|
||||
|
||||
/** The bullets of one `### ` subsection of the round's CHANGELOG section, each flattened to one line. */
|
||||
function changelogBullets(heading) {
|
||||
const lines = changelogSection();
|
||||
const s = lines.findIndex((l) => l.replace(/\s+$/, '') === heading);
|
||||
assert.ok(s !== -1, `the "${CHANGELOG_TITLE}" section of CHANGELOG.md must have "${heading}"`);
|
||||
const out = [];
|
||||
for (const l of lines.slice(s + 1)) {
|
||||
if (/^### /.test(l)) break;
|
||||
if (/^- /.test(l)) out.push(l);
|
||||
else if (out.length && l.trim() !== '' && /^\s/.test(l)) out[out.length - 1] += ` ${l}`;
|
||||
else if (l.trim() !== '') out.push('');
|
||||
}
|
||||
return out.filter((b) => b !== '').map(flat);
|
||||
}
|
||||
|
||||
test('[K4] the CHANGELOG names --gates=true as the shim\'s own form', () => {
|
||||
const hits = changelogBullets('### Fixed').filter((b) => b.startsWith('- **The texts next to the fixes say the same**'));
|
||||
assert.equal(hits.length, 1, `### Fixed must hold one siblings entry; found ${hits.length}`);
|
||||
assert.ok(hits[0].includes('the commands read only the two-token `--gates <value>` form'),
|
||||
`the siblings entry does not say the commands read only the two-token \`--gates <value>\` form: ${hits[0]}`);
|
||||
assert.ok(hits[0].includes('`--gates=true` is the gates shim\'s own form'),
|
||||
`the siblings entry does not name \`--gates=true\` as the gates shim's own form: ${hits[0]}`);
|
||||
assert.doesNotMatch(hits[0], /the gates shim reads `--gates=true` as on\./,
|
||||
`the siblings entry still ends on the gates shim reading \`--gates=true\` as on, which reads as a command form: ${hits[0]}`);
|
||||
});
|
||||
|
||||
test('[M4] the Unreleased entry says review-not-measured for a failed git call', () => {
|
||||
const hits = changelogBullets('### Fixed').filter((b) => b.startsWith('- **The merge lock refuses a review of an older commit**'));
|
||||
assert.equal(hits.length, 1, `### Fixed must hold one merge-lock entry; found ${hits.length}`);
|
||||
assert.doesNotMatch(hits[0], /a failed git call included/,
|
||||
`the merge-lock entry still counts a failed git call among the \`review-stale\` reasons: ${hits[0]}`);
|
||||
const said = sentencesWith(hits[0], 'failed git call');
|
||||
assert.ok(said.some((s) => /a failed git call exits 2 with a reason that starts `review-not-measured:`, not `review-stale`/.test(s)),
|
||||
`the merge-lock entry does not say a failed git call exits 2 with \`review-not-measured:\`, not \`review-stale\`: ${said.join(' | ') || hits[0]}`);
|
||||
});
|
||||
|
||||
test('[M2] the Unreleased entry records the brief-conflict exception in the flag summaries', () => {
|
||||
const hits = changelogBullets('### Fixed').filter((b) => b.includes('`--quick`') && b.includes('brief-conflict rule'));
|
||||
assert.equal(hits.length, 1, `### Fixed must hold one entry on the \`--quick\` summaries and the brief-conflict rule; found ${hits.length}`);
|
||||
assert.match(hits[0], /name the brief-conflict rule as the exception to the skipped reasonableness filter/,
|
||||
`the entry does not say the summaries name the brief-conflict rule as the exception: ${hits[0]}`);
|
||||
for (const where of ['`/trekreview`', 'the review orchestrator', '`docs/command-modes.md`', 'README']) {
|
||||
assert.ok(hits[0].includes(where), `the entry does not name ${where} among the four summaries: ${hits[0]}`);
|
||||
}
|
||||
});
|
||||
|
||||
test('[ARG] the CHANGELOG names the Bash-guard block on a parser heredoc that closes early', () => {
|
||||
const hits = changelogBullets('### Fixed').filter((b) => b.includes('`args-heredoc-closed-early`'));
|
||||
assert.equal(hits.length, 1, `### Fixed must hold one entry naming \`args-heredoc-closed-early\`; found ${hits.length}`);
|
||||
assert.ok(hits[0].includes('`hooks/scripts/pre-bash-executor.mjs`'), `the entry does not name the Bash guard's file: ${hits[0]}`);
|
||||
assert.ok(hits[0].includes('`VOYAGE_ARGS_EOF_7F3C9E`'), `the entry does not name the heredoc's closing line: ${hits[0]}`);
|
||||
assert.match(hits[0], /not the last non-empty line/, `the entry does not say when the guard blocks: ${hits[0]}`);
|
||||
assert.match(hits[0], /\(R6\)/, `the entry does not carry the R6 mark: ${hits[0]}`);
|
||||
});
|
||||
|
||||
test('[ARG] the CHANGELOG says ~ and $HOME in the arguments are no longer expanded', () => {
|
||||
const hits = changelogBullets('### Changed').filter((b) => b.includes('`~`') && b.includes('`$HOME`'));
|
||||
assert.equal(hits.length, 1, `### Changed must hold one entry on \`~\` and \`$HOME\`; found ${hits.length}`);
|
||||
for (const cmd of ['`/trekendsession`', '`/trekcontinue`', '`/trekreview`']) {
|
||||
assert.ok(hits[0].includes(cmd), `the entry does not name ${cmd}: ${hits[0]}`);
|
||||
}
|
||||
assert.match(hits[0], /are no longer expanded/, `the entry does not say they are no longer expanded: ${hits[0]}`);
|
||||
assert.match(hits[0], /write the path out/, `the entry does not tell the reader to write the path out: ${hits[0]}`);
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue