@litfamily/litclaude 1.0.4 → 1.0.5

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
@@ -7,6 +7,11 @@
7
7
  envelopes and plain-output policy; use flat orange/lime/ivory cell colors with
8
8
  fixed 256-color approximations and no background or extrusion.
9
9
 
10
+ ## 1.0.5
11
+
12
+ - Ignore host-generated task notifications and system reminders during prompt activation while preserving routes for genuine user text.
13
+ - Make scaffold-plan's paired-write cleanup tolerate transient sibling-draft churn without reporting refusal after a plan was written, while retaining replacement detection.
14
+
10
15
  ## 1.0.4
11
16
 
12
17
  - Keep managing a native `litclaude@litclaude-ai` registration after a host rewrite
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.4/docs/assets/cover.webp" width="100%" alt="LitClaude v5 armory cover" /></p>
1
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.5/docs/assets/cover.webp" width="100%" alt="LitClaude v5 armory cover" /></p>
2
2
 
3
3
  <h1 align="center">LitClaude</h1>
4
4
  <p align="center"><strong>Keep the work lit.</strong></p>
@@ -38,12 +38,12 @@
38
38
 
39
39
  </details>
40
40
 
41
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.4/docs/assets/litclaude-wordmark.svg" width="480" alt="LITCLAUDE display type" /></p>
42
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.4/docs/assets/litclaude-clay-icon.png" width="160" alt="LitClaude clay mark" /></p>
41
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.5/docs/assets/litclaude-wordmark.svg" width="480" alt="LITCLAUDE display type" /></p>
42
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.5/docs/assets/litclaude-clay-icon.png" width="160" alt="LitClaude clay mark" /></p>
43
43
 
44
44
  <p align="center">
45
- <img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.4/docs/assets/readme/badge-version.svg" alt="1.0.4" />
46
- <a href="./LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.4/docs/assets/readme/badge-license.svg" alt="MIT license" /></a>
45
+ <img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.5/docs/assets/readme/badge-version.svg" alt="1.0.5" />
46
+ <a href="./LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.5/docs/assets/readme/badge-license.svg" alt="MIT license" /></a>
47
47
  </p>
48
48
 
49
49
  <p align="center">
@@ -355,13 +355,13 @@ npm exec --yes --package @litfamily/litclaude@latest -- litclaude install
355
355
  For a reproducible install, pin the current package version:
356
356
 
357
357
  ```bash
358
- npm view @litfamily/litclaude@1.0.4 version
358
+ npm view @litfamily/litclaude@1.0.5 version
359
359
  ```
360
360
 
361
- If that lookup returns `1.0.4`, the exact install is available:
361
+ If that lookup returns `1.0.5`, the exact install is available:
362
362
 
363
363
  ```bash
364
- npm exec --yes --package @litfamily/litclaude@1.0.4 -- litclaude install
364
+ npm exec --yes --package @litfamily/litclaude@1.0.5 -- litclaude install
365
365
  ```
366
366
 
367
367
  Otherwise, wait for explicit human publication before using that pin. Check the
package/README_ko-KR.md CHANGED
@@ -1,4 +1,4 @@
1
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.4/docs/assets/cover.webp" width="100%" alt="LitClaude v5 armory cover" /></p>
1
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.5/docs/assets/cover.webp" width="100%" alt="LitClaude v5 armory cover" /></p>
2
2
 
3
3
  <h1 align="center">LitClaude</h1>
4
4
  <p align="center"><strong>Keep the work lit.</strong></p>
@@ -38,12 +38,12 @@
38
38
 
39
39
  </details>
40
40
 
41
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.4/docs/assets/litclaude-wordmark.svg" width="480" alt="LITCLAUDE 디스플레이 타입" /></p>
42
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.4/docs/assets/litclaude-clay-icon.png" width="160" alt="LitClaude 클레이 마크" /></p>
41
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.5/docs/assets/litclaude-wordmark.svg" width="480" alt="LITCLAUDE 디스플레이 타입" /></p>
42
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.5/docs/assets/litclaude-clay-icon.png" width="160" alt="LitClaude 클레이 마크" /></p>
43
43
 
44
44
  <p align="center">
45
- <img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.4/docs/assets/readme/badge-version.svg" alt="1.0.4" />
46
- <a href="./LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.4/docs/assets/readme/badge-license.svg" alt="MIT license" /></a>
45
+ <img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.5/docs/assets/readme/badge-version.svg" alt="1.0.5" />
46
+ <a href="./LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.5/docs/assets/readme/badge-license.svg" alt="MIT license" /></a>
47
47
  </p>
48
48
 
49
49
  <p align="center">
@@ -350,13 +350,13 @@ npm exec --yes --package @litfamily/litclaude@latest -- litclaude install
350
350
  설치를 재현하려면 registry에서 현재 package version을 조회한 뒤 고정합니다.
351
351
 
352
352
  ```bash
353
- npm view @litfamily/litclaude@1.0.4 version
353
+ npm view @litfamily/litclaude@1.0.5 version
354
354
  ```
355
355
 
356
- 조회 결과가 `1.0.4`이면 exact install을 사용할 수 있습니다.
356
+ 조회 결과가 `1.0.5`이면 exact install을 사용할 수 있습니다.
357
357
 
358
358
  ```bash
359
- npm exec --yes --package @litfamily/litclaude@1.0.4 -- litclaude install
359
+ npm exec --yes --package @litfamily/litclaude@1.0.5 -- litclaude install
360
360
  ```
361
361
 
362
362
  그렇지 않으면 명시적인 human publication을 기다립니다. Pin은 그 뒤에 사용합니다.
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="146" height="20" role="img" aria-label="release: 1.0.4"><title>release: 1.0.4</title><g shape-rendering="crispEdges"><rect width="49" height="20" fill="#080d14"/><rect x="49" width="97" height="20" fill="#ff6337"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="255" y="140" textLength="390" transform="scale(.1)">release</text><text x="965" y="140" textLength="870" transform="scale(.1)" fill="#080D14">1.0.4</text></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="146" height="20" role="img" aria-label="release: 1.0.5"><title>release: 1.0.5</title><g shape-rendering="crispEdges"><rect width="49" height="20" fill="#080d14"/><rect x="49" width="97" height="20" fill="#ff6337"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="255" y="140" textLength="390" transform="scale(.1)">release</text><text x="965" y="140" textLength="870" transform="scale(.1)" fill="#080D14">1.0.5</text></g></svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@litfamily/litclaude",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Claude Code-native workflow distribution.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "litclaude",
3
3
  "description": "Claude Code-native workflow plugin with a bounded-authority start-work lifecycle.",
4
- "version": "1.0.4",
4
+ "version": "1.0.5",
5
5
  "author": {
6
6
  "name": "LitClaude contributors"
7
7
  },
@@ -466,7 +466,24 @@ const withoutClosedCodeFences = (text) => {
466
466
  };
467
467
 
468
468
  const withoutCode = (text) => withoutClosedCodeFences(text).replace(/`[^`]*`/gu, " ");
469
- const rawTriggerText = (text) => withoutCode(text).toLowerCase();
469
+
470
+ // Claude Code (and herdr, which relays pane events the same way) can deliver a
471
+ // UserPromptSubmit turn whose `prompt` is host-generated background content rather
472
+ // than something the user typed — observed 3x on 2026-09-17 as a `<task-notification>`
473
+ // block reporting a finished background agent, which happened to contain UI-shaped
474
+ // prose ("dashboard", "configure", ...) and fired the frontend-ui-ux route. A
475
+ // `<system-reminder>` block is the same class of host-authored wrapper and is stripped
476
+ // for the same reason, even though only `<task-notification>` has been directly
477
+ // observed here. Only WELL-FORMED, fully-closed blocks are stripped — same rule as
478
+ // `withoutClosedCodeFences` for fences — so a bare, unclosed opening tag (accidental or
479
+ // not) stays visible and eligible rather than silently swallowing real user text.
480
+ // Genuine user prose outside (or between) these blocks is untouched and still routes
481
+ // normally; a prompt that consists ONLY of host-generated blocks reduces to nothing and
482
+ // therefore activates no route, which is the intended fix.
483
+ const withoutHostNotifications = (text) => text
484
+ .replace(/<task-notification>[\s\S]*?<\/task-notification>/gu, " ")
485
+ .replace(/<system-reminder>[\s\S]*?<\/system-reminder>/gu, " ");
486
+ const rawTriggerText = (text) => withoutCode(withoutHostNotifications(text)).toLowerCase();
470
487
  const normalizedTriggerText = (text) => rawTriggerText(text).replace(/[_-]+/gu, " ");
471
488
 
472
489
  const isPlainWordBoundary = (value) => value === undefined || !plainWordBoundary.test(value);
@@ -9,7 +9,7 @@ import {
9
9
  } from "../lib/wikify-knowledge.mjs";
10
10
 
11
11
  const protocolVersion = "2024-11-05";
12
- const serverVersion = "1.0.4";
12
+ const serverVersion = "1.0.5";
13
13
 
14
14
  const publicSourceReadTool = {
15
15
  name: "public_source_read",
@@ -47,7 +47,7 @@ export const canonicalSkillResourceManifest = Object.freeze(
47
47
  ["lib/strict-json.mjs", "d941f327aabce5ffc212770852cfbc7e08dd03471e4e9bc9560eff54f06d489a"],
48
48
  ["lib/wikify-knowledge-cli.mjs", "d98e4b3ea0efe3dcd483750c2dc3a5d0dfd14bc6eb349437902b1e01b8fa2ff4"],
49
49
  ["lib/wikify-knowledge.mjs", "4d2f4e0ac3bc0b40ac513470b324e853e2aeeb3f009216c13d8e12ec08e6c28b"],
50
- ["scripts/scaffold-plan.mjs", "a9b05ea6c382638a94fefeffd3b709a31b82a80f8355d0d5ef717a737d13dc5f"],
50
+ ["scripts/scaffold-plan.mjs", "c014b9acb49a647c97044dfb5a83eb5cc2bd4e13774ad1a9f213b9e074559d3e"],
51
51
  ["skills/autoconference/SKILL.md", "3731208dc3838d4d2916fb01da0c8cb63cca36342c2ffb5770770b3332d06cd3"],
52
52
  ["skills/autoresearch/SKILL.md", "2b69c53bade3851cfb9c770bce80afe5f9e75b9629719e9ba95a4b0045eaf5b3"],
53
53
  ["skills/browser-drive/scripts/capability-probe.mjs", "e767912bc034eaf9081256d8aa2f2bf63c7d9d29e39cb5e56f390e872df794f7"],
@@ -230,23 +230,38 @@ const inspectWorkspaceDirectory = (cwd) => {
230
230
  return { workspaceRoot, workspaceStat };
231
231
  };
232
232
 
233
+ // A directory that was actually REPLACED (rename-over, or unlink+recreate that
234
+ // reuses the freed inode number — dev/ino/birthtime can all coincide with the
235
+ // original on Linux; see test/inode-reuse.test.mjs) leaves an already-opened
236
+ // descriptor pinned to the old, now-unlinked inode. That inode's ctime is frozen
237
+ // at replacement time, so a descriptor-based read never converges with a fresh
238
+ // pathname-based read of the replacement. A brief sibling create/unlink INSIDE an
239
+ // otherwise-untouched directory (a different scaffold slug sharing
240
+ // `.litclaude/drafts/`, for example) also advances that directory's ctime and can
241
+ // land in the gap between the two reads, but it settles within microseconds since
242
+ // the directory itself was never replaced. Re-sampling a bounded number of times
243
+ // lets that transient churn resolve without weakening the replacement check: a
244
+ // genuine replacement's mismatch never resolves and still fails closed once the
245
+ // attempts are exhausted.
246
+ const DIRECTORY_PIN_SETTLE_ATTEMPTS = 5;
247
+
233
248
  const assertDirectoryPin = async (pin, label) => {
234
249
  if (pin?.descriptor === undefined || pin.parentState?.closed) throw new Error(`refused: ${label} pin is closed`);
235
250
  const openedBefore = fstatSync(pin.descriptor);
236
251
  const named = await lstat(pin.path);
237
252
  const openedAfter = fstatSync(pin.descriptor);
238
253
  const namedAfter = await lstat(pin.path);
239
- const openedFinal = fstatSync(pin.descriptor);
240
- // Take the pathname sample after the final descriptor sample. A competing
241
- // writer may create/remove a temporary entry between the earlier samples;
242
- // that normal ctime churn must not turn an unchanged pinned directory into a
243
- // false denial.
244
- const namedFinal = await lstat(pin.path);
245
- // A concurrent lock/temp-file creation legitimately advances directory ctime
246
- // between the first descriptor sample and the pathname stat. Accept that only
247
- // when the descriptor still names the same directory and the second sample
248
- // agrees with the pathname; a replacement after open leaves the two samples
249
- // disagreeing and remains fail-closed.
254
+ let openedFinal;
255
+ let namedFinal;
256
+ let settled = false;
257
+ for (let attempt = 0; attempt < DIRECTORY_PIN_SETTLE_ATTEMPTS && !settled; attempt += 1) {
258
+ openedFinal = fstatSync(pin.descriptor);
259
+ namedFinal = await lstat(pin.path);
260
+ settled = samePathIdentity(openedFinal, namedFinal);
261
+ }
262
+ // Accept the "before" pair only when the descriptor still names the same
263
+ // directory and the settled sample agrees with the pathname; a replacement
264
+ // after open leaves the two samples disagreeing and remains fail-closed.
250
265
  const stable = openedBefore.isDirectory()
251
266
  && openedAfter.isDirectory()
252
267
  && openedFinal.isDirectory()
@@ -254,7 +269,7 @@ const assertDirectoryPin = async (pin, label) => {
254
269
  && namedAfter.isDirectory()
255
270
  && !named.isSymbolicLink()
256
271
  && !namedAfter.isSymbolicLink()
257
- && samePathIdentity(openedFinal, namedFinal)
272
+ && settled
258
273
  && (samePathIdentity(openedBefore, named)
259
274
  || (openedBefore.dev === openedFinal.dev && openedBefore.ino === openedFinal.ino));
260
275
  if (!stable) {