diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index b6be6fb4..53c5ca90 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "commitlore", "displayName": "CommitLore", - "version": "1.2.4", + "version": "1.2.5", "description": "Recorded decisions from git history, delivered to the agent before it edits. Constraints, alternatives already ruled out, and warnings left by whoever was here last.", "author": { "name": "MongLong0214", diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index da184b0d..268d8063 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "commitlore", - "version": "1.2.4", + "version": "1.2.5", "description": "Decision memory from Git history, with verified capture for coding sessions.", "author": { "name": "MongLong0214", diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bf2c752..e668d61e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,65 @@ Release notes for 1.0.0, 1.0.1 and 1.0.2 are on the [GitHub releases page](https://github.com/MongLong0214/commitlore/releases); they were not written here. +## 1.2.5 + +Two flags on `capture` did nothing and said nothing; a third refusal knew the +fix and did not say it. + +**`capture --out` exited 0 and never wrote the file (#878).** The flag is +documented as "write the pending nonce to a file", and prompt-only mode — get the +nonce, hand the prompt to a model, come back with `--draft` — is the step it +exists for. That was the one run where the pipeline reported `nonce: null` while +prepare had already persisted a real transaction under a real nonce, so the write +was guarded out. Measured by the reporter as 3 runs, 3 exit 0, 3 missing files, +with and without `--diff`. The nonce is now reported, so `--out` writes it and +`--json` carries it. + +**`capture --diff` was accepted, ignored by prepare, and honoured by verify +(#877).** Passing the *same* `--diff` file to both steps failed whenever that +file was not byte-identical to the staged diff: +`discarded record 0 (source-mismatch): diff hash does not match the prepared +transaction`. That message is about the draft's sources, and the fault was +entirely the flag's — the reporter spent several attempts re-checking quotes and +locators that were never wrong. + +The refusal itself was right and stays. A capture transaction binds to the staged +diff, which prepare, verify and stage each recompute independently, because every +binding is computed server-side and never from the caller. `--diff` cannot select +a different diff; it can only assert what is staged. So it is now refused where +that is decidable — up front, exit 2, naming the flag and naming the way out +(`git reset --soft`, which is what the reporter had to find on their own) — rather +than several steps later against the record. A run refused this way also leaves no +pending transaction behind; the old path wrote two per attempt. + +`--diff` byte-identical to the staged diff keeps working, and the help text now +says what the flag does rather than implying an override it never had. + +**`unknown-key` now names the `X-` form the author could have written (#881).** +Claude Code instructs every session to end its commit message with +`Claude-Session:`, so the key arrives by default, the hook refuses it, the commit +is lost, and an agent that cannot see the repository's earlier commits writes it +again. Reported twice in one day in two repositories by the same author, the +second time after already knowing about the first, because `X-` is not the kind of +thing that stays in mind between repositories. + +``` +31: unknown-key Claude-Session — got "Claude-Session", + want "a key from SPEC §3, or X-Claude-Session if this is your own metadata" +``` + +Nothing is accepted that was not accepted before, and nothing is rewritten: SPEC +§6 says the message is not modified, and silently renaming someone's trailer would +be worse than refusing it. This only says the name. Two keys are deliberately not +offered the prefix — one whose value reads as a sentence, which keeps the #647 +answer, because that author's problem is that their prose became metadata; and one +that differs from a SPEC §3 key only by case, because `X-limit` would be a valid +record carrying the wrong key. + +`spec/fixtures/invalid/03-unknown-key.expected.json` moves with it. The violation +it pins is unchanged and `Constraint:` is still refused; only the advisory `want` +text differs. + ## 1.2.4 `doctor` blamed the hook that worked, and prescribed reinstalling it. diff --git a/README.ja.md b/README.ja.md index 2fb227b1..1977f407 100644 --- a/README.ja.md +++ b/README.ja.md @@ -47,18 +47,18 @@

```bash -curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.sh | sh -s v1.2.4 +curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.sh | sh -s v1.2.5 ```
先にインストーラーを読みたいですか? ```bash -curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.sh -sh install.sh v1.2.4 +curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.sh +sh install.sh v1.2.5 # あるいはスクリプトを使わずに。スクリプトが作るチェックアウトは自分でも作れます。 -git clone --depth 1 --branch v1.2.4 https://github.com/MongLong0214/commitlore +git clone --depth 1 --branch v1.2.5 https://github.com/MongLong0214/commitlore node commitlore/dist/commitlore.mjs --version ``` @@ -107,13 +107,13 @@ CommitLore はその判断をコードのそばに残します。 macOS と Linux: ```bash -curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.sh | sh -s v1.2.4 +curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.sh | sh -s v1.2.5 ``` Windows: ```powershell -& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.ps1))) v1.2.4 +& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.ps1))) v1.2.5 ``` Node.js 22.23.2+ と Git が必要です。スクリプトは何かを書き込む前に両方を確認します。 diff --git a/README.ko.md b/README.ko.md index a5883f2c..6b39adb0 100644 --- a/README.ko.md +++ b/README.ko.md @@ -47,18 +47,18 @@

```bash -curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.sh | sh -s v1.2.4 +curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.sh | sh -s v1.2.5 ```
먼저 설치기를 읽어 보고 싶나요? ```bash -curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.sh -sh install.sh v1.2.4 +curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.sh +sh install.sh v1.2.5 # 또는 스크립트를 건너뜁니다. 스크립트가 만드는 체크아웃은 직접 만들 수 있습니다. -git clone --depth 1 --branch v1.2.4 https://github.com/MongLong0214/commitlore +git clone --depth 1 --branch v1.2.5 https://github.com/MongLong0214/commitlore node commitlore/dist/commitlore.mjs --version ``` @@ -107,13 +107,13 @@ CommitLore는 그 판단을 코드 곁에 보관합니다. macOS와 Linux: ```bash -curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.sh | sh -s v1.2.4 +curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.sh | sh -s v1.2.5 ``` Windows: ```powershell -& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.ps1))) v1.2.4 +& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.ps1))) v1.2.5 ``` Node.js 22.23.2+와 Git이 필요합니다. 스크립트는 무엇이든 쓰기 전에 둘을 확인합니다. diff --git a/README.md b/README.md index 365acbd0..3a242739 100644 --- a/README.md +++ b/README.md @@ -48,18 +48,18 @@

```bash -curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.sh | sh -s v1.2.4 +curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.sh | sh -s v1.2.5 ```
Prefer to read the installer first? ```bash -curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.sh -sh install.sh v1.2.4 +curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.sh +sh install.sh v1.2.5 # Or skip the script: the checkout it makes is one you can make yourself. -git clone --depth 1 --branch v1.2.4 https://github.com/MongLong0214/commitlore +git clone --depth 1 --branch v1.2.5 https://github.com/MongLong0214/commitlore node commitlore/dist/commitlore.mjs --version ``` @@ -109,13 +109,13 @@ preserve, not for narrating every change. macOS and Linux: ```bash -curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.sh | sh -s v1.2.4 +curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.sh | sh -s v1.2.5 ``` Windows: ```powershell -& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.ps1))) v1.2.4 +& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.ps1))) v1.2.5 ``` Requires Node.js 22.23.2+ and Git. The script checks both before it writes anything. diff --git a/README.zh-CN.md b/README.zh-CN.md index 8790036f..df475c1a 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -47,18 +47,18 @@

```bash -curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.sh | sh -s v1.2.4 +curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.sh | sh -s v1.2.5 ```
想先阅读安装器吗? ```bash -curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.sh -sh install.sh v1.2.4 +curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.sh +sh install.sh v1.2.5 # 或者跳过脚本:它创建的检出,你自己也能创建。 -git clone --depth 1 --branch v1.2.4 https://github.com/MongLong0214/commitlore +git clone --depth 1 --branch v1.2.5 https://github.com/MongLong0214/commitlore node commitlore/dist/commitlore.mjs --version ``` @@ -105,13 +105,13 @@ CommitLore 把那份判断留在代码旁边。 macOS 和 Linux: ```bash -curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.sh | sh -s v1.2.4 +curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.sh | sh -s v1.2.5 ``` Windows: ```powershell -& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.ps1))) v1.2.4 +& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.ps1))) v1.2.5 ``` 需要 Node.js 22.23.2+ 和 Git。脚本会在写入任何内容前检查两者。 diff --git a/dist/commands/capture.js b/dist/commands/capture.js index e13a16a2..21d885e9 100644 --- a/dist/commands/capture.js +++ b/dist/commands/capture.js @@ -100,14 +100,32 @@ export const runCapture = (opts) => { const runCapturePipeline = (opts) => { const { transcriptPath, diffPath, draftPath, cwd } = opts; const transcript = readCallerFile(transcriptPath); - // Prepare hashes `git diff --cached` itself, so verification has to be given - // the same bytes. This used to default to the empty string, whose hash never - // matches -- every record was refused with `source-mismatch` and the command - // printed `no record staged`, so `capture --draft` could not succeed at all - // unless the caller happened to pass a --diff file byte-identical to the - // staged diff. A caller-supplied --diff that differs is still a real mismatch - // and is still refused. - const diff = diffPath ? readCallerFile(diffPath) : execGitOrThrow(['diff', '--cached'], { cwd }); + // The transaction binds to the staged diff and only to that: prepare hashes + // `git diff --cached` itself, and stage recomputes it a third time before + // writing, because every binding is computed server-side and never from the + // caller (capture-stage.ts). So `--diff` can assert what is staged; it cannot + // override it. + // + // It used to default to the empty string, whose hash never matches -- every + // record was refused with `source-mismatch` and the command printed `no record + // staged`, so `capture --draft` could not succeed at all unless the caller + // happened to pass a --diff file byte-identical to the staged diff. + // + // A --diff that differs is still refused. What #877 is about is where that + // refusal surfaced: prepare wrote a pending file for a run that could not + // succeed, and verify then blamed the draft -- `source-mismatch: diff hash + // does not match the prepared transaction` -- for a fault belonging entirely + // to the flag. The reporter re-checked quotes and locators that were never + // wrong. It is refused here instead, before prepare, naming the flag. + const callerDiff = diffPath === undefined ? undefined : readCallerFile(diffPath); + const diff = execGitOrThrow(['diff', '--cached'], { cwd }); + if (callerDiff !== undefined && callerDiff !== diff) { + throw markCaptureError(new Error(`--diff ${JSON.stringify(diffPath)} is not the staged diff. A capture transaction ` + + 'binds to the staged diff -- prepare, verify and stage each recompute it, so --diff ' + + 'can assert what is staged but cannot override it. Stage the change you are ' + + 'recording; to record against a commit that already exists, soft-reset it first ' + + '(git reset --soft HEAD~1).'), 'usage'); + } // 1. Prepare: compute bindings, generate prompt, persist prepared transaction const prepareResult = prepareCaptureContext({ cwd, @@ -125,10 +143,17 @@ const runCapturePipeline = (opts) => { process.stderr.write(`commitlore capture: ${prepareResult.policy_error}\ncommitlore capture: the built-in defaults were used for this capture\n`); } // 2. If no draft provided, print the prompt contract and exit (prompt-only mode) + // + // The nonce is reported, not dropped (#878). Prepare has already persisted the + // transaction under it, and prompt-only is the step `--out` exists for: get the + // nonce, hand the prompt to a model, come back with --draft. Returning null + // here made `if (options.out && result.nonce)` false on exactly that run, so + // --out wrote nothing and said nothing, and a scripted caller had no handle on + // which transaction it was completing until verify failed several steps later. if (!draftPath) { return { outcome: 'empty', - nonce: null, + nonce: prepareResult.nonce, staged: false, prompt: prepareResult.prompt, transcript_window: prepareResult.transcript_window, @@ -267,7 +292,8 @@ export const register = (program) => { // action below instead, where it applies only to the capture flow itself. .option('--transcript ', 'path to the session transcript file (the prompt carries its last 256 KiB; ' + 'COMMITLORE_TRANSCRIPT_BUDGET_BYTES changes that, and verification always reads all of it)') - .option('--diff ', 'path to the diff file (defaults to the staged diff)') + .option('--diff ', 'assert the staged diff equals this file; the transaction always binds to the staged diff, ' + + 'so this cannot select a different one') .option('--draft ', 'path to the draft JSON file (omit for prompt-only mode)') .option('--out ', 'write the pending nonce to a file') .option('--shadow', 'measure historical capture candidates without writing anything') diff --git a/dist/commands/capture.js.map b/dist/commands/capture.js.map index 401907c1..47c45865 100644 --- a/dist/commands/capture.js.map +++ b/dist/commands/capture.js.map @@ -1 +1 @@ -{"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/commands/capture.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/commands/capture.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commitlore.mjs b/dist/commitlore.mjs index a0cfcb6b..dbc2b9e7 100755 --- a/dist/commitlore.mjs +++ b/dist/commitlore.mjs @@ -11887,6 +11887,14 @@ var FORMAT_WANT = { "CommitLore-Version": "semver" }; var UNKNOWN_KEY_WANT = "a key from SPEC \xA73 or X-"; +var unknownKeyWant = (key) => { + if (KNOWN_KEYS.some((known) => known.toLowerCase() === key.toLowerCase())) { + return UNKNOWN_KEY_WANT; + } + const prefixed = `X-${key}`; + if (!EXTENSION_KEY_RE.test(prefixed)) return UNKNOWN_KEY_WANT; + return `a key from SPEC \xA73, or ${prefixed} if this is your own metadata`; +}; var PROSE_KEY_WANT = 'a key from SPEC \xA73 or X- \u2014 or, if this line is a sentence rather than metadata, reword it: git reads the last paragraph as trailers, so prose beginning "Word:" becomes one. Moving the record block below it works too.'; var looksLikeProse = (value) => /\s/.test(value.trim()) && /[.!?]$/.test(value.trim()); var RULED_OUT_CODE_SPAN_WANT = 'alternative | reason \u2014 the alternative opens a code span that closes after the separator, so the first "|" sits inside quoted text; there is no escape, so rephrase the alternative to hold no "|"'; @@ -11923,7 +11931,7 @@ var violationFor = (trailer, field) => { value: trailer.value, rule: "unknown-key", got: trailer.key, - want: looksLikeProse(trailer.value) ? PROSE_KEY_WANT : UNKNOWN_KEY_WANT + want: looksLikeProse(trailer.value) ? PROSE_KEY_WANT : unknownKeyWant(trailer.key) }; } const enumWant = ENUM_WANT[trailer.key]; @@ -18124,7 +18132,16 @@ var runCapture = (opts) => { var runCapturePipeline = (opts) => { const { transcriptPath, diffPath, draftPath, cwd } = opts; const transcript = readCallerFile(transcriptPath); - const diff = diffPath ? readCallerFile(diffPath) : execGitOrThrow(["diff", "--cached"], { cwd }); + const callerDiff = diffPath === void 0 ? void 0 : readCallerFile(diffPath); + const diff = execGitOrThrow(["diff", "--cached"], { cwd }); + if (callerDiff !== void 0 && callerDiff !== diff) { + throw markCaptureError( + new Error( + `--diff ${JSON.stringify(diffPath)} is not the staged diff. A capture transaction binds to the staged diff -- prepare, verify and stage each recompute it, so --diff can assert what is staged but cannot override it. Stage the change you are recording; to record against a commit that already exists, soft-reset it first (git reset --soft HEAD~1).` + ), + "usage" + ); + } const prepareResult = prepareCaptureContext({ cwd, transcript, @@ -18143,7 +18160,7 @@ commitlore capture: the built-in defaults were used for this capture if (!draftPath) { return { outcome: "empty", - nonce: null, + nonce: prepareResult.nonce, staged: false, prompt: prepareResult.prompt, transcript_window: prepareResult.transcript_window, @@ -18263,7 +18280,10 @@ var register3 = (program3) => { ).option( "--transcript ", "path to the session transcript file (the prompt carries its last 256 KiB; COMMITLORE_TRANSCRIPT_BUDGET_BYTES changes that, and verification always reads all of it)" - ).option("--diff ", "path to the diff file (defaults to the staged diff)").option("--draft ", "path to the draft JSON file (omit for prompt-only mode)").option("--out ", "write the pending nonce to a file").option("--shadow", "measure historical capture candidates without writing anything").option("--since ", "exclusive historical lower bound for --shadow").option("--json", "emit structured JSON output").option( + ).option( + "--diff ", + "assert the staged diff equals this file; the transaction always binds to the staged diff, so this cannot select a different one" + ).option("--draft ", "path to the draft JSON file (omit for prompt-only mode)").option("--out ", "write the pending nonce to a file").option("--shadow", "measure historical capture candidates without writing anything").option("--since ", "exclusive historical lower bound for --shadow").option("--json", "emit structured JSON output").option( "--unattended", `declare this capture unattended: prepared, verified and staged without asking. Refused unless the repository opted in (${POLICY_FILE_NAME}: "unattended": true, mode "auto")` ).addHelpText( diff --git a/dist/core/schema.js b/dist/core/schema.js index 8f5e1082..e0ac1a4b 100644 --- a/dist/core/schema.js +++ b/dist/core/schema.js @@ -51,6 +51,43 @@ const FORMAT_WANT = { 'CommitLore-Version': 'semver', }; const UNKNOWN_KEY_WANT = 'a key from SPEC §3 or X-'; +/** + * Name the `X-` form the author could have written, rather than its shape (#881). + * + * `X-` is already in the answer, and it was not enough: Claude Code tells + * every session to end its commit message with `Claude-Session:`, so the key + * arrives by default, the hook refuses it, the commit is lost, and the agent — + * which cannot see the repository's earlier commits — writes it again. Reported + * twice in one day in two repositories by the same author, the second time after + * already knowing about the first, because `X-` is not the kind of thing that + * stays in mind between repositories. Naming `X-Claude-Session` turns a refused + * commit into a corrected one. + * + * Not a rewrite: SPEC §6 says the message is not modified, and silently renaming + * someone's trailer would be worse than refusing it. This only says the name. + * + * Two keys are deliberately not offered the prefix: + * + * - one whose value reads as a sentence, which keeps the #647 answer instead — + * that author's problem is that their prose became metadata, and `X-` is the + * wrong door for them. That branch is chosen before this function is called. + * - one that differs from a SPEC §3 key only by case. `limit:` is `Limit:` + * miswritten, not an extension, and `X-limit` would be a valid record holding + * the wrong key. SPEC §3 matches case-sensitively and `KNOWN_KEYS` still does, + * so the plain answer — which names §3 first — is the useful one here. + * + * Anything the prefix cannot rescue (a leading digit, an underscore) falls back + * too: `EXTENSION_KEY_RE` is asked rather than assumed. + */ +const unknownKeyWant = (key) => { + if (KNOWN_KEYS.some((known) => known.toLowerCase() === key.toLowerCase())) { + return UNKNOWN_KEY_WANT; + } + const prefixed = `X-${key}`; + if (!EXTENSION_KEY_RE.test(prefixed)) + return UNKNOWN_KEY_WANT; + return `a key from SPEC §3, or ${prefixed} if this is your own metadata`; +}; /** * The same violation, told to someone who did not write a trailer (#647). * @@ -165,7 +202,7 @@ const violationFor = (trailer, field) => { value: trailer.value, rule: 'unknown-key', got: trailer.key, - want: looksLikeProse(trailer.value) ? PROSE_KEY_WANT : UNKNOWN_KEY_WANT, + want: looksLikeProse(trailer.value) ? PROSE_KEY_WANT : unknownKeyWant(trailer.key), }; } const enumWant = ENUM_WANT[trailer.key]; diff --git a/dist/core/schema.js.map b/dist/core/schema.js.map index 251df3c2..14398754 100644 --- a/dist/core/schema.js.map +++ b/dist/core/schema.js.map @@ -1 +1 @@ -{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/install.ps1 b/install.ps1 index 24558bcb..7d38ee6f 100644 --- a/install.ps1 +++ b/install.ps1 @@ -1,8 +1,8 @@ <# Installs commitlore from source on Windows, for any agent that is not Claude Code. - irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.ps1 | iex - & ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.ps1))) v1.2.4 + irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.ps1 | iex + & ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.ps1))) v1.2.5 Claude Code users do not need this script. The repository is itself a plugin marketplace (ADR-0011), so two /plugin commands register the MCP server, the diff --git a/install.sh b/install.sh index c69df874..c1d78dce 100755 --- a/install.sh +++ b/install.sh @@ -1,8 +1,8 @@ #!/bin/sh # Installs commitlore from source, for any agent that is not Claude Code. # -# curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.sh | sh -# curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.sh | sh -s v1.2.4 +# curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.sh | sh +# curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.sh | sh -s v1.2.5 # # **Claude Code users do not need this script.** The repository is itself a # plugin marketplace (ADR-0011), so two `/plugin` commands register the MCP diff --git a/installer/canonical-artifact.json b/installer/canonical-artifact.json index 06375734..ac428bdc 100644 --- a/installer/canonical-artifact.json +++ b/installer/canonical-artifact.json @@ -15,10 +15,10 @@ "tsconfig.json", "src" ], - "sha256": "647fdb182d701fe945822747cdf93142fa1834ba9f663e438e71b8a58117d979" + "sha256": "a9983e1d679fb5ac209c43b7b3e67c5c14fa540d7153a40421194cae60e96310" }, "artifact": { - "sha256": "9254b0587193cda00301cc8347daf77f8ec93339af6ae79d1cfb4ccfa7d67286", + "sha256": "33af8c43e7d90253bcdfecee3baede439188ef1a57ff179f0e0268ccaa933d81", "files": [ { "path": "dist/cli.d.ts", @@ -62,11 +62,11 @@ }, { "path": "dist/commands/capture.js", - "sha256": "4ce293e005e3cbc898f2a9fd230b5c98dd83ebb4d3e35c57b87b6b8b23057676" + "sha256": "9b805998ca20832432d46c9cdbcee41253ccb044da37e139e3f1d32263b5d6a0" }, { "path": "dist/commands/capture.js.map", - "sha256": "94fe0ee505c05caa6916bda2dc979648bf75e3a2855695f60771c312126648e3" + "sha256": "06abe0bb9cba4f1f8cd0d2278295d0cb0cada9132360dee0724d86ee1c95011e" }, { "path": "dist/commands/demo.d.ts", @@ -622,7 +622,7 @@ }, { "path": "dist/commitlore.mjs", - "sha256": "d800ef0f2ddcd255eaf56a8d42d37d6647a83bef890ab2cda5dc4d3bd6e325fe" + "sha256": "e5c54a1bcada00b43660db4b1de9e30c08b475f013eb6de34b2225e1777625ba" }, { "path": "dist/core/agent-configs.d.ts", @@ -1002,11 +1002,11 @@ }, { "path": "dist/core/schema.js", - "sha256": "94cedb9a442247df4841d785f98e038033272409dff9fda59984e86e15ef840f" + "sha256": "8b8ddf476f0b07027aefadd0c7efd54d792ad85b11a4f2192545fd8d70339e56" }, { "path": "dist/core/schema.js.map", - "sha256": "f5056656c76182fe911ccb030cc316708506620a1ba84c75b60f81588106f43d" + "sha256": "caac82d11c39f3947e8070641168b17398888f876b25efe526ead9bf9fb533b2" }, { "path": "dist/core/secret-guard.d.ts", diff --git a/package-lock.json b/package-lock.json index 5730f28a..afc2d547 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "commitlore", - "version": "1.2.4", + "version": "1.2.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "commitlore", - "version": "1.2.4", + "version": "1.2.5", "license": "MIT", "dependencies": { "@modelcontextprotocol/sdk": "^1.30.0", diff --git a/package.json b/package.json index b1b7b646..aaccc9ff 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "commitlore", - "version": "1.2.4", + "version": "1.2.5", "description": "Git-native, lifecycle-aware decision memory for coding agents", "license": "MIT", "private": true, diff --git a/server.json b/server.json index 6e4f9cb6..19048891 100644 --- a/server.json +++ b/server.json @@ -8,7 +8,7 @@ "source": "github" }, "websiteUrl": "https://github.com/MongLong0214/commitlore#readme", - "version": "1.2.4", + "version": "1.2.5", "_meta": { "io.modelcontextprotocol.registry/publisher-provided": { "registryFit": "Distribution is a tagged git checkout plus a Claude Code plugin marketplace (ADR-0011 registry-free git distribution, ADR-0026 no compiled executables and no uploaded release asset), so no official package type applies and this record relies on websiteUrl plus publisher metadata.", @@ -18,8 +18,8 @@ "/plugin marketplace add MongLong0214/commitlore", "/plugin install commitlore@commitlore" ], - "installer": "curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.4/install.sh | sh -s v1.2.4", - "release": "https://github.com/MongLong0214/commitlore/releases/tag/v1.2.4" + "installer": "curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.2.5/install.sh | sh -s v1.2.5", + "release": "https://github.com/MongLong0214/commitlore/releases/tag/v1.2.5" }, "runtime": { "transport": "stdio", diff --git a/spec/fixtures/invalid/03-unknown-key.expected.json b/spec/fixtures/invalid/03-unknown-key.expected.json index 8d3a13f2..d6ccc0c0 100644 --- a/spec/fixtures/invalid/03-unknown-key.expected.json +++ b/spec/fixtures/invalid/03-unknown-key.expected.json @@ -4,6 +4,6 @@ { "key": "Constraint", "value": "must ship by friday per the compliance deadline" } ], "violations": [ - { "key": "Constraint", "value": "must ship by friday per the compliance deadline", "rule": "unknown-key", "got": "Constraint", "want": "a key from SPEC §3 or X-" } + { "key": "Constraint", "value": "must ship by friday per the compliance deadline", "rule": "unknown-key", "got": "Constraint", "want": "a key from SPEC §3, or X-Constraint if this is your own metadata" } ] } diff --git a/src/commands/capture.ts b/src/commands/capture.ts index 90e70de9..bbeaa178 100644 --- a/src/commands/capture.ts +++ b/src/commands/capture.ts @@ -210,14 +210,37 @@ const runCapturePipeline = (opts: { const { transcriptPath, diffPath, draftPath, cwd } = opts; const transcript = readCallerFile(transcriptPath); - // Prepare hashes `git diff --cached` itself, so verification has to be given - // the same bytes. This used to default to the empty string, whose hash never - // matches -- every record was refused with `source-mismatch` and the command - // printed `no record staged`, so `capture --draft` could not succeed at all - // unless the caller happened to pass a --diff file byte-identical to the - // staged diff. A caller-supplied --diff that differs is still a real mismatch - // and is still refused. - const diff = diffPath ? readCallerFile(diffPath) : execGitOrThrow(['diff', '--cached'], { cwd }); + // The transaction binds to the staged diff and only to that: prepare hashes + // `git diff --cached` itself, and stage recomputes it a third time before + // writing, because every binding is computed server-side and never from the + // caller (capture-stage.ts). So `--diff` can assert what is staged; it cannot + // override it. + // + // It used to default to the empty string, whose hash never matches -- every + // record was refused with `source-mismatch` and the command printed `no record + // staged`, so `capture --draft` could not succeed at all unless the caller + // happened to pass a --diff file byte-identical to the staged diff. + // + // A --diff that differs is still refused. What #877 is about is where that + // refusal surfaced: prepare wrote a pending file for a run that could not + // succeed, and verify then blamed the draft -- `source-mismatch: diff hash + // does not match the prepared transaction` -- for a fault belonging entirely + // to the flag. The reporter re-checked quotes and locators that were never + // wrong. It is refused here instead, before prepare, naming the flag. + const callerDiff = diffPath === undefined ? undefined : readCallerFile(diffPath); + const diff = execGitOrThrow(['diff', '--cached'], { cwd }); + if (callerDiff !== undefined && callerDiff !== diff) { + throw markCaptureError( + new Error( + `--diff ${JSON.stringify(diffPath)} is not the staged diff. A capture transaction ` + + 'binds to the staged diff -- prepare, verify and stage each recompute it, so --diff ' + + 'can assert what is staged but cannot override it. Stage the change you are ' + + 'recording; to record against a commit that already exists, soft-reset it first ' + + '(git reset --soft HEAD~1).', + ), + 'usage', + ); + } // 1. Prepare: compute bindings, generate prompt, persist prepared transaction const prepareResult = prepareCaptureContext({ @@ -239,10 +262,17 @@ const runCapturePipeline = (opts: { } // 2. If no draft provided, print the prompt contract and exit (prompt-only mode) + // + // The nonce is reported, not dropped (#878). Prepare has already persisted the + // transaction under it, and prompt-only is the step `--out` exists for: get the + // nonce, hand the prompt to a model, come back with --draft. Returning null + // here made `if (options.out && result.nonce)` false on exactly that run, so + // --out wrote nothing and said nothing, and a scripted caller had no handle on + // which transaction it was completing until verify failed several steps later. if (!draftPath) { return { outcome: 'empty', - nonce: null, + nonce: prepareResult.nonce, staged: false, prompt: prepareResult.prompt, transcript_window: prepareResult.transcript_window, @@ -396,7 +426,11 @@ export const register = (program: Command): void => { 'path to the session transcript file (the prompt carries its last 256 KiB; ' + 'COMMITLORE_TRANSCRIPT_BUDGET_BYTES changes that, and verification always reads all of it)', ) - .option('--diff ', 'path to the diff file (defaults to the staged diff)') + .option( + '--diff ', + 'assert the staged diff equals this file; the transaction always binds to the staged diff, ' + + 'so this cannot select a different one', + ) .option('--draft ', 'path to the draft JSON file (omit for prompt-only mode)') .option('--out ', 'write the pending nonce to a file') .option('--shadow', 'measure historical capture candidates without writing anything') diff --git a/src/core/schema.ts b/src/core/schema.ts index 4f72f8ef..9580a1ed 100644 --- a/src/core/schema.ts +++ b/src/core/schema.ts @@ -75,6 +75,43 @@ const FORMAT_WANT: Readonly> = { const UNKNOWN_KEY_WANT = 'a key from SPEC §3 or X-'; +/** + * Name the `X-` form the author could have written, rather than its shape (#881). + * + * `X-` is already in the answer, and it was not enough: Claude Code tells + * every session to end its commit message with `Claude-Session:`, so the key + * arrives by default, the hook refuses it, the commit is lost, and the agent — + * which cannot see the repository's earlier commits — writes it again. Reported + * twice in one day in two repositories by the same author, the second time after + * already knowing about the first, because `X-` is not the kind of thing that + * stays in mind between repositories. Naming `X-Claude-Session` turns a refused + * commit into a corrected one. + * + * Not a rewrite: SPEC §6 says the message is not modified, and silently renaming + * someone's trailer would be worse than refusing it. This only says the name. + * + * Two keys are deliberately not offered the prefix: + * + * - one whose value reads as a sentence, which keeps the #647 answer instead — + * that author's problem is that their prose became metadata, and `X-` is the + * wrong door for them. That branch is chosen before this function is called. + * - one that differs from a SPEC §3 key only by case. `limit:` is `Limit:` + * miswritten, not an extension, and `X-limit` would be a valid record holding + * the wrong key. SPEC §3 matches case-sensitively and `KNOWN_KEYS` still does, + * so the plain answer — which names §3 first — is the useful one here. + * + * Anything the prefix cannot rescue (a leading digit, an underscore) falls back + * too: `EXTENSION_KEY_RE` is asked rather than assumed. + */ +const unknownKeyWant = (key: string): string => { + if ((KNOWN_KEYS as readonly string[]).some((known) => known.toLowerCase() === key.toLowerCase())) { + return UNKNOWN_KEY_WANT; + } + const prefixed = `X-${key}`; + if (!EXTENSION_KEY_RE.test(prefixed)) return UNKNOWN_KEY_WANT; + return `a key from SPEC §3, or ${prefixed} if this is your own metadata`; +}; + /** * The same violation, told to someone who did not write a trailer (#647). * @@ -204,7 +241,7 @@ const violationFor = (trailer: Trailer, field: string): Violation | null => { value: trailer.value, rule: 'unknown-key', got: trailer.key, - want: looksLikeProse(trailer.value) ? PROSE_KEY_WANT : UNKNOWN_KEY_WANT, + want: looksLikeProse(trailer.value) ? PROSE_KEY_WANT : unknownKeyWant(trailer.key), }; } diff --git a/test/capture.test.ts b/test/capture.test.ts index 2bf50641..8aed8c51 100644 --- a/test/capture.test.ts +++ b/test/capture.test.ts @@ -496,6 +496,104 @@ describe('commitlore capture', () => { }); }); +describe('commitlore capture --out (#878)', () => { + // Prompt-only is the step --out exists for -- get the nonce, hand the prompt + // to a model, come back with --draft -- and it was the one run where the + // pipeline returned `nonce: null`, so the write was guarded out. Exit 0, no + // file, nothing said. Three runs because the report measured three. + it('writes the pending nonce in prompt-only mode', () => { + const cwd = makeRepo(); + const { transcriptPath } = makeFixtures(cwd); + + for (const run of [1, 2, 3]) { + const outPath = join(cwd, `nonce-${run}.txt`); + const result = runCapture(['--transcript', transcriptPath, '--out', outPath], { cwd }); + + expect(result.exitCode).toBe(0); + expect(existsSync(outPath), `run ${run} wrote no file`).toBe(true); + expect(readFileSync(outPath, 'utf8').trim()).toMatch(/^[0-9a-f]{32}$/); + } + }); + + // The file is worthless unless it names the transaction prepare actually + // persisted -- a well-formed nonce nothing can be staged under would be the + // same silence in a different shape. + it('writes a nonce that names a real pending transaction', () => { + const cwd = makeRepo(); + const { transcriptPath } = makeFixtures(cwd); + const outPath = join(cwd, 'nonce.txt'); + + runCapture(['--transcript', transcriptPath, '--out', outPath], { cwd }); + + const nonce = readFileSync(outPath, 'utf8').trim(); + expect(listPending(cwd)).toContain(`${nonce}.json`); + }); + + it('reports the nonce in the JSON envelope too', () => { + const cwd = makeRepo(); + const { transcriptPath } = makeFixtures(cwd); + + const result = runCapture(['--transcript', transcriptPath, '--json'], { cwd }); + + const parsed = JSON.parse(result.stdout) as { outcome: string; nonce: string | null }; + expect(parsed.outcome).toBe('empty'); + expect(parsed.nonce).toMatch(/^[0-9a-f]{32}$/); + }); +}); + +describe('commitlore capture --diff (#877)', () => { + /** A real diff that is not the staged one: the previous commit's. */ + const writeForeignDiff = (cwd: string): string => { + const path = join(cwd, 'other.patch'); + writeFileSync(path, execSync('git show HEAD', { cwd, encoding: 'utf8' })); + return path; + }; + + // The transaction binds to the staged diff and nothing else, so a --diff that + // differs cannot be honoured. It was refused before this too -- but at verify, + // as `source-mismatch` against the draft's sources, which sent the reporter to + // re-check quotes and locators that were never wrong. + it('refuses a --diff that is not the staged diff, naming the flag', () => { + const cwd = makeRepo(); + const { transcriptPath } = makeFixtures(cwd); + const foreign = writeForeignDiff(cwd); + + const result = runCapture(['--transcript', transcriptPath, '--diff', foreign], { cwd }); + + expect(result.exitCode).toBe(2); + expect(result.stderr).toContain('--diff'); + expect(result.stderr, 'the flag is named, not the draft').not.toContain('source-mismatch'); + expect(result.stderr, 'and the way out is named').toContain('git reset --soft'); + }); + + // Refused before prepare, so a run that cannot succeed leaves no transaction + // for `capture gc` to collect. Two were left behind per attempt before. + it('writes no pending transaction for a --diff it refuses', () => { + const cwd = makeRepo(); + const { transcriptPath, draftPath } = makeFixtures(cwd); + const foreign = writeForeignDiff(cwd); + + runCapture(['--transcript', transcriptPath, '--diff', foreign, '--draft', draftPath], { cwd }); + + expect(listPending(cwd)).toEqual([]); + }); + + // The control. Without it the fix degenerates into "reject every --diff", + // which passes the two assertions above and breaks every caller that has one. + it('still stages when --diff is byte-identical to the staged diff', () => { + const cwd = makeRepo(); + const { transcriptPath, diffPath, draftPath } = makeFixtures(cwd); + + const result = runCapture( + ['--transcript', transcriptPath, '--diff', diffPath, '--draft', draftPath], + { cwd }, + ); + + expect(result.exitCode).toBe(0); + expect(listStagedPending(cwd).length).toBe(1); + }); +}); + describe('commitlore capture --unattended (#511)', () => { it('is refused where the repository did not opt in, and stages nothing', () => { const cwd = makeRepo(); diff --git a/test/help-text-honesty.test.ts b/test/help-text-honesty.test.ts index 62f696c0..962f24b0 100644 --- a/test/help-text-honesty.test.ts +++ b/test/help-text-honesty.test.ts @@ -91,12 +91,24 @@ describe('#303 user-facing text names only packages the manifest carries', () => */ describe('#359 capture --diff documents the default it actually has', () => { const captureSource = readFileSync(join(REPO_ROOT, 'src/commands/capture.ts'), 'utf8'); - const diffOption = captureSource - .split('\n') - .find((line) => line.includes(".option('--diff '")); + + // The whole `.option(...)` call, not one line of it. r-diffdefault recorded + // reading a single line as this check's known limit, and #877 collected on it: + // the description outgrew one line, the call became multi-line, and all three + // assertions below stopped seeing any string at all. A guard that silently + // matches nothing reports the same green as one that passed. + const optionCall = (flag: string): string | undefined => { + const chunk = captureSource.split('.option(').find((part) => part.trimStart().startsWith(flag)); + if (chunk === undefined) return undefined; + // Chained calls are indented four spaces; stop at the next one. + const end = chunk.indexOf('\n .'); + return end === -1 ? chunk : chunk.slice(0, end); + }; + const diffOption = optionCall("'--diff '"); it('the option line exists to be checked', () => { expect(diffOption).toBeDefined(); + expect(diffOption).toContain('--diff '); }); it('does not tell the caller the default is empty', () => { @@ -107,6 +119,15 @@ describe('#359 capture --diff documents the default it actually has', () => { expect(diffOption).toMatch(/staged/i); }); + // #877 narrowed what the flag means without changing what it reads. The + // transaction binds to the staged diff at prepare, verify and stage, so a + // description promising that `--diff` selects a different diff would be the + // #359 defect again in the other direction: the caller passes one, every + // record comes back `source-mismatch`, and the help text told them to. + it('does not promise that --diff selects a diff other than the staged one', () => { + expect(diffOption).toMatch(/assert|cannot (select|override)/i); + }); + // Teeth: the sentence above is only worth asserting while the code still // behaves that way. If the default ever moves off the staged diff, this fails // and the help text has to be re-decided rather than quietly drifting again. diff --git a/test/schema.test.ts b/test/schema.test.ts index e02a05b4..746a1fbf 100644 --- a/test/schema.test.ts +++ b/test/schema.test.ts @@ -193,13 +193,51 @@ describe('validateRecord', () => { }); // The other half, and the reason the value decides rather than the key: a - // key someone meant as a key gets the short answer. spec/fixtures/invalid/ - // 03-unknown-key.txt pins this same reading through the conformance suite. - it('keeps the plain answer for a key that was meant as a key', () => { + // key someone meant as a key is not told their sentence became metadata. + // What it is told changed in #881 — the answer now names the X- form the + // author could have written instead of describing its shape. spec/fixtures/ + // invalid/03-unknown-key.json pins this same reading through the conformance + // suite; the violation it pins is unchanged, and `Constraint` is still + // refused. Only the advice moved, which test/validate.test.ts already + // records as advisory prose rather than the conformance contract. + it('names the extension form for a key that was meant as a key', () => { const violations = validateRecord([ { key: 'Constraint', value: 'must ship by friday per the compliance deadline' }, ]); + expect(violations.map((v) => v.rule)).toEqual(['unknown-key']); + expect(violations[0]?.want).toBe( + 'a key from SPEC §3, or X-Constraint if this is your own metadata', + ); + }); + + // #881: the reported case. Claude Code tells every session to end its commit + // message with this key, so it arrives by default and the refusal has to + // carry the repair or the same commit is written, refused and written again. + it('names X-Claude-Session when refusing Claude-Session', () => { + const violations = validateRecord([ + { key: 'Claude-Session', value: 'https://claude.ai/code/session_abc123' }, + ]); + + expect(violations.map((v) => v.rule)).toEqual(['unknown-key']); + expect(violations[0]?.want).toContain('X-Claude-Session'); + expect(violations[0]?.want, 'SPEC §3 still comes first').toContain('a key from SPEC §3'); + }); + + // The guard the hint made necessary. `limit:` is `Limit:` miswritten, not an + // extension, and `X-limit` would be a valid record carrying the wrong key. + it('does not offer the X- form for a SPEC §3 key that differs only by case', () => { + const violations = validateRecord([{ key: 'limit', value: 'the cache times out at 30s' }]); + + expect(violations.map((v) => v.rule)).toEqual(['unknown-key']); + expect(violations[0]?.want).toBe('a key from SPEC §3 or X-'); + }); + + // A key the prefix cannot rescue: EXTENSION_KEY_RE requires a letter after + // `X-`, so `X-2fa-mode` is not valid either and must not be suggested. + it('keeps the plain answer for a key that X- cannot make valid', () => { + const violations = validateRecord([{ key: '2fa-mode', value: 'totp' }]); + expect(violations.map((v) => v.rule)).toEqual(['unknown-key']); expect(violations[0]?.want).toBe('a key from SPEC §3 or X-'); });