@litfamily/litclaude 1.0.27 → 1.0.29

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,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.29 - 2026-10-15
4
+
5
+ - Reports and decks no longer fill up with lines that tell the reader what the document is not for, such as `동일 조건의 독립 성능 비교로 쓰지 않음.` When the model writes one into a file, the pre-write guard refuses the save and the model rewrites it. Three new rules cover Korean self-referencing pledges, repeated disclaimers and the English forms; legal and financial notices, safety warnings and real negative findings stay untouched. The rules finish in milliseconds even on very long runs of spaces.
6
+ - The `lit-docx` and `lit-pptx` instructions that taught the habit now ask for a real limit once, as a fact beside the number it affects, with anything about what the document is not for kept in the reply.
7
+
8
+ ## 1.0.28 - 2026-10-14
9
+
10
+ - A new lit-loop no longer shows every stage of the card's workflow map as done when an older goal in the project had already finished. The finished goal now ends the map only when it finished after the current stage was recorded, so the map follows the work you are doing now; a goal that really finishes still shows done.
11
+ - `litclaude-ai` is now on the Bash PATH after a plugin install, so the documented `litclaude-ai litgoal`, `start-work`, `workflow-stage` and similar commands run without the npm package. Other subcommands point you at the npm package.
12
+ - The start-work gate lets its own `start-work pause` through when it names an outside target root. The pause records a pending boundary and grants nothing; forbidden actions are still refused.
13
+
3
14
  ## 1.0.27 - 2026-10-13
4
15
 
5
16
  - The lit-loop map now moves when the work happens in the shell. Writing a test with a shell command (`cat > test/…`, `>>`, `tee` or `sed -i`) turns the map to RED, changing a source file the same way turns it to GREEN, and the next test run turns it to VERIFY. A failing test run while the criterion is still pinned also counts as RED, including a bare `npm test` that exits with an error. The card keeps only the stage, never the command or the file names.
package/README.md CHANGED
@@ -1,14 +1,14 @@
1
- <p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/docs/assets/cover-motion-still.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/docs/assets/cover-motion.webp" width="100%" alt="LitFamily motion cover: five armored robots power on one by one, the LitClaude robot wakes with glowing eyes and a lit frame, then LITFAMILY and KEEP THE WORK LIT. light up." /></picture></p>
1
+ <p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/docs/assets/cover-motion-still.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/docs/assets/cover-motion.webp" width="100%" alt="LitFamily motion cover: five armored robots power on one by one, the LitClaude robot wakes with glowing eyes and a lit frame, then LITFAMILY and KEEP THE WORK LIT. light up." /></picture></p>
2
2
 
3
3
  <h1 align="center">LitClaude</h1>
4
4
  <p align="center"><strong>Keep the work lit.</strong></p>
5
5
  <p align="center">A Claude Code plugin that helps every session plan the work, build it, check it, and leave a note the next session can pick up.</p>
6
6
  <p align="center">
7
- <img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/docs/assets/readme/badge-version.svg" alt="1.0.27" />
8
- <a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/docs/assets/readme/badge-license.svg" alt="MIT license" /></a>
7
+ <img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/docs/assets/readme/badge-version.svg" alt="1.0.29" />
8
+ <a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/docs/assets/readme/badge-license.svg" alt="MIT license" /></a>
9
9
  </p>
10
10
  <p align="center">
11
- <a href="https://github.com/wjgoarxiv/litclaude#readme">Full guide and skills gallery on GitHub</a> · <a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/README_ko-KR.md">한국어</a>
11
+ <a href="https://github.com/wjgoarxiv/litclaude#readme">Full guide and skills gallery on GitHub</a> · <a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/README_ko-KR.md">한국어</a>
12
12
  </p>
13
13
 
14
14
  Add `lit` to a Claude Code prompt and Claude pins the goal, writes a failing test first,
@@ -73,7 +73,7 @@ the `/plugin` menu.
73
73
  ## More
74
74
 
75
75
  - [Full guide and skills gallery on GitHub](https://github.com/wjgoarxiv/litclaude#readme)
76
- - [Privacy and network behavior](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/docs/privacy.md)
77
- - [Migration and ownership conflicts](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/docs/migration.md)
78
- - [Release history](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/CHANGELOG.md)
79
- - [MIT license](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/LICENSE)
76
+ - [Privacy and network behavior](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/docs/privacy.md)
77
+ - [Migration and ownership conflicts](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/docs/migration.md)
78
+ - [Release history](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/CHANGELOG.md)
79
+ - [MIT license](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/LICENSE)
package/README_ko-KR.md CHANGED
@@ -1,14 +1,14 @@
1
- <p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/docs/assets/cover-motion-still.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/docs/assets/cover-motion.webp" width="100%" alt="LitFamily 모션 커버: 다섯 로봇 패널이 차례로 켜지고, LitClaude 로봇의 눈과 테두리가 빛난 뒤 LITFAMILY와 KEEP THE WORK LIT. 문구가 밝아지는 영상" /></picture></p>
1
+ <p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/docs/assets/cover-motion-still.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/docs/assets/cover-motion.webp" width="100%" alt="LitFamily 모션 커버: 다섯 로봇 패널이 차례로 켜지고, LitClaude 로봇의 눈과 테두리가 빛난 뒤 LITFAMILY와 KEEP THE WORK LIT. 문구가 밝아지는 영상" /></picture></p>
2
2
 
3
3
  <h1 align="center">LitClaude</h1>
4
4
  <p align="center"><strong>Keep the work lit.</strong></p>
5
5
  <p align="center">Claude Code에서 세션마다 계획하고, 만들고, 확인한 뒤 다음 세션이 이어받을 기록을 남기게 돕는 플러그인입니다.</p>
6
6
  <p align="center">
7
- <img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/docs/assets/readme/badge-version.svg" alt="1.0.27" />
8
- <a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/docs/assets/readme/badge-license.svg" alt="MIT license" /></a>
7
+ <img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/docs/assets/readme/badge-version.svg" alt="1.0.29" />
8
+ <a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/docs/assets/readme/badge-license.svg" alt="MIT license" /></a>
9
9
  </p>
10
10
  <p align="center">
11
- <a href="https://github.com/wjgoarxiv/litclaude/blob/main/README_ko-KR.md">전체 안내와 스킬 갤러리는 GitHub에서</a> · <a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/README.md">English</a>
11
+ <a href="https://github.com/wjgoarxiv/litclaude/blob/main/README_ko-KR.md">전체 안내와 스킬 갤러리는 GitHub에서</a> · <a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/README.md">English</a>
12
12
  </p>
13
13
 
14
14
  Claude Code 프롬프트에 `lit`을 붙이면 Claude가 목표를 고정하고, 실패하는 테스트를 먼저 쓰고,
@@ -71,7 +71,7 @@ LitClaude는 프로젝트 상태를 `.litclaude/`에 두고, 그 안의 `.gitign
71
71
  ## 더 보기
72
72
 
73
73
  - [전체 안내와 스킬 갤러리 (GitHub)](https://github.com/wjgoarxiv/litclaude/blob/main/README_ko-KR.md)
74
- - [개인정보와 네트워크 동작](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/docs/privacy.md)
75
- - [이전과 소유권 충돌](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/docs/migration.md)
76
- - [변경 이력](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/CHANGELOG.md)
77
- - [MIT 라이선스](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.27/LICENSE)
74
+ - [개인정보와 네트워크 동작](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/docs/privacy.md)
75
+ - [이전과 소유권 충돌](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/docs/migration.md)
76
+ - [변경 이력](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/CHANGELOG.md)
77
+ - [MIT 라이선스](https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.29/LICENSE)
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="146" height="20" role="img" aria-label="release: 1.0.27"><title>release: 1.0.27</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.27</text></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="146" height="20" role="img" aria-label="release: 1.0.29"><title>release: 1.0.29</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.29</text></g></svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@litfamily/litclaude",
3
- "version": "1.0.27",
3
+ "version": "1.0.29",
4
4
  "description": "Claude Code plugin: add lit to a prompt and Claude plans, tests, checks and reviews the work, then leaves a handoff for the next session.",
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.27",
4
+ "version": "1.0.29",
5
5
  "author": {
6
6
  "name": "LitClaude contributors"
7
7
  },
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ // The `litclaude-ai` the skills and commands name, as the installed plugin serves it. Claude Code
3
+ // puts this bin/ directory on the Bash tool's PATH; the npm CLI (bin/litclaude-ai.js in the
4
+ // package) is usually not there. This entry runs the in-session subcommands from the plugin's own
5
+ // lib/ and sends everything else (install, doctor, update…) to the user's terminal.
6
+ //
7
+ // No file extension, so the bare name resolves on PATH; the code avoids `import`, `require`,
8
+ // `import.meta` and `module` so it runs whether Node loads it as CommonJS or as an ES module.
9
+
10
+ const SUBCOMMANDS = {
11
+ litgoal: async (load, rest) => (await load("../lib/litgoal/cli.mjs")).runLitgoalCli(rest),
12
+ "start-work": async (load, rest) => (await load("../lib/start-work-cli.mjs")).runStartWorkCli(rest, undefined, process.cwd()),
13
+ "start-work-next": async (load, rest) => {
14
+ const { resolveProjectStateRoot } = await load("../lib/project-state-root.mjs");
15
+ return (await load("../lib/start-work-continuation.mjs")).runStartWorkContinuationCli(resolveProjectStateRoot(process.cwd()), rest);
16
+ },
17
+ "workflow-stage": async (load, rest) => (await load("../lib/workflow-stage.mjs")).runWorkflowStageCli(rest, process.cwd()),
18
+ wikify: async (load, rest) => (await load("../lib/wikify-knowledge-cli.mjs")).runWikifyKnowledgeCli(rest, undefined, process.cwd()),
19
+ "motion-runtime": async (load, rest) => (await load("../skills/lit-typographic-motion/scripts/motion-runtime.mjs")).main(rest),
20
+ };
21
+
22
+ const main = async () => {
23
+ const [command, ...rest] = process.argv.slice(2);
24
+ const run = Object.hasOwn(SUBCOMMANDS, command ?? "") ? SUBCOMMANDS[command] : null;
25
+ if (!run) {
26
+ process.stderr.write(
27
+ `litclaude-ai (plugin): ${command ? `"${command}" is not served from the plugin` : "no command given"}. `
28
+ + `In-session commands: ${Object.keys(SUBCOMMANDS).join(", ")}. `
29
+ + `For install, update, doctor and the rest, ask the user to run in their own terminal: npx @litfamily/litclaude ${command ?? "--help"}\n`,
30
+ );
31
+ return 64;
32
+ }
33
+ const { realpathSync } = await import("node:fs");
34
+ const { dirname, join } = await import("node:path");
35
+ const { pathToFileURL } = await import("node:url");
36
+ const here = dirname(realpathSync(process.argv[1]));
37
+ return run((relative) => import(pathToFileURL(join(here, relative)).href), rest);
38
+ };
39
+
40
+ main().then(
41
+ (code) => {
42
+ process.exitCode = Number.isInteger(code) ? code : 0;
43
+ },
44
+ (error) => {
45
+ process.stderr.write(`litclaude-ai (plugin): ${error?.message ?? error}\n`);
46
+ process.exitCode = 1;
47
+ },
48
+ );
@@ -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.27";
12
+ const serverVersion = "1.0.29";
13
13
 
14
14
  const publicSourceReadTool = {
15
15
  name: "public_source_read",
@@ -498,7 +498,7 @@ export const canonicalSkillResourceManifest = Object.freeze(
498
498
  ["skills/lit-diagram-drawer/scripts/verify-type.mjs", "8cfa31a29d398e4d438a2433f3d1ea6f88c10bb0555281304936146b46e42bc3"],
499
499
  ["skills/lit-diagram-drawer/scripts/visual-quality.mjs", "6ee6fd0a2710eb2a354d445956d86838bece874cea8449d2c14bd4c108dd3fcb"],
500
500
  ["skills/lit-docx/NOTICE", "768ce7ea5a9b7290f6e4d0af4218646c819797e59dc0d7acb230e56352a679c7"],
501
- ["skills/lit-docx/SKILL.md", "eb4dda35604ef4e60ff03065635b40ce596db9d57711894e9e46fc47d713ed9c"],
501
+ ["skills/lit-docx/SKILL.md", "ec7aa9f49ba52418842a9322f5122ca86f329d48e94eae3655dddaf31b491b6e"],
502
502
  ["skills/lit-docx/references/components.md", "7d1583d52120859f137b0ae0c72511c9eb72621573e1a5e90412dd0a5fbcf535"],
503
503
  ["skills/lit-docx/references/direction-step.md", "ed79c399cd8aa3c8b80c53a6a7b0bd1dac8f014ef0790d72fc5bf79e539c895e"],
504
504
  ["skills/lit-docx/references/examples/01-report-ko.md", "13a038839aeab5a3d8da2abd64d7e78662051d6e773b1290eb331c70225b22e2"],
@@ -517,7 +517,7 @@ export const canonicalSkillResourceManifest = Object.freeze(
517
517
  ["skills/lit-docx/references/slop_phrase_list.yaml", "b4cb5dc858b2ea44b5558e8be4cb51199af40de53b901fb563b53c5416c50bdc"],
518
518
  ["skills/lit-docx/references/slop_rules.md", "3d182b85a5643e42411ab6552d23e76e963854ec9e88e8953c20bf8df8614a57"],
519
519
  ["skills/lit-docx/references/tonalities/brief.md", "5a0571cb7c0cc31391f3d707803aba415d7bb80b57826787f924ab535435f08a"],
520
- ["skills/lit-docx/references/tonalities/journal.md", "45871c10611346a2a0d81b3e7db14c8762c75daeeee3cea30e6e8edfc7066807"],
520
+ ["skills/lit-docx/references/tonalities/journal.md", "2d1a42602bbb43a42741add0a8f4896f1739d4a5f01518c63b39a9c2007d77cf"],
521
521
  ["skills/lit-docx/references/tonalities/manual.md", "b192101743c6b908095635c27a9bb6c7ee922a05f3139851c57b9566ba8848cb"],
522
522
  ["skills/lit-docx/references/tonalities/memo.md", "0e6863b3a5cf29a8e5a773f6bab8a3e65c4ecee3a63ff1b49bb194326ea291e1"],
523
523
  ["skills/lit-docx/references/tonalities/proposal.md", "904324ce21411e1942624a3ce8d4dd308eba0f8df2fdb5b88220cbc46e28b469"],
@@ -617,8 +617,8 @@ export const canonicalSkillResourceManifest = Object.freeze(
617
617
  ["skills/lit-humanizer/references/litclaude-rewrite-rules.md", "ba0a9de5d02a427a1dd955bfb71f215abf76d658a50a31e7d42d862b3db44870"],
618
618
  ["skills/lit-humanizer/references/litclaude-style-patterns.md", "19932e2dd5eda9e1e48f0d83086170ad4548e89d05333f702b1d342494c7af5e"],
619
619
  ["skills/lit-humanizer/references/rewrite-playbook.md", "3b0bae2e24e9aada73ea527402e80c25a9bf471b65871248858496f1a2fe8ffb"],
620
- ["skills/lit-humanizer/references/taxonomy.md", "82d8e806a7aa800e2fee106f0959b7b689d5e92e4b1356f259e8a5dfefb6dcde"],
621
- ["skills/lit-humanizer/rules.json", "d69ad386d534bde0fdbc08603151f82477db78e4c920203bf070128e927a7a5b"],
620
+ ["skills/lit-humanizer/references/taxonomy.md", "c69c11a0e9315b5dfb8c339e3c97522593cd7452955b187526406b29d1f16671"],
621
+ ["skills/lit-humanizer/rules.json", "6153ca0835b04fc9512c903b4c5080c3a45cd1fd68c1a9dbad8972b5a150fb6c"],
622
622
  ["skills/lit-humanizer/scripts/artifact-text.mjs", "36f893449d0b7719c747cbb512e0b7caed4146cb97b87acf813b3d911577a0e6"],
623
623
  ["skills/lit-humanizer/scripts/core.mjs", "748b008b02d1fab1be4b7784cc7b195f89a3b1a992b8975b6040fc30fc16c904"],
624
624
  ["skills/lit-humanizer/scripts/detect.mjs", "cdec0aa65c61c36fc1d7fb78551029a5a362ff8693ba8e04a52b7366d5e42a36"],
@@ -626,7 +626,7 @@ export const canonicalSkillResourceManifest = Object.freeze(
626
626
  ["skills/lit-humanizer/scripts/ko-metrics.mjs", "5e53d6dfb212241fbcbddaa5d89cacfda61fa739616b4d1a3dd4d76268b0d871"],
627
627
  ["skills/lit-humanizer/scripts/scan-input.mjs", "2743185b72ab3ef5d94b389f0f6aba12d3beb945e717e06090e4aeaffdd00ac9"],
628
628
  ["skills/lit-pptx/NOTICE", "3b8ee9072906635575aded1e2d2eed51dec1284af9f6ccd47151de376f541153"],
629
- ["skills/lit-pptx/SKILL.md", "6eb619d72a6eb77a95fbbd584e941a7a64359fb69268930fbe390a10f3bcb560"],
629
+ ["skills/lit-pptx/SKILL.md", "7a7f7dadc4bf44ce9008a0b8120c8147b79859b1eb42b5861a249c3d45714521"],
630
630
  ["skills/lit-pptx/assets/azure/circle-lg.png", "20c10807b0bda06766bb82ab257d2a10f815337c828ee9c6d74852569779fee0"],
631
631
  ["skills/lit-pptx/assets/azure/circle-md.png", "4e155989472a4c5b786f8f2cec717f54c5931af3386025e808bb930f03e53bae"],
632
632
  ["skills/lit-pptx/assets/azure/circle-sm.png", "27e355441a8c2b8747a1ba065d0b0ca900e3b5e66bac4d5d72b05e7d383d8689"],
@@ -648,17 +648,17 @@ export const canonicalSkillResourceManifest = Object.freeze(
648
648
  ["skills/lit-pptx/references/agents/synthesizer.md", "a497001d0622c1df6b6772748969c69dfe14fee6b18ec174d0b4ec74968161af"],
649
649
  ["skills/lit-pptx/references/agents/thesis.md", "b4bd2c6056f167beebf345996767e6a54011f14dc339aebcebaaf6fbaf4e828e"],
650
650
  ["skills/lit-pptx/references/anti-slop-checklist.md", "2ffca3f0e86086e95cfc27c50f69cb54581020755cf64c238680c82d249c212a"],
651
- ["skills/lit-pptx/references/authoring-guide.md", "a3cf2304614fa1abaccb6e609a645976c7af704a4f98dd46aaa67d5692de6ba0"],
651
+ ["skills/lit-pptx/references/authoring-guide.md", "ae68ba4291f595b0349c637363729cf84e88a8096f1e7592b706bb1573dd6182"],
652
652
  ["skills/lit-pptx/references/consensus-protocol.md", "5f4b31841edca43c0d88f84a06a7ef3ca21d1fa23d94acd337c137da1a068bdd"],
653
- ["skills/lit-pptx/references/data-display-cookbook.md", "c2a9a311e6eb25c1d9f17e6145fadafcc84db6a17ccb727baa9168aa8a2e2f53"],
654
- ["skills/lit-pptx/references/density-and-fill.md", "3741542502273fa4620149c4732f590e5daef1969e1abde443e10ca520b5b8ed"],
653
+ ["skills/lit-pptx/references/data-display-cookbook.md", "c9f5cb5056a4fc19f7cee2def8172337af1ea7848344efc92bdddc16530ac533"],
654
+ ["skills/lit-pptx/references/density-and-fill.md", "7d257dc66da4760b3ad22166dbb0191020d4d179f5def4dd6153926ee4ca1cb5"],
655
655
  ["skills/lit-pptx/references/design-system-azure.md", "7a6d2a2ce60a3b0eb8776460ad684b84acbc99a90e3257eb1a8209aaadfb6294"],
656
656
  ["skills/lit-pptx/references/direction-step.md", "a3a729ddc4144df7b2938b8fa9e5c570819620bccbf22995568c3a95673e9864"],
657
657
  ["skills/lit-pptx/references/examples/01-pitch-signal-ko.md", "eca98c5f64cc09cb55b6154cf8d33e5d3cb41a39474181de9078b46a4e1927fe"],
658
658
  ["skills/lit-pptx/references/examples/02-pitch-studio-ko.md", "0357937edcbd3ad0bda153c4671e69fc8a2f2c9b45a99a88d71b40e72ff30b12"],
659
659
  ["skills/lit-pptx/references/examples/03-business-review-ledger-ko.md", "e63d6148b68ccf113aea38fcd943cdd2b24801d6cb122fc838b758e6ca0c582e"],
660
660
  ["skills/lit-pptx/references/examples/04-business-review-night-en.md", "bbf54f7001cf41df6756cc105a42bdf69e97378f02384d6971558a6b33a74c5f"],
661
- ["skills/lit-pptx/references/examples/05-research-talk-paper-en.md", "119dbc21b44aed84f68b36ad5ed487a960820952072c7fd9fb485404fd983db5"],
661
+ ["skills/lit-pptx/references/examples/05-research-talk-paper-en.md", "41d9f0804aaa640c85c80cb9c94ee92d36b8a37ee79c36329c5bafbf4e263dd6"],
662
662
  ["skills/lit-pptx/references/examples/06-lecture-chalk-ko.md", "1f5c5e20ece711cff121742b4eb655c815aa2a3df6dff39ee3a85859c59225f4"],
663
663
  ["skills/lit-pptx/references/examples/07-data-review-night-en.md", "e3c52d3b3288deab0db8eaae82e963d893b2a267fd89c5edf88a25def8eb363a"],
664
664
  ["skills/lit-pptx/references/examples/08-image-led-atlas-ko.md", "1290d05ae02840e8055b97a043c603003faf71a3e1dce864f728712b1e61b087"],
@@ -667,7 +667,7 @@ export const canonicalSkillResourceManifest = Object.freeze(
667
667
  ["skills/lit-pptx/references/examples/11-portfolio-studio-en.md", "932e3e44947ee3d48e7c721744da8de6403264176f4fd9c95cc4382f7810c627"],
668
668
  ["skills/lit-pptx/references/examples/12-research-tutorial-chalk-en.md", "8a904158f421f9225785167a7be3b0a11e3f9ed46b0019565bcf105e45038a6e"],
669
669
  ["skills/lit-pptx/references/interview-protocol.md", "4194b549b0b8a293c7ad59ea4ca49b27053af9c7f2c68798053655901f17ad3a"],
670
- ["skills/lit-pptx/references/layout-families.md", "d818868933206811e2e20737ab22d223daacba198df258b098dbda1898cd7aa4"],
670
+ ["skills/lit-pptx/references/layout-families.md", "ad6a26453d643ce16281e634263eec84a2dbd9fdbfcfd73d5ed6994fa7a2ebd9"],
671
671
  ["skills/lit-pptx/references/stages/autopilot.md", "efa2e60b1a2e8df734ff7237af643430b0fa451ca72d266e5ac26547e600c53d"],
672
672
  ["skills/lit-pptx/references/stages/interview.md", "1d57f85cf1914019784c0f0eb827a0fd6f2d707ce11a87a93ed09c16832e8651"],
673
673
  ["skills/lit-pptx/references/stages/plan.md", "401e2f176020ee15de84e43a625605f7294ff2e351e86e3325a5657a85082023"],
@@ -677,7 +677,7 @@ export const canonicalSkillResourceManifest = Object.freeze(
677
677
  ["skills/lit-pptx/references/tonalities/gazette.md", "ff2e459c982cba824c29355bb6229802a90bb100675cd27d41ce446b130fae64"],
678
678
  ["skills/lit-pptx/references/tonalities/ledger.md", "84b8c5dd66b829c45e2c43536e92179ae260fbe466568f7e12f4baae9ead5309"],
679
679
  ["skills/lit-pptx/references/tonalities/night.md", "c26b005e0ab430037d07cfeb4a64913716b91087dda05e398768de465b413f3e"],
680
- ["skills/lit-pptx/references/tonalities/paper.md", "3cf05a6a19714b3b18b9c3f3ac40d65f56175f94faf046d4e02b9b333975152e"],
680
+ ["skills/lit-pptx/references/tonalities/paper.md", "901cb6b3c37615de7e723a4144ca3860bf47b3c154444faa740038c5779dd38b"],
681
681
  ["skills/lit-pptx/references/tonalities/signal.md", "48277d1165183e93343afb03aeaca6c39d4d249cfed178945a9f9a0e619e9bbc"],
682
682
  ["skills/lit-pptx/references/tonalities/studio.md", "c699df3fc2647e25c2d07f0cb5ad5face5a58903f06b3000d2a04dc653be2369"],
683
683
  ["skills/lit-pptx/scripts/compile-deck.js", "50d3f6663446f31c5ebc9e2773efd880ead396d368c2871b1d479f637fd5cb80"],
@@ -705,7 +705,7 @@ export const canonicalSkillResourceManifest = Object.freeze(
705
705
  ["skills/lit-pptx/scripts/package.json", "a51bff776fdd53226e2e67d8f654d17dadfe3decc8bf8bf869cba3aff9813826"],
706
706
  ["skills/lit-pptx/scripts/qa_deck.py", "9186cdb81846b6e3e10a1cdad015a81e08d0bd9cf2294fbcbfff7234431ba98c"],
707
707
  ["skills/lit-pptx/scripts/validate_pptx.py", "152b4ec92054dd49a71cd112d336a02b92299efa2d5d74eafb44ba68ff64d7b8"],
708
- ["skills/lit-pptx/specs/markdown-slide-spec-v1.md", "000089052be5f6fae073f4378dba296b23951e5e3e1ebcee51934d84594f132a"],
708
+ ["skills/lit-pptx/specs/markdown-slide-spec-v1.md", "e784855c6933e86dc7a6f24645480b7f02bab331d1b900362c00fa11e1e2abf6"],
709
709
  ["skills/lit-pptx/specs/markdown-slide-spec-v2.md", "c2f417ef458f4960eaee50befd12565636ace50d3aa07666be8fa14b6041c91b"],
710
710
  ["skills/lit-pptx/specs/slide-ast-v1.schema.json", "d5d03fab6569dc00484eca268601b6ac4dce496dfb586c3153693049f8376f1e"],
711
711
  ["skills/lit-pptx/specs/slide-ast-v2.schema.json", "e685dba539b34ec03ba8a7ab4a03338296360059ccdc91a4fbabd53b5770af86"],
@@ -233,6 +233,10 @@ export const parseGoals = (state, sessionId) => {
233
233
  .filter(Boolean),
234
234
  lastCheckpoint: str(Array.isArray(state.checkpoints) ? state.checkpoints.at(-1)?.status : null, 40),
235
235
  createdAt: time(state.createdAt),
236
+ // When the goal was finished: its last `complete` checkpoint, else its last update.
237
+ completedAt: state.status === "complete"
238
+ ? time((Array.isArray(state.checkpoints) ? state.checkpoints : []).findLast((entry) => entry?.status === "complete")?.createdAt) ?? time(state.updatedAt)
239
+ : null,
236
240
  };
237
241
  };
238
242
 
@@ -111,6 +111,10 @@ const entryOf = ({ snapshot, skills, now }) => {
111
111
  return candidates.sort((a, b) => b.at - a.at || (a.from === "record" ? -1 : 1))[0] ?? null;
112
112
  };
113
113
 
114
+ // A finished goal ends the map unless a stage record, skill or ignition came after it: that is a
115
+ // new request, and the old finish says nothing about it.
116
+ const goalFinished = (goal, entry) => goal?.status === "complete" && !(Number.isFinite(goal.completedAt) && Number.isFinite(entry?.at) && entry.at > goal.completedAt);
117
+
114
118
  const goalIsOpen = (goal) => Boolean(goal && ["active", "blocked", "review_blocked", "needs_user_decision"].includes(goal.status));
115
119
 
116
120
  // Without a discipline or a record, the durable state that says work is under way.
@@ -173,7 +177,7 @@ export const buildWorkflow = ({ snapshot, skills = [], completion = null, now })
173
177
  const planSaved = stage === "plan" && record?.stage === "plan" && record.done;
174
178
  if (planSaved) stage = "work";
175
179
  const lanes = record?.stage === "review" ? laneVerdicts(record.verdicts) : null;
176
- if (completion || goal?.status === "complete" || stage === "done") stage = "done";
180
+ if (completion || goalFinished(goal, entry) || stage === "done") stage = "done";
177
181
  else if (stage === "work" && !work && !goalIsOpen(goal) && snapshot.completedWorkIds.length > 0) stage = "review";
178
182
  else if (stage === "review" && lanes?.every(({ state }) => state === "pass")) stage = "done";
179
183
  if (planSaved && stage === "work" && !work) items.push("plan saved");
@@ -226,7 +230,7 @@ export const buildWorkflow = ({ snapshot, skills = [], completion = null, now })
226
230
  }
227
231
 
228
232
  const order = WORKFLOW_FAMILIES[family];
229
- const finished = family === "main" ? stage === "done" : completion !== null || (family === "loop" && snapshot.goal?.status === "complete");
233
+ const finished = family === "main" ? stage === "done" : completion !== null || (family === "loop" && goalFinished(snapshot.goal, entry));
230
234
  const current = finished ? -1 : order.indexOf(stage);
231
235
  const wave = sources.research?.wave ?? 0;
232
236
  const stages = order.map((id, index) => {
@@ -990,6 +990,14 @@ const classifyBashWords = (words, cwd) => {
990
990
  if (rest[0] === "start-work" && START_WORK_SELF_MOVES.has(rest[1]) && !rest.includes("--root") && rest.every((word) => !word.includes("/"))) {
991
991
  return canonicalBashTargets(cwd, [cwd, ...cli], "write");
992
992
  }
993
+ // `pause` is how the work asks the user for a new boundary: it records the pending boundary
994
+ // and grants nothing, so the root it names may lie outside the grants, and the lifecycle
995
+ // refuses a forbidden action itself. Only that `--target-root` value may hold a `/`, and only
996
+ // the bare CLI name passes: a `node <path>/litclaude-ai.js` file is checked by name, not content.
997
+ if (cli.length === 0 && rest[0] === "start-work" && rest[1] === "pause" && !rest.includes("--root")
998
+ && rest.every((word, index) => !word.includes("/") || rest[index - 1] === "--target-root")) {
999
+ return canonicalBashTargets(cwd, [cwd, ...cli], "write");
1000
+ }
993
1001
  }
994
1002
  if (head.text === "node") return classifyNodeScriptWords(args, cwd);
995
1003
  return null;
@@ -151,7 +151,7 @@ python3 "$SKILL_ROOT/scripts/generate_docx_templates.py" --registry my-registry.
151
151
 
152
152
  - Lead with the conclusion; one idea per paragraph; paragraphs of three to five sentences.
153
153
  - Plain, specific wording. No AI-tell phrases, stock openers or closers, hedging pile-ups or promotional adjective stacks — the same list the lint enforces (`references/slop_rules.md`, `references/slop_phrase_list.yaml`).
154
- - Separate observation, inference, limitation and proposal; expand abbreviations on first use.
154
+ - Separate observation, inference and proposal. State a genuine limit of the data or method one time, next to the figure it qualifies ("샘플은 한 공정 조건만 포함한다"); what the document is not for goes in the reply, never into the body. Expand abbreviations on first use.
155
155
  - Korean: consistent sentence endings (보고서 ~다 체 unless the user's material uses another register), no English words where a common Korean term exists, numbers with units and thousands separators.
156
156
 
157
157
  ## #contract.outputs
@@ -41,7 +41,7 @@ features (`qa_docx.py a.docx --compare b.docx`, check `tonality.structure`).
41
41
  - **Numbering.** Decimal: h1 `1`, h2 `1.1`, in plain ink at heading size, so cross-references resolve.
42
42
  References or further reading close the piece as a numbered list; that back-matter heading is left
43
43
  unnumbered.
44
- - **Components and their purpose.** One kind only: `callout`, for a definition, a caveat or a method
44
+ - **Components and their purpose.** One kind only: `callout`, for a definition, a data fact or a method
45
45
  note that sits outside the line of argument, at about one per four pages. It is drawn as a 1 pt ink
46
46
  rule down its left side with a bold title, no fill. A `::: sidebar`, `::: keyfigures` or `::: columns`
47
47
  written in the source keeps its content as ordinary text with its title as a bold lead line, and
@@ -16,7 +16,8 @@ This original category comes from the 26 real lines in fixtures/pos-real.txt and
16
16
  - en-demo-self-disclaimer — en, block. A demonstration label attached to a synthesis, assumption or recommendation is process framing. Name what is proposed and what was measured.
17
17
  - ko-bracket-status-tag and en-bracket-status-tag — ko/en, block. Replace bracket keys with a sentence describing the status.
18
18
  - ko-standalone-scope-disclaimer and en-standalone-scope-disclaimer — ko/en, block for stock disclaimers. Preserve a user-requested legal, medical or safety notice and place it once where it applies.
19
- - ko-status-negation, ko-mi-status, en-epistemic-negation and en-not-performed — warnings. A negative result or unperformed action may be the finding. Write the actor, scope and verb plainly; never turn unknown into false or an estimate into a fact.
19
+ - ko-negative-pledge, ko-negative-pledge-repeat and en-negative-pledge — ko/en, block. A line that tells the reader what the document, table or number is not for (`동일 조건의 독립 성능 비교로 쓰지 않음`, `외부 공개용 수치가 아님`, `This is not intended as a head-to-head benchmark`) is a promise about the document, not a finding. ko-negative-pledge reads one line at a time and fires on three shapes only: a self-reference topic (이/본/해당/위/아래 plus a document noun) with a negated claim verb or claim noun, a comparison or ranking noun with a negated use verb, and a purpose-용 data noun with 아님. ko-negative-pledge-repeat reads the whole text and fires when two such sentences end in 해석하지/주장하지/대표하지 않음 or a claim noun plus 아님. en-negative-pledge needs a comparison, benchmark or ranking noun, or `makes no claim`. Say it once as a fact beside the number it affects (`샘플은 한 공정 조건만 포함한다`), or move it to the reply. Operating rules (`방폭 구역에서 사용하지 않습니다`), negative findings (`첨가제 B는 수율을 개선하지 않았다`), and legal, financial or safety notices (대체하, 보장하, 권유 and `substitute for professional advice`) stay clean on purpose. The guard scans only the text a write adds, so a second pledge appended with an Edit to a file that already holds one is not counted by the repeat rule.
20
+ - ko-status-negation, ko-mi-status, en-epistemic-negation and en-not-performed — warnings. ko-status-negation also reads `쓰지 않음` and the 않습니다/않았습니다 endings, with or without bold around the ending, so a method line such as `실제 운영 데이터로 검증하지 않았습니다` is flagged for a context check and never refused. A negative result or unperformed action may be the finding. Write the actor, scope and verb plainly; never turn unknown into false or an estimate into a fact.
20
21
  - ko-plain-meta-label-warn and en-plain-caveat-label — warnings for boundary headings. They may be useful in internal or technical packets.
21
22
  - en-knowledge-cutoff, en-ai-self-disclaimer, en-hope-helps and ko-chatbot-signoff — block. Remove the model wrapper or generic sign-off, then retain the answer.
22
23
  - ko-chatbot-opener and en-chatbot-opener — block stock greetings and praise at the start of a deliverable.
@@ -185,7 +185,7 @@
185
185
  "id": "ko-status-negation",
186
186
  "lang": "ko",
187
187
  "severity": "warn",
188
- "pattern": "(?:검증|실측|측정|실행|실시|시작|확인|보장|평가|판단|조언|의미|증명|재현|사용|제공|적용|쓰)(?:[된한]\\s*(?:적이|값이)?|하지(?:\\s*않(?:음|는다|았다))?|되지\\s*않(?:음|는다|았다)|이|은|는)?\\s*(?:아님|않음|않는다|않았다|없음)|보류",
188
+ "pattern": "(?:검증|실측|측정|실행|실시|시작|확인|보장|평가|판단|조언|의미|증명|재현|사용|제공|적용|쓰)(?:[된한](?:\\s*(?:적이|값이))?|하지(?:\\s*않(?:음|는다|았다))?|되지\\s*않(?:음|는다|았다)|(?<=쓰)지|이|은|는)?\\s*(?:(?:\\*\\*|__)\\s*)?(?:아님|않음|않는다|않았다|않습니다|않았습니다|없음)|보류",
189
189
  "flags": "im",
190
190
  "scope": "line",
191
191
  "context": [
@@ -879,6 +879,57 @@
879
879
  "en-chatbot-closer:positive",
880
880
  "en-chatbot-closer:negative"
881
881
  ]
882
+ },
883
+ {
884
+ "id": "ko-negative-pledge",
885
+ "lang": "ko",
886
+ "severity": "block",
887
+ "pattern": "(?<![가-힣])(?:이|본|해당|위|아래)\\s+(?:자료|문서|보고서|슬라이드|덱|표|그림|그래프|차트|수치|결과|비교|분석|내용|예시)(?:은|는)\\s[^.!?\\n]{0,40}?(?:(?:해석하|의미하|주장하|대표하)(?:지\\s*(?:[*_]{1,2}\\s*)?(?:않(?:음|는다|습니다)|말\\s*것|마세요|마십시오)|(?:으)?면\\s*(?:[*_]{1,2}\\s*)?안\\s*(?:됨|된다|됩니다))|(?:(?:비교|결론|벤치마크|순위|대표값|일반화)(?:이|가)|목적이|위한\\s*것이)\\s*(?:[*_]{1,2}\\s*)?(?:아님|아니다|아닙니다)(?![가-힣]))|(?:비교|결론|벤치마크|순위|대표값|일반화)(?:으로|로)\\s*(?:[*_]{1,2}\\s*)?(?:쓰|사용하|해석하|읽|간주하|인용하)(?:지\\s*(?:[*_]{1,2}\\s*)?(?:않(?:음|는다|습니다)|말\\s*것|마세요|마십시오)|(?:으)?면\\s*(?:[*_]{1,2}\\s*)?안\\s*(?:됨|된다|됩니다))|(?:공개|배포|대외|외부|홍보|발표|보고|비교|인용|공식)용\\s*(?:자료|문서|수치|표|그래프)(?:이|가)\\s*(?:[*_]{1,2}\\s*)?(?:아님|아니다|아닙니다)(?![가-힣])",
888
+ "flags": "m",
889
+ "scope": "line",
890
+ "context": [
891
+ "fenced_code",
892
+ "quoted_user_text"
893
+ ],
894
+ "rationale": "A sentence that tells the reader what the document, table or number is not for belongs in the reply or becomes a data fact. Three shapes: a self-reference topic (이/본/해당/위/아래 + document noun + 은/는) with a negated claim verb or a claim noun + 아님 within one bullet; a comparison or ranking noun + (으)로 + a negated use verb; a purpose-용 data noun (공개용 수치) + 아님. Use verbs after a self-reference, 근거/평가/증거/추천, and legal or financial notices (대체하, 보장하, 권유) stay outside the pattern because operating rules, method lines and standard notices use them.",
895
+ "fixture_ids": [
896
+ "ko-negative-pledge:positive",
897
+ "ko-negative-pledge:negative"
898
+ ]
899
+ },
900
+ {
901
+ "id": "ko-negative-pledge-repeat",
902
+ "lang": "ko",
903
+ "severity": "block",
904
+ "pattern": "(?:(?:해석하|주장하|대표하)지\\s*(?:[*_]{1,2}\\s*)?않(?:음|습니다)|(?:비교|결론|벤치마크|순위|대표값|일반화)(?:이|가)\\s*(?:[*_]{1,2}\\s*)?(?:아님|아닙니다)(?![가-힣]))(?:[*_]{1,2})?(?=\\s*(?:[.!?。]|$))[\\s\\S]*?(?:(?:해석하|주장하|대표하)지\\s*(?:[*_]{1,2}\\s*)?않(?:음|습니다)|(?:비교|결론|벤치마크|순위|대표값|일반화)(?:이|가)\\s*(?:[*_]{1,2}\\s*)?(?:아님|아닙니다)(?![가-힣]))(?:[*_]{1,2})?(?=\\s*(?:[.!?。]|$))",
905
+ "flags": "m",
906
+ "scope": "document",
907
+ "context": [
908
+ "fenced_code",
909
+ "quoted_user_text"
910
+ ],
911
+ "rationale": "Two or more sentences that end in 해석하지/주장하지/대표하지 않음 or a claim noun + 이/가 + 아님 turn a document into a list of disclaimers. 의미하, 간주하, 인용하 and the use verbs are left out because repeated definitions, data-processing rules, method lines and operating rules end that way; a single such sentence stays with the warn-only ko-status-negation.",
912
+ "fixture_ids": [
913
+ "ko-negative-pledge-repeat:positive",
914
+ "ko-negative-pledge-repeat:negative"
915
+ ]
916
+ },
917
+ {
918
+ "id": "en-negative-pledge",
919
+ "lang": "en",
920
+ "severity": "block",
921
+ "pattern": "\\b(?:this|these)\\s+(?:deck|report|document|analysis|table|chart|figure|figures|numbers|results|slide|comparison)\\s+(?:(?:is|are)\\s+not\\s+(?:intended|meant|to\\s+be\\s+(?:read|used|taken|interpreted))(?:\\s+to\\s+be\\s+(?:read|used|taken|interpreted))?\\s+as\\b(?!\\s*(?:a\\s+substitute|a\\s+replacement|(?:legal|investment|medical|professional)\\s+advice))\\s+(?:an?\\s+|the\\s+)?(?:[A-Za-z0-9-]+\\s+){0,4}?(?:comparison|benchmark|ranking)s?\\b(?!-)(?!\\s+(?:arm|arms|group|groups|standard|standards|class|baseline)\\b)|(?:should|must)\\s+not\\s+be\\s+(?:read|used|taken|interpreted)\\s+as\\s+(?:an?\\s+|the\\s+)?(?:[A-Za-z0-9-]+\\s+){0,4}?(?:comparison|benchmark|ranking)s?\\b(?!-)(?!\\s+(?:arm|arms|group|groups|standard|standards|class|baseline)\\b)|makes?\\s+no\\s+claims?\\s+(?:about|that|regarding|as\\s+to)\\b)|\\b(?:this|these)\\s+(?:is|are)\\s+not\\s+(?:intended|meant)\\s+as\\b(?!\\s*(?:a\\s+substitute|a\\s+replacement|(?:legal|investment|medical|professional)\\s+advice))\\s+(?:an?\\s+|the\\s+)?(?:[A-Za-z0-9-]+\\s+){0,4}?(?:comparison|benchmark|ranking)s?\\b(?!-)(?!\\s+(?:arm|arms|group|groups|standard|standards|class|baseline)\\b)|\\bthe\\s+(?:deck|report|document|analysis)\\s+makes?\\s+no\\s+claims?\\s+(?:about|that|regarding|as\\s+to)\\b|(?:^|\\s[-*]\\s)\\s*(?:[-*]\\s+|\\d+\\.\\s+)?(?:[*_]{1,2})?not\\s+(?:intended|meant|to\\s+be\\s+read|to\\s+be\\s+used)\\s+as\\b(?!\\s*(?:a\\s+substitute|a\\s+replacement|(?:legal|investment|medical|professional)\\s+advice))\\s+(?:an?\\s+|the\\s+)?(?:[A-Za-z0-9-]+\\s+){0,4}?(?:comparison|benchmark|ranking)s?\\b(?!-)(?!\\s+(?:arm|arms|group|groups|standard|standards|class|baseline)\\b)|\\b(?:this|these)\\s+(?:table|chart|figure|figures|numbers|results|comparison|analysis)\\s+(?:does|do)\\s+not\\s+constitute\\s+(?:an?\\s+)?[^.!?]{0,60}?\\b(?:comparison|benchmark|ranking)s?\\b(?!-)(?!\\s+(?:arm|arms|group|groups|standard|standards|class|baseline)\\b)",
922
+ "flags": "i",
923
+ "scope": "sentence",
924
+ "context": [
925
+ "fenced_code",
926
+ "quoted_user_text"
927
+ ],
928
+ "rationale": "A sentence that says the deck, report or numbers are not intended, meant or to be read as a comparison, benchmark or ranking, or make no claim about something belongs in the reply, and so does a table, chart or set of numbers that does not constitute one. Requiring one of those nouns keeps safety labels and advice, offer or diagnosis notices clean; \"does not constitute\" for a report or document stays a notice form, and \"the\" is not a subject except with \"makes no claim\".",
929
+ "fixture_ids": [
930
+ "en-negative-pledge:positive",
931
+ "en-negative-pledge:negative"
932
+ ]
882
933
  }
883
934
  ]
884
935
  }
@@ -208,7 +208,7 @@ The full checklist is `references/anti-slop-checklist.md`; each tonality's token
208
208
  - **Colour.** Every colour comes from the pack's roles. Tinted neutrals carry most of the surface, one accent ≤ ~10% marks the single emphasised item. One colour, one meaning, across the deck. No per-slide one-off hex.
209
209
  - **Contrast floors.** Body and captions 4.5:1 on their actual fill, large text and structural lines 3:1. Push toward ink when close; no grey text on a coloured fill.
210
210
  - **Anti-slop bans.** No side-stripe accent bars, no border plus heavy shadow on one card, no card inside a card, no eyebrow or 01·02·03 ordinal on every slide, no identical icon-card grids as filler, no cream or beige reading ground, no hand-drawn decoration, no generic titles ("개요", "Overview"), no declarative titles or subtitles, no single exaggerated number as a slide, no padding bullets that restate the title, no placeholder or AI-tell wording.
211
- - **Evidence.** Separate observation, inference, limitation and proposal. Every sourced number traces to its source and every example value is labelled as one; every figure or table carries a caption with 출처/Source or "(예시)". Expand specialist abbreviations on first use. Unsupported absolutes are review findings.
211
+ - **Evidence.** Separate observation, inference and proposal. State a genuine limit of the data or method one time, next to the figure it qualifies ("샘플은 한 공정 조건만 포함한다"); what the deck is not for goes in the reply, never onto a slide. Every sourced number traces to its source and every example value is labelled as one; every figure or table carries a caption with 출처/Source or "(예시)". Expand specialist abbreviations on first use. Unsupported absolutes are review findings.
212
212
 
213
213
  ## #contract.outputs
214
214
 
@@ -108,12 +108,12 @@ These are semantic compositions of existing v1 blocks, so they remain renderer c
108
108
  ![Figure 1. Pressure trend | Source: test report, p. 12](assets/pressure.png)
109
109
 
110
110
  - **Observation** Pressure remained inside the validated band.
111
- (1) Limitation: one operating condition was not sampled.
111
+ (1) Basis: only one operating condition was sampled.
112
112
  (2) Implication: repeat the test before scale-up.
113
113
  ```
114
114
 
115
115
  2. **table plus decision takeaway** — keep units in headers, quantitative cells compact, ≤6 columns, and add a blockquote caption/source immediately after the table.
116
- 3. **source capture** — use a legible screenshot with locator/date in the alt text and state its limitation and relevance in the body.
116
+ 3. **source capture** — use a legible screenshot with locator/date in the alt text and state in the body what it shows and why it matters.
117
117
  4. **two-record appendix evidence** — show at most two records per slide; include a one-line summary, source locator, and clickable DOI/canonical link when available. In a table cell, write `[원문](https://example.org/record)`; the PPTX renderer emits an external OOXML hyperlink relationship.
118
118
 
119
119
  Do not write authoring trace or unresolved placeholders. Treat overclaim, jargon, imperative tone, unsupported schedules, hierarchy, and visual density as review-only items to resolve during rendered page review.
@@ -39,7 +39,7 @@ Place source text under the table/chart, smaller than body text:
39
39
 
40
40
  ## Evidence display patterns
41
41
 
42
- - **figure plus interpretation:** one figure, numbered caption, source locator, limitation, and a concise interpretation placed as one visual group.
42
+ - **figure plus interpretation:** one figure, numbered caption, source locator, the data basis beside the number it bounds, and a concise interpretation placed as one visual group.
43
43
  - **table plus decision takeaway:** one bounded table, caption/source, and one decision sentence. Do not duplicate the table in prose.
44
44
  - **source capture:** crop to the relevant region while retaining enough interface/document context to verify the locator.
45
45
  - **two-record appendix evidence:** at most two records per slide. Each record includes summary, source/locator, and DOI/canonical link when available.
@@ -100,7 +100,7 @@ lower part of the body.
100
100
  four to six columns where the source has them, charts five to eight categories, comparisons three
101
101
  or four labelled criteria a side. Example values are labelled as examples.
102
102
  - **Close every data slide with its source.** A last line `출처: …` (`Source: …`) names where the
103
- figures come from and when; a `주: …` (`Note: …`) line may follow with a definition or a caveat.
103
+ figures come from and when; a `주: …` (`Note: …`) line may follow with a definition or a data fact.
104
104
  The engine sets them as a strip at the foot of the body, at source size, so they cost the takeaways
105
105
  no room.
106
106
  - **Figures come in rows of four to six.** A `kpi-row` table holds up to six figures, its second row
@@ -36,8 +36,7 @@ layout: figure-academic
36
36
 
37
37
  - **Observation** Conversion stalls after 30 minutes: 44% at 30 min, 50% at 60 min
38
38
  - **Observation** The baseline gains only 6 points after minute 30
39
- - **Basis** 1.0 L/min feed, 20 L reactor, three replicates (example data)
40
- - **Limitation** One temperature and one catalyst batch were tested
39
+ - **Basis** 1.0 L/min feed, 20 L reactor, three replicates at one temperature and one catalyst batch (example data)
41
40
  - **Implication** The plateau, not the kinetics, limits throughput
42
41
  - Source: Example Process Lab baseline runs B1-B3, May 2026 (example data)
43
42
  ---
@@ -48,7 +48,7 @@ Each row says what the family is for, what the source gives it, and which packs
48
48
  | `image-split` | a picture beside its explanation | an image, then bullets | signal, atlas, chalk, studio |
49
49
  | `photo-grid` | two or three pictures compared | two or three images on consecutive lines, then one line of text | atlas, studio |
50
50
  | `figure-pair` | before and after, or two conditions | two images, then one line of text | atlas, paper |
51
- | `figure-academic` | a numbered figure with its reading | an image with a numbered caption and source, then observation, limitation, implication bullets | paper |
51
+ | `figure-academic` | a numbered figure with its reading | an image with a numbered caption and source, then observation, basis, implication bullets | paper |
52
52
  | `asymmetric-feature` | a feature told by one large element and a narrow text column | an image or a one-cell figure, then bullets | signal, atlas, studio |
53
53
  | `references-appendix` | sources and definitions, one per row | `- [1] …` lines; links as real Markdown links | ledger, paper, gazette |
54
54
 
@@ -61,7 +61,7 @@ its `layout:` line, for example `title: top-rule`, as long as the family allows
61
61
 
62
62
  ## Families and variants
63
63
 
64
- - `figure-academic`: one figure with its numbered caption and a short observation, limitation and
64
+ - `figure-academic`: one figure with its numbered caption and a short observation, basis and
65
65
  implication.
66
66
  - `figure-pair`: two figures side by side, for before and after or two conditions.
67
67
  - `method`: a formula or process figure beside the definitions of its symbols.
@@ -88,8 +88,8 @@ closing's next step sits under a rule at the foot of the page, its rows keyed by
88
88
 
89
89
  Number every figure and table caption and give each a source. Title each slide with what it shows
90
90
  ("Conversion at 60 min by feed rate"), and put the finding in the first observation. Keep the crimson for the proposed
91
- method in every chart, so the audience learns its meaning on the first plot. Put the limitation on
92
- the same slide as the result it limits. End with the reference list, so the last page carries the
91
+ method in every chart, so the audience learns its meaning on the first plot. Put the data fact that
92
+ bounds a result on the same slide, beside the number it affects. End with the reference list, so the last page carries the
93
93
  deck's sources.
94
94
 
95
95
  ## Avoid
@@ -236,7 +236,7 @@ Enrolled templates may advertise these semantic compositions of existing blocks:
236
236
 
237
237
  - **figure plus interpretation:** `image` + `figure-caption` + body interpretation;
238
238
  - **table plus decision takeaway:** table/`kpi-table` + `table-caption` + body takeaway;
239
- - **source capture:** `image` + `figure-caption` containing locator/source + body limitation/relevance;
239
+ - **source capture:** `image` + `figure-caption` containing locator/source + body relevance and data basis;
240
240
  - **two-record appendix evidence:** title/body or `summary-group`, with no more than two records and DOI/canonical links when available.
241
241
 
242
242
  For a Markdown image used as evidence, alt text is the visible figure caption and should contain a figure number plus `Source:`/`출처:`. A blockquote immediately after a table is its visible table caption/source. Appendix DOI/canonical/raw URL fields use `[label](https://...)` in table cells so the PPTX contains an external hyperlink relationship. These requirements reuse existing parser and renderer behavior.