@litfamily/litmuse 0.1.1 → 0.1.3

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.
Files changed (177) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +23 -1
  3. package/README_ko-KR.md +23 -1
  4. package/TRADEMARK.md +12 -0
  5. package/bin/litmuse.mjs +4 -0
  6. package/lib/stage-card.mjs +249 -6
  7. package/package.json +3 -2
  8. package/plugin/.muse-plugin/plugin.json +26 -11
  9. package/plugin/commands/lit-status.md +3 -1
  10. package/plugin/commands/lit.md +1 -1
  11. package/plugin/hooks/lib/digest.mjs +1 -1
  12. package/plugin/hooks/lib/next-step.mjs +112 -0
  13. package/plugin/hooks/lib/routes.mjs +59 -0
  14. package/plugin/hooks/lib/stage.mjs +53 -6
  15. package/plugin/hooks/lib/workflow-stack.mjs +336 -0
  16. package/plugin/hooks/post-tool-use-failure.mjs +2 -0
  17. package/plugin/hooks/post-tool-use.mjs +2 -0
  18. package/plugin/hooks/session-end.mjs +2 -1
  19. package/plugin/hooks/session-start.mjs +32 -2
  20. package/plugin/hooks/stop.mjs +23 -3
  21. package/plugin/hooks/user-prompt-submit.mjs +138 -7
  22. package/plugin/lib/capped-fetch.mjs +25 -0
  23. package/plugin/lib/pinned-fetch.mjs +79 -0
  24. package/plugin/lib/plan-task-rows.mjs +32 -0
  25. package/plugin/lib/render_pages.py +29 -1
  26. package/plugin/lib/rewind/collect.mjs +808 -0
  27. package/plugin/lib/rewind/gauge.mjs +72 -0
  28. package/plugin/lib/rewind/next-step.mjs +91 -0
  29. package/plugin/lib/rewind/redact.mjs +83 -0
  30. package/plugin/lib/rewind/transcripts.mjs +229 -0
  31. package/plugin/skills/frontend-ui-ux/SKILL.md +24 -9
  32. package/plugin/skills/frontend-ui-ux/kit/components.css +414 -0
  33. package/plugin/skills/frontend-ui-ux/kit/fonts.json +22 -0
  34. package/plugin/skills/frontend-ui-ux/kit/layouts/landing.html +164 -0
  35. package/plugin/skills/frontend-ui-ux/kit/layouts/settings.html +114 -0
  36. package/plugin/skills/frontend-ui-ux/kit/layouts/workspace.html +115 -0
  37. package/plugin/skills/frontend-ui-ux/kit/styles/computational-brutalism.json +227 -0
  38. package/plugin/skills/frontend-ui-ux/kit/styles/field-notes.json +205 -0
  39. package/plugin/skills/frontend-ui-ux/kit/styles/graphite.json +200 -0
  40. package/plugin/skills/frontend-ui-ux/kit/styles/meadow.json +199 -0
  41. package/plugin/skills/frontend-ui-ux/kit/styles/neo-brutalism.json +222 -0
  42. package/plugin/skills/frontend-ui-ux/kit/ui.js +226 -0
  43. package/plugin/skills/frontend-ui-ux/references/complete-contract.md +2 -1
  44. package/plugin/skills/frontend-ui-ux/references/craft-floor.md +9 -4
  45. package/plugin/skills/frontend-ui-ux/references/default-editorial-pixel.json +59 -7
  46. package/plugin/skills/frontend-ui-ux/references/house-styles.md +234 -0
  47. package/plugin/skills/frontend-ui-ux/references/motion-guide.md +3 -3
  48. package/plugin/skills/frontend-ui-ux/references/slop-register.md +7 -7
  49. package/plugin/skills/frontend-ui-ux/scripts/design-lock.mjs +400 -0
  50. package/plugin/skills/frontend-ui-ux/scripts/interface-probe-lock.mjs +196 -0
  51. package/plugin/skills/frontend-ui-ux/scripts/interface-probe-page.mjs +31 -10
  52. package/plugin/skills/frontend-ui-ux/scripts/interface-probe-rules.mjs +19 -7
  53. package/plugin/skills/frontend-ui-ux/scripts/interface-probe-static.mjs +4 -0
  54. package/plugin/skills/frontend-ui-ux/scripts/interface-probe.mjs +59 -7
  55. package/plugin/skills/frontend-ui-ux/scripts/pixel-art.mjs +60 -0
  56. package/plugin/skills/lit-adhd/SKILL.md +195 -0
  57. package/plugin/skills/lit-adhd/references/card-examples.md +121 -0
  58. package/plugin/skills/lit-adhd/references/status-taxonomy.md +45 -0
  59. package/plugin/skills/lit-adhd/scripts/rewind.mjs +11 -0
  60. package/plugin/skills/lit-diagram-drawer/SKILL.md +3 -3
  61. package/plugin/skills/lit-diagram-drawer/scripts/diagram-craft-rules.mjs +1 -2
  62. package/plugin/skills/lit-diagram-drawer/scripts/visual-quality.mjs +0 -1
  63. package/plugin/skills/lit-docx/SKILL.md +1 -1
  64. package/plugin/skills/lit-hijack/SKILL.md +589 -0
  65. package/plugin/skills/lit-hijack/references/capture-and-provenance.md +123 -0
  66. package/plugin/skills/lit-hijack/references/clean-room-build.md +133 -0
  67. package/plugin/skills/lit-hijack/references/distil-and-licence.md +128 -0
  68. package/plugin/skills/lit-hijack/references/gap-and-port-design.md +152 -0
  69. package/plugin/skills/lit-hijack/references/parity-and-report.md +133 -0
  70. package/plugin/skills/lit-hijack/scripts/hijack.mjs +879 -0
  71. package/plugin/skills/lit-plan/SKILL.md +12 -1
  72. package/plugin/skills/lit-plan/scripts/check-plan.mjs +71 -4
  73. package/plugin/skills/lit-pptx/SKILL.md +20 -9
  74. package/plugin/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Bold.ttf +0 -0
  75. package/plugin/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Regular.ttf +0 -0
  76. package/plugin/skills/lit-pptx/fonts/jetbrains-mono/OFL.txt +93 -0
  77. package/plugin/skills/lit-pptx/fonts/provenance.json +32 -1
  78. package/plugin/skills/lit-pptx/references/direction-step.md +19 -2
  79. package/plugin/skills/lit-pptx/references/examples/13-engineering-review-computational-brutalism-ko.md +173 -0
  80. package/plugin/skills/lit-pptx/references/examples/14-launch-pitch-neo-brutalism-ko.md +154 -0
  81. package/plugin/skills/lit-pptx/references/examples/15-design-lecture-bauhaus-ko.md +139 -0
  82. package/plugin/skills/lit-pptx/references/examples/16-community-programme-riso-ko.md +158 -0
  83. package/plugin/skills/lit-pptx/references/examples/17-public-data-briefing-newsroom-ko.md +179 -0
  84. package/plugin/skills/lit-pptx/references/tonalities/bauhaus.md +112 -0
  85. package/plugin/skills/lit-pptx/references/tonalities/computational-brutalism.md +118 -0
  86. package/plugin/skills/lit-pptx/references/tonalities/neo-brutalism.md +125 -0
  87. package/plugin/skills/lit-pptx/references/tonalities/newsroom.md +115 -0
  88. package/plugin/skills/lit-pptx/references/tonalities/riso.md +109 -0
  89. package/plugin/skills/lit-pptx/scripts/compile-deck.js +1 -1
  90. package/plugin/skills/lit-pptx/scripts/craft_extras.py +136 -92
  91. package/plugin/skills/lit-pptx/scripts/embed_fonts.py +13 -1
  92. package/plugin/skills/lit-pptx/scripts/lib/grid-resolver.js +105 -116
  93. package/plugin/skills/lit-pptx/scripts/lib/layout-resolver.js +9 -15
  94. package/plugin/skills/lit-pptx/scripts/lib/render-pack.js +368 -561
  95. package/plugin/skills/lit-pptx/scripts/lib/slide-grid.js +104 -0
  96. package/plugin/skills/lit-pptx/scripts/lib/template-registry.js +57 -6
  97. package/plugin/skills/lit-pptx/scripts/qa_deck.py +4 -4
  98. package/plugin/skills/lit-pptx/templates/tonalities/atlas/pack.yaml +1 -1
  99. package/plugin/skills/lit-pptx/templates/tonalities/bauhaus/pack.yaml +98 -0
  100. package/plugin/skills/lit-pptx/templates/tonalities/chalk/pack.yaml +1 -1
  101. package/plugin/skills/lit-pptx/templates/tonalities/computational-brutalism/pack.yaml +99 -0
  102. package/plugin/skills/lit-pptx/templates/tonalities/gazette/pack.yaml +1 -1
  103. package/plugin/skills/lit-pptx/templates/tonalities/ledger/pack.yaml +1 -1
  104. package/plugin/skills/lit-pptx/templates/tonalities/neo-brutalism/pack.yaml +107 -0
  105. package/plugin/skills/lit-pptx/templates/tonalities/newsroom/pack.yaml +99 -0
  106. package/plugin/skills/lit-pptx/templates/tonalities/night/pack.yaml +1 -1
  107. package/plugin/skills/lit-pptx/templates/tonalities/paper/pack.yaml +1 -1
  108. package/plugin/skills/lit-pptx/templates/tonalities/riso/pack.yaml +99 -0
  109. package/plugin/skills/lit-pptx/templates/tonalities/signal/pack.yaml +2 -2
  110. package/plugin/skills/lit-pptx/templates/tonalities/studio/pack.yaml +1 -1
  111. package/plugin/skills/lit-recap/SKILL.md +3 -0
  112. package/plugin/skills/lit-schematic/SKILL.md +241 -0
  113. package/plugin/skills/lit-schematic/examples/iso-heat-exchanger/build.mjs +14 -0
  114. package/plugin/skills/lit-schematic/examples/iso-heat-exchanger/scene.mjs +8 -0
  115. package/plugin/skills/lit-schematic/examples/journal-adsorption-rig/build.mjs +22 -0
  116. package/plugin/skills/lit-schematic/examples/pid-dosing-skid/build.mjs +73 -0
  117. package/plugin/skills/lit-schematic/references/cutaway-outputs.md +25 -0
  118. package/plugin/skills/lit-schematic/references/isometric-craft.md +24 -0
  119. package/plugin/skills/lit-schematic/references/journal-figures.md +19 -0
  120. package/plugin/skills/lit-schematic/references/kit-api.md +27 -0
  121. package/plugin/skills/lit-schematic/references/pfd-and-layout.md +20 -0
  122. package/plugin/skills/lit-schematic/references/pid-drafting.md +26 -0
  123. package/plugin/skills/lit-schematic/references/pid-symbols.md +27 -0
  124. package/plugin/skills/lit-schematic/references/verification.md +24 -0
  125. package/plugin/skills/lit-schematic/scripts/doctor.mjs +13 -0
  126. package/plugin/skills/lit-schematic/scripts/lib/figure.mjs +49 -0
  127. package/plugin/skills/lit-schematic/scripts/lib/isa.mjs +18 -0
  128. package/plugin/skills/lit-schematic/scripts/lib/iso.mjs +58 -0
  129. package/plugin/skills/lit-schematic/scripts/lib/legend-sheet.mjs +10 -0
  130. package/plugin/skills/lit-schematic/scripts/lib/qa-core.mjs +241 -0
  131. package/plugin/skills/lit-schematic/scripts/lib/sheet.mjs +446 -0
  132. package/plugin/skills/lit-schematic/scripts/lib/svg.mjs +39 -0
  133. package/plugin/skills/lit-schematic/scripts/lib/theme.mjs +25 -0
  134. package/plugin/skills/lit-schematic/scripts/motion.mjs +8 -0
  135. package/plugin/skills/lit-schematic/scripts/qa.mjs +21 -0
  136. package/plugin/skills/lit-schematic/scripts/render.mjs +38 -0
  137. package/plugin/skills/lit-schematic/scripts/scaffold.mjs +73 -0
  138. package/plugin/skills/lit-scientific-visualization/SKILL.md +2 -0
  139. package/plugin/skills/lit-team/scripts/state-root.mjs +5 -18
  140. package/plugin/skills/lit-typographic-motion/SKILL.md +12 -8
  141. package/plugin/skills/lit-typographic-motion/engine/THIRD_PARTY_NOTICES +11 -0
  142. package/plugin/skills/lit-typographic-motion/engine/blender/runner.py +218 -0
  143. package/plugin/skills/lit-typographic-motion/engine/core/presets.mjs +1 -1
  144. package/plugin/skills/lit-typographic-motion/engine/node/assets.mjs +218 -0
  145. package/plugin/skills/lit-typographic-motion/engine/node/blender.mjs +144 -0
  146. package/plugin/skills/lit-typographic-motion/engine/node/board.mjs +136 -0
  147. package/plugin/skills/lit-typographic-motion/engine/node/done.mjs +42 -3
  148. package/plugin/skills/lit-typographic-motion/engine/node/gallery.mjs +120 -0
  149. package/plugin/skills/lit-typographic-motion/engine/node/house.mjs +44 -0
  150. package/plugin/skills/lit-typographic-motion/engine/node/pipeline.mjs +18 -7
  151. package/plugin/skills/lit-typographic-motion/engine/node/runtime.mjs +6 -3
  152. package/plugin/skills/lit-typographic-motion/engine/node/scaffold.mjs +210 -0
  153. package/plugin/skills/lit-typographic-motion/engine/node/score.mjs +639 -0
  154. package/plugin/skills/lit-typographic-motion/engine/node/sound-cli.mjs +21 -4
  155. package/plugin/skills/lit-typographic-motion/engine/node/sound.mjs +126 -27
  156. package/plugin/skills/lit-typographic-motion/engine/node/stage-serve.mjs +29 -5
  157. package/plugin/skills/lit-typographic-motion/engine/node/stage.mjs +82 -14
  158. package/plugin/skills/lit-typographic-motion/engine/node/styles.mjs +214 -0
  159. package/plugin/skills/lit-typographic-motion/engine/node/treatment.mjs +311 -10
  160. package/plugin/skills/lit-typographic-motion/engine/vendor/three/LICENSE +21 -0
  161. package/plugin/skills/lit-typographic-motion/engine/vendor/three/addons/environments/RoomEnvironment.js +144 -0
  162. package/plugin/skills/lit-typographic-motion/engine/vendor/three/addons/geometries/RoundedBoxGeometry.js +155 -0
  163. package/plugin/skills/lit-typographic-motion/engine/vendor/three/three.module.js +54571 -0
  164. package/plugin/skills/lit-typographic-motion/recipes/hero-3d/expected.json +69 -0
  165. package/plugin/skills/lit-typographic-motion/recipes/hero-3d/index.html +139 -0
  166. package/plugin/skills/lit-typographic-motion/references/depth.md +122 -0
  167. package/plugin/skills/lit-typographic-motion/references/sound.md +74 -16
  168. package/plugin/skills/lit-typographic-motion/references/stage.md +29 -5
  169. package/plugin/skills/lit-typographic-motion/references/studio.md +245 -0
  170. package/plugin/skills/lit-typographic-motion/references/treatment.md +31 -8
  171. package/plugin/skills/lit-typographic-motion/scripts/motion.mjs +48 -7
  172. package/plugin/skills/lit-typographic-motion/styles/paper.json +41 -0
  173. package/plugin/skills/lit-typographic-motion/styles/swiss-signal.json +41 -0
  174. package/plugin/skills/lit-typographic-motion/styles/terminalcore.json +42 -0
  175. package/plugin/skills/lit-typographic-motion/styles/tidal.json +41 -0
  176. package/plugin/skills/readme-studio/SKILL.md +1 -1
  177. package/plugin/skills/start-work/SKILL.md +10 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.3 — 2026-10-28
4
+
5
+ - After you save a plan, typing `go` within 30 minutes starts it. A plan saved by another session, or an older one, does not.
6
+ - lit-plan checks that every command touching a path outside the project is covered by a `Scope roots:` line, and start-work points to that check. A command quoted in a code block or inline code is treated as text and does not count.
7
+ - The LIT card is clearer about other sessions: running ones come first, then idle ones, each named by its skill and, inside herdr, its pane. A finished start-work stays as done for a minute and then leaves. When a newer LitMuse is installed than the one this session loaded, the card says `restart to <version>`.
8
+ - `lit-adhd` reads your plans before transcripts, keeps finished plans as complete, picks up the `## Next` section of this worktree's handoff, marks sessions as done or idle, and opens with a three-line summary. Its next step no longer repeats one that is already done.
9
+ - A linked git worktree keeps its own `.litmuse` state instead of writing into the main checkout's.
10
+ - New `TRADEMARK.md`: the code stays MIT; the LitMuse and LitFamily names and art are covered there.
11
+ - The hook code changed, so Muse asks you to approve the LitMuse hooks again after the update; `npx @litfamily/litmuse install` lists them and asks once.
12
+
13
+ ## 0.1.2 — 2026-10-27
14
+
15
+ - Three new skills, so LitMuse now has 42. `lit-schematic` draws P&IDs with ISA-5.1 tags and control loops, apparatus figures for papers and isometric cutaways, as editable SVG with a QA gate. `lit-hijack` studies a tool you point it at and rebuilds what you want from it clean-room, with a gate after each phase. `lit-adhd` (also `lit-rewind`) is a briefing across your recent Muse sessions: what each one asked, did and is waiting on, with a single next step that a bare `go` picks up.
16
+ - Workflow stacks: a lit route started inside another one pauses the first, and `lit continue` picks it back up. start-work waits for a typed `lit start plans/<name>.md` before it acts on a plan, and a bare `go` follows the next step the brief suggested.
17
+ - The LIT card (`/lit-status`, `litmuse status --card`) shows a row per open thread, an amber `YOUR TURN` headline when Muse waits on you, and a rainbow headline for every way of opening `lit-adhd` (`/lit-adhd`, `/litmuse:lit-adhd`, `lit-rewind`).
18
+ - Slides: five new tonalities (`bauhaus`, `computational-brutalism`, `neo-brutalism`, `newsroom`, `riso`), hero and decoration on every pack, grid zones, and JetBrains Mono as a face for titles and labels beside Pretendard. The slide, document, interface, diagram, schematic, README and film skills ask which theme or style you want before building, unless you already named one or said to choose.
19
+ - Films: house styles, a storyboard board you see before the full render, a 3D stage and an original layered score made for each film.
20
+ - The README has a gallery of real renders from these skills.
21
+ - Security fixes from review: the session brief masks secrets more reliably, including those in URLs and environment values; streamed downloads have size caps; three.js is pinned; and `lit-hijack` and the film asset downloads connect only to the address they checked and re-check every redirect, which closes a DNS-rebinding gap.
22
+ - The hook code changed, so Muse asks you to approve the LitMuse hooks again after the update; `npx @litfamily/litmuse install` lists them and asks once.
23
+
3
24
  ## 0.1.1 — 2026-10-26
4
25
 
5
26
  - The README studio's HyperFrames and Remotion cover templates pin newer `hono` and `fast-uri` in their lockfiles, picking up upstream fixes. A fresh template setup installs these versions.
package/README.md CHANGED
@@ -133,6 +133,26 @@ The snapshot names the trigger, the session, the route, the plan with its open r
133
133
 
134
134
  <p align="center"><img src="./docs/assets/handoff/latest.webp" width="960" alt="The handoff snapshot: trigger, session, the lit-plan route, the plan with 0 ticked and 2 open rows, and recent ledger lines." /></p>
135
135
 
136
+ ## What you can make
137
+
138
+ Four real outputs rendered on a Mac during the quality parity round, each opened, read, and fixed until it looked right:
139
+
140
+ <p align="center"><img src="./docs/assets/parity/lit-adhd-brief.png" width="960" alt="The lit-adhd brief in a real terminal: rainbow headline, one active session card with goal and work time, tools, the finished commit, and a boxed recommended next step." /></p>
141
+
142
+ `lit-adhd` briefs your live sessions: session cards with status badges, an ended table, and a boxed recommended step — colour on TTY, no internal field names leaking.
143
+
144
+ <p align="center"><img src="./docs/assets/parity/lit-pptx-deck.png" width="960" alt="A lit-pptx status deck: KPI row and a column chart of suite growth per wave." /></p>
145
+
146
+ `lit-pptx` compiles real decks from data: this one charts the port's own test-suite growth, wave by wave.
147
+
148
+ <p align="center"><img src="./docs/assets/parity/lit-schematic-pid.png" width="960" alt="A lit-schematic P&ID: a sodium hypochlorite dosing skid with tank TK-101, duty and standby dosing pumps, a relief-valve spillback, instrument bubbles, line numbers, a drawn-symbol legend, and title block EX-PID-001." /></p>
149
+
150
+ `lit-schematic` draws QA-checked P&IDs: a dosing skid with real symbols, a drawn legend, line numbers, and a title block — seven look rounds until every label read cleanly.
151
+
152
+ <p align="center"><img src="./docs/assets/parity/lit-frontend-page.png" width="960" alt="A frontend-ui-ux gallery page: dark ledger, phosphor accents, one plate per render, checked at phone, tablet, and desktop widths." /></p>
153
+
154
+ `frontend-ui-ux` builds the page around them: one gallery, one plate per render, checked at phone, tablet, and desktop widths.
155
+
136
156
  ## What you get
137
157
 
138
158
  **39 skills**, each a dense Muse skill loaded on demand, with the references, scripts, templates and engines it needs inside its own folder. The catalog only holds their short descriptions, about 3.7 KB in total, so they keep their place even next to a large personal skill collection.
@@ -158,7 +178,7 @@ The document, diagram, README-cover and figure skills ship pinned engines (`offi
158
178
 
159
179
  **4 commands**: `/lit <route> <task>`, `/lit-korean <file or text>`, `/lit-status`, `/lit-hud`.
160
180
 
161
- **10 hooks**: SessionStart (LitMuse context and routes; after a compaction it re-injects the saved handoff once, and it adds the answer style you chose with `litmuse style`), UserPromptSubmit (`lit` activation; a later `lit` while its route is active continues it, `lit <other route>` switches, a bare `lit` resumes a started plan, `lit new` or `lit restart` starts over), PreToolUse (during lit-plan: writes through write_file, edit_file, apply_patch or delete_file stay inside `plans/` and `.litmuse/`, shell commands are read-only, and only read-only LitMuse agents may be spawned; on every route: guards against clustered negations and clustered hedges that a write adds to Markdown or text prose), PostToolUse (the tool ledger, plus the whole-line comments an edit added for comment-checker and an advisory lit-humanizer check on written prose; on the motion route it also notes each render and each image `read_file` opened), PostToolUseFailure (ledger), Stop (a lit-plan turn ends after its plan file exists; a motion turn ends when the skill's done-check passes on the last render, or after two holds with a plain not-done notice; start-work keeps going while plan rows are open and litgoal while criteria are open, each at most 3 holds in a row without progress), PreCompact (writes `.litmuse/handoff/latest.md` before Muse compacts), SubagentStart (the return format for child agents), SubagentStop and SessionEnd (ledger lines). The hooks also keep a live record of the route, plan progress and running child agents, which `/lit-status` and `npx @litfamily/litmuse status --card` show, because Muse's `/hud` shows fixed fields only.
181
+ **10 hooks**: SessionStart (LitMuse context and routes; after a compaction it re-injects the saved handoff once, and it adds the answer style you chose with `litmuse style`), UserPromptSubmit (`lit` activation; a later `lit` while its route is active continues it, `lit <other route>` switches, a bare `lit` resumes a started plan, `lit new` or `lit restart` starts over), PreToolUse (during lit-plan: writes through write_file, edit_file, apply_patch or delete_file stay inside `plans/` and `.litmuse/`, shell commands are read-only, and only read-only LitMuse agents may be spawned; on every route: guards against clustered negations and clustered hedges that a write adds to Markdown or text prose), PostToolUse (the tool ledger, plus the whole-line comments an edit added for comment-checker and an advisory lit-humanizer check on written prose; on the motion route it also notes each render and each image `read_file` opened), PostToolUseFailure (ledger), Stop (a lit-plan turn ends after its plan file exists, and a one-word `go` in the same session within 30 minutes then starts that plan with start-work; a motion turn ends when the skill's done-check passes on the last render, or after two holds with a plain not-done notice; start-work keeps going while plan rows are open and litgoal while criteria are open, each at most 3 holds in a row without progress), PreCompact (writes `.litmuse/handoff/latest.md` before Muse compacts), SubagentStart (the return format for child agents), SubagentStop and SessionEnd (ledger lines). The hooks also keep a live record of the route, plan progress and running child agents, plus each session's liveness (PostToolUse says alive, Stop idle, SessionEnd ended), which `/lit-status` and `npx @litfamily/litmuse status --card` show, because Muse's `/hud` shows fixed fields only. The card lists other sessions of the project running first, then idle, keeps a finished start-work as done for a minute, names a herdr pane session `<skill> · <pane>`, and says `restart to <version>` when a newer LitMuse was installed after the session started.
162
182
 
163
183
  **11 agents**, spawned as `litmuse/<name>`: lit-planner, lit-executor, lit-verifier, qa-runner, quality-reviewer, librarian-researcher, and five Korean prose agents. Reviewers and the Korean agents get read and search tools only.
164
184
 
@@ -195,3 +215,5 @@ LitMuse is one of the seven LitFamily packages, and the seven armored robots on
195
215
  ## License
196
216
 
197
217
  MIT, © LitMuse contributors. LitMuse is an independent community project and is not affiliated with or endorsed by Meta.
218
+
219
+ The LitMuse and LitFamily names, logos and mascot art are covered by [TRADEMARK.md](./TRADEMARK.md).
package/README_ko-KR.md CHANGED
@@ -133,6 +133,26 @@ Muse의 `/hud`는 켜고 끄는 고정 항목 목록이라서 플러그인 글
133
133
 
134
134
  <p align="center"><img src="./docs/assets/handoff/latest.webp" width="960" alt="인계 스냅샷. 실행 계기와 세션, lit-plan 경로, 0개 체크와 2개 열린 행의 계획, 최근 기록 줄을 보여 줍니다." /></p>
135
135
 
136
+ ## 만들 수 있는 것
137
+
138
+ 품질 패리티 라운드에서 Mac에서 직접 렌더한 결과물 4종입니다. 파일을 열어 눈으로 읽고, 어색한 곳은 고쳐 다시 렌더했습니다.
139
+
140
+ <p align="center"><img src="./docs/assets/parity/lit-adhd-brief.png" width="960" alt="실제 터미널의 lit-adhd 브리프. 무지개 헤드라인, 목표와 작업 시간이 적힌 활성 세션 카드 하나, 도구, 완료된 커밋, 박스형 권장 다음 단계." /></p>
141
+
142
+ `lit-adhd`는 실행 중 세션을 브리핑합니다. 상태 뱃지가 달린 세션 카드와 종료 표, 박스형 권장 다음 단계 — 터미널 색상 그대로, 내부 필드 이름은 새지 않습니다.
143
+
144
+ <p align="center"><img src="./docs/assets/parity/lit-pptx-deck.png" width="960" alt="lit-pptx 상태 덱. KPI 행과 웨이브별 스위트 증가 막대 차트." /></p>
145
+
146
+ `lit-pptx`는 자료로 실제 덱을 엮습니다. 이 덱은 포팅 웨이브별 테스트 스위트 증가를 그립니다.
147
+
148
+ <p align="center"><img src="./docs/assets/parity/lit-schematic-pid.png" width="960" alt="lit-schematic P&ID. 탱크 TK-101, 상용·예비 도징 펌프, 릴리프 밸브 스필백, 계장 버블, 라인 번호, 심벌 범례, EX-PID-001 타이틀 블록을 갖춘 차아염소산나트륨 도징 스키드." /></p>
149
+
150
+ `lit-schematic`은 QA를 통과한 P&ID를 그립니다. 실제 심벌과 범례, 라인 번호, 타이틀 블록을 갖춘 도징 스키드이며, 모든 라벨이 읽힐 때까지 일곱 번 고쳐 그렸습니다.
151
+
152
+ <p align="center"><img src="./docs/assets/parity/lit-frontend-page.png" width="960" alt="frontend-ui-ux 갤러리 페이지. 어두운 원장과 형광 악센트, 렌더마다 플레이트 하나, 휴대전화·태블릿·데스크톱 너비에서 확인." /></p>
153
+
154
+ `frontend-ui-ux`는 이를 감싸는 페이지를 만듭니다. 렌더 한 종마다 플레이트 하나인 갤러리이며, 휴대전화·태블릿·데스크톱 너비에서 확인했습니다.
155
+
136
156
  ## 들어 있는 것
137
157
 
138
158
  **스킬 39개.** 필요할 때 불러오는 밀도 높은 Muse 스킬이며, 각 스킬에 필요한 참고 문서, 스크립트, 템플릿, 엔진이 그 스킬 폴더 안에 함께 들어 있습니다. 카탈로그에는 짧은 설명만 올라가며, 모두 합쳐 약 3.7 KB라서 개인 스킬이 많은 환경에서도 자리를 지킵니다.
@@ -158,7 +178,7 @@ Muse의 `/hud`는 켜고 끄는 고정 항목 목록이라서 플러그인 글
158
178
 
159
179
  **명령 4개**: `/lit <경로> <작업>`, `/lit-korean <파일 또는 글>`, `/lit-status`, `/lit-hud`.
160
180
 
161
- **훅 10개**: SessionStart(LitMuse 컨텍스트와 경로 표. 컴팩션 뒤에는 저장해 둔 인계 메모를 한 번 다시 넣고, `litmuse style`로 고른 답변 스타일도 더함), UserPromptSubmit(맨 앞의 `lit` 활성화. 같은 경로가 이미 켜져 있으면 이어서 진행, 다른 경로면 전환, 맨 `lit`은 시작한 계획을 재개, `lit new`·`lit restart`는 새로 시작), PreToolUse(lit-plan 동안 write_file·edit_file·apply_patch·delete_file 쓰기는 `plans/`와 `.litmuse/` 안으로 제한하고 셸 명령은 읽기 전용만 허용, 자식 에이전트는 읽기 전용 LitMuse 에이전트만 허용, 모든 경로에서 쓰기가 Markdown이나 텍스트 글에 새로 더하는 부정문 몰림과 얼버무림 몰림 검사), PostToolUse(도구 기록, 편집이 새로 더한 한 줄 주석을 comment-checker에 넘기고 쓴 글에는 lit-humanizer 참고 검사. 모션 경로에서는 렌더 실행과 `read_file`로 연 이미지도 기록), PostToolUseFailure(기록), Stop(lit-plan 턴은 계획 파일이 생긴 뒤 끝남. 모션 턴은 마지막 렌더가 스킬의 완료 검사를 통과하면 끝나고, 두 번 붙잡은 뒤에는 아직 끝나지 않았다고 분명히 말하게 함. start-work는 계획 행이, litgoal은 기준이 남아 있으면 이어 가되 진전 없이 연속 3번까지만 붙잡음), PreCompact(Muse가 컴팩션하기 전에 `.litmuse/handoff/latest.md`를 씀), SubagentStart(자식 에이전트의 보고 형식), SubagentStop·SessionEnd(기록 줄). 훅은 경로, 계획 진행, 실행 중인 자식 에이전트도 실시간 기록으로 남기며, Muse의 `/hud`는 고정 항목만 보여 주므로 이 기록은 `/lit-status`와 `npx @litfamily/litmuse status --card`로 봅니다.
181
+ **훅 10개**: SessionStart(LitMuse 컨텍스트와 경로 표. 컴팩션 뒤에는 저장해 둔 인계 메모를 한 번 다시 넣고, `litmuse style`로 고른 답변 스타일도 더함), UserPromptSubmit(맨 앞의 `lit` 활성화. 같은 경로가 이미 켜져 있으면 이어서 진행, 다른 경로면 전환, 맨 `lit`은 시작한 계획을 재개, `lit new`·`lit restart`는 새로 시작), PreToolUse(lit-plan 동안 write_file·edit_file·apply_patch·delete_file 쓰기는 `plans/`와 `.litmuse/` 안으로 제한하고 셸 명령은 읽기 전용만 허용, 자식 에이전트는 읽기 전용 LitMuse 에이전트만 허용, 모든 경로에서 쓰기가 Markdown이나 텍스트 글에 새로 더하는 부정문 몰림과 얼버무림 몰림 검사), PostToolUse(도구 기록, 편집이 새로 더한 한 줄 주석을 comment-checker에 넘기고 쓴 글에는 lit-humanizer 참고 검사. 모션 경로에서는 렌더 실행과 `read_file`로 연 이미지도 기록), PostToolUseFailure(기록), Stop(lit-plan 턴은 계획 파일이 생긴 뒤 끝나고, 같은 세션에서 30분 안에 `go` 한 단어를 입력하면 그 계획을 start-work로 시작. 모션 턴은 마지막 렌더가 스킬의 완료 검사를 통과하면 끝나고, 두 번 붙잡은 뒤에는 아직 끝나지 않았다고 분명히 말하게 함. start-work는 계획 행이, litgoal은 기준이 남아 있으면 이어 가되 진전 없이 연속 3번까지만 붙잡음), PreCompact(Muse가 컴팩션하기 전에 `.litmuse/handoff/latest.md`를 씀), SubagentStart(자식 에이전트의 보고 형식), SubagentStop·SessionEnd(기록 줄). 훅은 경로, 계획 진행, 실행 중인 자식 에이전트와 세션별 활동 상태(PostToolUse는 alive, Stop은 idle, SessionEnd는 ended)도 실시간 기록으로 남기며, Muse의 `/hud`는 고정 항목만 보여 주므로 이 기록은 `/lit-status`와 `npx @litfamily/litmuse status --card`로 봅니다. 카드는 같은 프로젝트의 다른 세션을 실행 중인 것부터 쉬는 것 순으로 보여 주고, 끝난 start-work는 1분 동안 done으로 두었다가 지우며, herdr 창 세션은 `<skill> · <pane>`으로 표시하고, 세션 시작 뒤 더 새 LitMuse가 설치되면 `restart to <버전>`을 띄웁니다.
162
182
 
163
183
  **에이전트 11개**, `litmuse/<이름>`으로 띄웁니다: lit-planner, lit-executor, lit-verifier, qa-runner, quality-reviewer, librarian-researcher, 그리고 한국어 글 에이전트 다섯. 리뷰어와 한국어 에이전트는 읽기와 검색 도구만 씁니다.
164
184
 
@@ -195,3 +215,5 @@ LitMuse는 LitFamily 패키지 일곱 개 가운데 하나이고, 표지의 로
195
215
  ## 라이선스
196
216
 
197
217
  MIT, © LitMuse contributors. LitMuse는 독립 커뮤니티 프로젝트이며 Meta와 제휴하거나 Meta의 보증을 받은 프로젝트가 아닙니다.
218
+
219
+ LitMuse와 LitFamily 이름, 로고, 마스코트 그림에는 [TRADEMARK.md](./TRADEMARK.md)가 적용됩니다.
package/TRADEMARK.md ADDED
@@ -0,0 +1,12 @@
1
+ # Trademark policy
2
+
3
+ The code in this repository is free to use under the MIT License (see `LICENSE`). The names **LitMuse**
4
+ and **LitFamily**, and the logos and mascot art, are not part of that license.
5
+
6
+ - You can fork, change and share the code under MIT.
7
+ - If you publish a changed version, give it a different name and logo, and do not suggest that the
8
+ LitMuse maintainers made or endorse it.
9
+ - You can say in plain text that your project is "based on LitMuse" or "a fork of LitMuse".
10
+ - Unchanged copies, such as mirrors and package caches, may keep the name.
11
+
12
+ Questions: open an issue at https://github.com/wjgoarxiv/litmuse/issues.
package/bin/litmuse.mjs CHANGED
@@ -13,6 +13,7 @@ import { checkUpdate } from '../lib/update-check.mjs';
13
13
  import { runtime } from '../lib/runtime.mjs';
14
14
  import { buildCard, renderCard } from '../lib/stage-card.mjs';
15
15
  import { styleCommand } from '../lib/style.mjs';
16
+ import { runRewindCli } from '../plugin/lib/rewind/collect.mjs';
16
17
 
17
18
  const HELP = `LitMuse ${packageVersion()}: LitFamily workflows for Meta's Muse Code
18
19
 
@@ -26,6 +27,7 @@ Commands
26
27
  hud Show the recommended /hud and /theme preset
27
28
  style eli5 | asd-ste100 | off | status: the answer style LitMuse adds to every session
28
29
  runtime status [name] | install <name|all>: the pinned engine runtimes, cached under the LitMuse data dir
30
+ rewind Cross-session brief records [--json] [--here] [--since 7d] [--max 12] [--session <id>]
29
31
  uninstall Remove the plugin from Muse and the staged bundle
30
32
  help This text
31
33
 
@@ -97,6 +99,8 @@ async function main() {
97
99
  return models({ env, flags, print });
98
100
  case 'runtime':
99
101
  return runtime({ env, flags, args, print });
102
+ case 'rewind':
103
+ return runRewindCli(flags.json ? [...args, '--json'] : args, process.cwd(), { env });
100
104
  case 'hud':
101
105
  print(readFileSync(join(PACKAGE_ROOT, 'docs', 'hud-preset.md'), 'utf8'));
102
106
  return 0;
@@ -1,6 +1,14 @@
1
1
  import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
- import { latestFile, readStage, stageFile, workspaceHash } from '../plugin/hooks/lib/stage.mjs';
3
+ import { latestFile, readLiveness, readStage, stageFile, workspaceHash } from '../plugin/hooks/lib/stage.mjs';
4
+ import { newerThan } from '../plugin/hooks/lib/common.mjs';
5
+ import { readManifest } from './bundle.mjs';
6
+ import { paths } from './paths.mjs';
7
+ import { gauge } from '../plugin/lib/rewind/gauge.mjs';
8
+ import { REVIEW_LANES, projectKey, resolveProjectStateRoot } from '../plugin/hooks/lib/workflow-stack.mjs';
9
+
10
+ // The hooks write `.litmuse` at the project state root, which may sit above the card's cwd.
11
+ const stacksDir = (cwd) => join(resolveProjectStateRoot(cwd), '.litmuse', 'workflow-stack');
4
12
 
5
13
  export function fmtDuration(ms) {
6
14
  const s = Math.max(0, Math.floor(ms / 1000));
@@ -28,9 +36,16 @@ export function planProgress(cwd, planFile) {
28
36
  const rows = [...readFileSync(join(cwd, file), 'utf8').matchAll(/^- \[([ xX])\] (\d+)\.\s*(.*)$/gm)];
29
37
  if (!rows.length) return null;
30
38
  const open = rows.find((r) => r[1] === ' ');
39
+ let mtimeMs = null;
40
+ try {
41
+ mtimeMs = statSync(join(cwd, file)).mtimeMs;
42
+ } catch {
43
+ // Readable just now but stat fails: freshness stays unknown.
44
+ }
31
45
  return {
32
46
  file, total: rows.length, done: rows.filter((r) => r[1] !== ' ').length,
33
47
  next: open ? { row: Number(open[2]), text: open[3].slice(0, 120) } : null,
48
+ mtimeMs,
34
49
  };
35
50
  } catch {
36
51
  return null;
@@ -54,6 +69,7 @@ export function activeGoal(cwd) {
54
69
  slug: best.g.slug ?? null, objective: String(best.g.objective ?? '').slice(0, 200),
55
70
  met: criteria.filter((c) => c.status === 'pass').length, total: criteria.length,
56
71
  open: criteria.filter((c) => c.status !== 'pass').map((c) => ({ id: c.id, text: String(c.text ?? '').slice(0, 120) })),
72
+ mtimeMs: best.m,
57
73
  };
58
74
  } catch {
59
75
  return null;
@@ -67,10 +83,168 @@ export function loadStage({ cwd, session, env = process.env }) {
67
83
  return entry && entry.session ? readStage(stageFile(cwd, entry.session, env)) : null;
68
84
  }
69
85
 
86
+ // One rainbow-tinted line at most: a static ANSI gradient, no animation, no blinking, no
87
+ // full-field luminance swing, so it stays flash-safe on any terminal. It marks the adhd turn.
88
+ const RAINBOW = [196, 208, 226, 46, 51, 21, 201];
89
+ export function rainbowLine(text) {
90
+ let color = 0;
91
+ let out = '';
92
+ for (const ch of String(text)) {
93
+ out += ch === ' ' ? ch : `\u001b[38;5;${RAINBOW[color++ % RAINBOW.length]}m${ch}`;
94
+ }
95
+ return `${out}\u001b[0m`;
96
+ }
97
+
98
+ // Fresh workflow stacks mean recent sessions worth briefing: any stack file touched in 24 h.
99
+ export function freshStacks(cwd, now = Date.now()) {
100
+ try {
101
+ const dir = stacksDir(cwd);
102
+ const day = 24 * 60 * 60 * 1000;
103
+ return readdirSync(dir).some((name) => name.endsWith('.json') && now - statSync(join(dir, name)).mtimeMs <= day);
104
+ } catch {
105
+ return false;
106
+ }
107
+ }
108
+
109
+ // Thread rows for the status card, read from the workflow stacks at render time. Every count
110
+ // resolves from exactly one source, in this order: the frame's recorded k/n, the named plan's
111
+ // rows, the active goal's criteria, otherwise the indeterminate pulse. Frames without a stage
112
+ // (a pure `record` spine) and frames older than 24 h are dropped; sibling sessions older than
113
+ // 15 minutes are skipped. Order is fixed (own stack, then other sessions as below), so a repaint
114
+ // with no change is byte-identical.
115
+ const THREAD_CAP = 6;
116
+ const THREAD_STALE_MS = 24 * 60 * 60 * 1000;
117
+ const SIBLING_FRESH_MS = 15 * 60 * 1000;
118
+
119
+ const readStackFile = (path) => {
120
+ try {
121
+ const text = readFileSync(path, 'utf8');
122
+ if (text.length > 64 * 1024) return null;
123
+ const parsed = JSON.parse(text);
124
+ return Array.isArray(parsed.frames) ? parsed : null;
125
+ } catch {
126
+ return null;
127
+ }
128
+ };
129
+
130
+ const frameGauge = (frame, cwd, goal) => {
131
+ if (Number.isInteger(frame.n) && Number.isInteger(frame.total)) return gauge(frame.n, frame.total);
132
+ if (frame.ref?.plan) {
133
+ const plan = planProgress(cwd, frame.ref.plan);
134
+ if (plan) return gauge(plan.done, plan.total);
135
+ }
136
+ if (goal) return gauge(goal.met, goal.total);
137
+ return gauge(null, null);
138
+ };
139
+
140
+ const frameRow = (frame, session, cwd, goal) => ({
141
+ session,
142
+ skill: typeof frame.skill === 'string' ? frame.skill : 'unknown',
143
+ stage: typeof frame.stage === 'string' ? frame.stage : null,
144
+ status: frame.status === 'paused' ? 'paused' : 'active',
145
+ gauge: frameGauge(frame, cwd, goal),
146
+ verdicts: frame.verdicts && typeof frame.verdicts === 'object' ? { ...frame.verdicts } : undefined,
147
+ });
148
+
149
+ // Other sessions of this project come from two sources: their fresh workflow stacks and their liveness
150
+ // records (alive, idle, ended, written by the hooks). Each reads `running`, `idle` or `done`; a session
151
+ // that ended, or whose start-work plan is fully ticked, reads `done` for a minute and then leaves the
152
+ // card. Running rows come first, then paused and idle ones, then done; ties keep the name order. A
153
+ // session started in a herdr pane is named `<skill> · <pane>` instead of by its id, and a session with
154
+ // no stack still gets a row (skill from its stage record, else `session`), even as the only row.
155
+ const DONE_SHOW_MS = 60 * 1000;
156
+ const OTHER_RANK = Object.freeze({ running: 0, paused: 1, idle: 1, done: 2 });
157
+ const fileKey = (session) => String(session).replace(/[^A-Za-z0-9_-]/gu, '_').slice(0, 128);
158
+
159
+ const finishedAt = (frame, live, cwd) => {
160
+ if (live?.state === 'ended') return Date.parse(live.at);
161
+ if (frame?.skill === 'start-work' && frame.ref?.plan) {
162
+ const plan = planProgress(cwd, frame.ref.plan);
163
+ if (plan && plan.total > 0 && plan.done >= plan.total && Number.isFinite(plan.mtimeMs)) return plan.mtimeMs;
164
+ }
165
+ return null;
166
+ };
167
+
168
+ function otherRows({ cwd, own, names, stacks, env, now, goal }) {
169
+ const others = new Map();
170
+ for (const name of names) {
171
+ const path = join(stacks, name);
172
+ let mtime = 0;
173
+ try {
174
+ mtime = statSync(path).mtimeMs;
175
+ } catch {
176
+ continue;
177
+ }
178
+ if (now - mtime > SIBLING_FRESH_MS) continue;
179
+ const top = readStackFile(path)?.frames.at(-1);
180
+ if (top?.stage) others.set(name.replace(/\.json$/, ''), { frame: top });
181
+ }
182
+ const root = projectKey(cwd);
183
+ for (const live of readLiveness(env)) {
184
+ if (typeof live.session !== 'string' || typeof live.cwd !== 'string' || live.session === own) continue;
185
+ if (projectKey(live.cwd) !== root) continue;
186
+ const entry = others.get(live.session);
187
+ if (!entry && live.state !== 'ended' && now - Date.parse(live.at) > SIBLING_FRESH_MS) continue;
188
+ others.set(live.session, { ...entry, live });
189
+ }
190
+ const rows = [];
191
+ for (const [id, { frame, live }] of [...others].sort(([a], [b]) => a.localeCompare(b))) {
192
+ const done = finishedAt(frame, live, cwd);
193
+ if (done !== null && !(now - done <= DONE_SHOW_MS)) continue;
194
+ const word = done !== null ? 'done' : live?.state === 'idle' ? 'idle' : 'running';
195
+ const route = frame ? null : readStage(stageFile(cwd, id, env))?.route;
196
+ const row = frame ? frameRow(frame, id, cwd, goal) : { session: id, skill: typeof route === 'string' && route ? route : 'session', stage: null, gauge: '' };
197
+ // The status word already says running; an unknown count adds nothing.
198
+ if (row.gauge === gauge(null, null)) row.gauge = '';
199
+ rows.push({
200
+ ...row,
201
+ status: frame?.status === 'paused' && word !== 'done' ? 'paused' : word,
202
+ pane: typeof live?.pane === 'string' ? live.pane : null,
203
+ sibling: true,
204
+ });
205
+ }
206
+ return rows.sort((a, b) => OTHER_RANK[a.status] - OTHER_RANK[b.status]);
207
+ }
208
+
209
+ export function threadRows({ cwd, session, env = process.env, now = Date.now() }) {
210
+ const goal = activeGoal(cwd);
211
+ const stacks = stacksDir(cwd);
212
+ let dir = [];
213
+ try {
214
+ dir = readdirSync(stacks);
215
+ } catch { /* no stacks yet: liveness may still name other sessions */ }
216
+ const own = session ? fileKey(session) : null;
217
+ const rows = [];
218
+ if (own) {
219
+ const stack = readStackFile(join(stacks, `${own}.json`));
220
+ for (const frame of stack?.frames ?? []) {
221
+ if (!frame.stage) continue;
222
+ if (frame.at && now - Date.parse(frame.at) > THREAD_STALE_MS) continue;
223
+ rows.push(frameRow(frame, session, cwd, goal));
224
+ }
225
+ }
226
+ const names = dir.filter((entry) => entry.endsWith('.json') && entry !== `${own}.json`);
227
+ rows.push(...otherRows({ cwd, own, names, stacks, env, now, goal }));
228
+ return { rows: rows.slice(0, THREAD_CAP), omitted: Math.max(0, rows.length - THREAD_CAP) };
229
+ }
230
+
231
+ // The restart chip: the installed bundle carries a newer version than the code this session loaded at
232
+ // SessionStart, so the hooks and skills in use are older until Muse restarts. Unknown either way: no chip.
233
+ function restartTo(rec, env) {
234
+ if (typeof rec?.loadedVersion !== 'string') return null;
235
+ try {
236
+ const installed = readManifest(paths(env).stage).version;
237
+ return typeof installed === 'string' && newerThan(installed, rec.loadedVersion) ? installed : null;
238
+ } catch {
239
+ return null;
240
+ }
241
+ }
242
+
70
243
  export function buildCard({ cwd, session, env = process.env, now = Date.now() }) {
71
244
  const rec = loadStage({ cwd, session, env });
72
245
  const goal = activeGoal(cwd);
73
- if (!rec) return { active: false, route: null, goal, plan: planProgress(cwd, null), lanes: [], now };
246
+ const threads = threadRows({ cwd, session: rec?.session ?? session ?? null, env, now });
247
+ if (!rec) return { active: false, route: null, goal, plan: planProgress(cwd, null), lanes: [], threads, idle: freshStacks(cwd, now), now, noColor: Boolean(env.NO_COLOR) };
74
248
  const lanes = (rec.lanes ?? []).map((l) => ({
75
249
  id: l.id, type: l.type, status: l.status,
76
250
  elapsedMs: (l.endedAt ?? now) - l.startedAt,
@@ -78,15 +252,81 @@ export function buildCard({ cwd, session, env = process.env, now = Date.now() })
78
252
  return {
79
253
  active: Boolean(rec.route), route: rec.route ?? null, keyword: rec.keyword ?? null, kind: rec.kind ?? null,
80
254
  session: rec.session ?? null, activeMs: rec.route && rec.activatedAt ? now - rec.activatedAt : null,
81
- plan: planProgress(cwd, rec.plan ?? null), lanes, goal, updated: rec.updated ?? null, now,
255
+ plan: planProgress(cwd, rec.plan ?? null), lanes, goal, threads, idle: !rec.route && freshStacks(cwd, now), updated: rec.updated ?? null, now, noColor: Boolean(env.NO_COLOR),
256
+ restartTo: restartTo(rec, env),
82
257
  };
83
258
  }
84
259
 
260
+ // Skill looks (BRIEF-mod-looks). Static TTY only: colour plus a label, never animation —
261
+ // the host has no card animation surface, and NO_COLOR strips even the static colour.
262
+ // The registry maps a card state to its headline paint; the lanes strip and the done burst
263
+ // are extra lines drawn from real reports only, never placeholders.
264
+ const paint = (code, text, color) => (color ? `\u001b[${code}m${text}\u001b[0m` : text);
265
+
266
+ // Waiting on the user: a paused thread, or a lane that reported failure. A turn where the
267
+ // model asked a question but left no tool state is not visible to the card.
268
+ const waitingOf = (card) => (card.threads?.rows ?? []).some((row) => row.status === 'paused')
269
+ || (card.lanes ?? []).some((lane) => lane.status === 'failed');
270
+
271
+ const headlineFor = (card, color) => {
272
+ if (!card.active) return 'LIT · no active route in this workspace';
273
+ const route = card.route ?? 'lit-loop';
274
+ if (waitingOf(card)) return paint('33;1', `LIT · ${route} · YOUR TURN`, color);
275
+ if (route === 'lit-adhd') return color ? rainbowLine('LIT · lit-adhd · brief on screen') : 'LIT · lit-adhd · brief on screen';
276
+ return `LIT · ${route}${card.activeMs !== null ? ` · active ${fmtDuration(card.activeMs)}` : ''}${card.kind && card.kind !== 'ignite' ? ` (${card.kind})` : ''}`;
277
+ };
278
+
279
+ // Canonical review-lane display names, in REVIEW_LANES order; the strip reads the same
280
+ // list, so the two cannot drift apart.
281
+ const REVIEW_LANE_LABELS = Object.freeze({ goal: 'scope', quality: 'package', security: 'security', qa: 'tests+evidence', context: 'surface' });
282
+ const VERDICT_DOT = Object.freeze({ pass: ['32;1', '●'], fail: ['31;1', '●'], running: ['33;1', '◐'], pending: ['33', '○'] });
283
+
284
+ const laneSegment = (id, verdict, color) => {
285
+ const label = REVIEW_LANE_LABELS[id] ?? id;
286
+ const known = verdict ? VERDICT_DOT[verdict] : null;
287
+ if (!known) return paint('2', `${label} ○`, color);
288
+ return paint(known[0], `${label} ${known[1]}`, color);
289
+ };
290
+
291
+ const lanesStrip = (card, color) => {
292
+ const frame = (card.threads?.rows ?? []).find((row) => row.skill === 'review-work' && row.verdicts);
293
+ const verdicts = frame?.verdicts ?? {};
294
+ return `review lanes: ${REVIEW_LANES.map(({ id }) => laneSegment(id, verdicts[id], color)).join(' · ')}`;
295
+ };
296
+
297
+ // Static TTY cannot play a one-shot animation and settle: a freshly completed plan or goal
298
+ // prints one celebratory line until the freshness window passes, then the card settles on
299
+ // its own. A published release has no signal the card can see.
300
+ const BURST_FRESH_MS = 15 * 60 * 1000;
301
+ const burstOf = (card, now) => {
302
+ const plan = card.plan;
303
+ if (plan && plan.total > 0 && plan.done >= plan.total && Number.isFinite(plan.mtimeMs) && now - plan.mtimeMs <= BURST_FRESH_MS) {
304
+ return `✨ done: ${plan.file} · ${plan.done}/${plan.total} rows ticked ✨`;
305
+ }
306
+ const goal = card.goal;
307
+ if (goal && goal.total > 0 && goal.met >= goal.total && Number.isFinite(goal.mtimeMs) && now - goal.mtimeMs <= BURST_FRESH_MS) {
308
+ return `✨ goal done: ${goal.objective} ✨`;
309
+ }
310
+ return null;
311
+ };
312
+
85
313
  export function renderCard(card) {
86
314
  const out = [];
87
- out.push(card.active
88
- ? `LIT · ${card.route}${card.activeMs !== null ? ` · active ${fmtDuration(card.activeMs)}` : ''}${card.kind && card.kind !== 'ignite' ? ` (${card.kind})` : ''}`
89
- : 'LIT · no active route in this workspace');
315
+ const color = !card.noColor;
316
+ out.push(headlineFor(card, color));
317
+ if (card.restartTo) out.push(`restart to ${card.restartTo}: LitMuse was updated after this session loaded it`);
318
+ if (!card.active && card.idle) out.push('idle — say `lit adhd` for the cross-session brief');
319
+ const threads = card.threads?.rows ?? [];
320
+ if (threads.length) {
321
+ out.push('threads:');
322
+ threads.forEach((thread, index) => {
323
+ const branch = index === threads.length - 1 && !card.threads.omitted ? '└─' : '├─';
324
+ const name = thread.pane ? `${thread.skill} · ${thread.pane}` : thread.skill;
325
+ const where = thread.sibling && !thread.pane ? ` (${thread.session})` : '';
326
+ out.push(`${branch} ${name}${thread.stage ? ` ${thread.stage}` : ''} ${thread.status}${thread.gauge ? ` ${thread.gauge}` : ''}${where}`);
327
+ });
328
+ if (card.threads.omitted) out.push(`+${card.threads.omitted} more`);
329
+ }
90
330
  if (card.plan) {
91
331
  out.push(`plan ${card.plan.done}/${card.plan.total} · ${card.plan.file}${card.plan.next ? ` · next ${card.plan.next.row}. ${card.plan.next.text}` : ' · all rows ticked'}`);
92
332
  }
@@ -94,9 +334,12 @@ export function renderCard(card) {
94
334
  const finished = card.lanes.filter((l) => l.status !== 'running');
95
335
  if (running.length) out.push(`lanes running: ${running.map((l) => `${l.type} ${fmtDuration(l.elapsedMs)}`).join(', ')}`);
96
336
  if (finished.length) out.push(`lanes finished: ${finished.map((l) => `${l.type} ${l.status} ${fmtDuration(l.elapsedMs)}`).join(', ')}`);
337
+ if (card.route === 'review-work') out.push(lanesStrip(card, color));
97
338
  if (card.goal) {
98
339
  out.push(`goal: ${card.goal.objective} (${card.goal.met}/${card.goal.total} criteria met)`);
99
340
  for (const c of card.goal.open.slice(0, 5)) out.push(` open ${c.id}: ${c.text}`);
100
341
  }
342
+ const burst = burstOf(card, card.now ?? Date.now());
343
+ if (burst) out.push(burst);
101
344
  return out.join('\n');
102
345
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@litfamily/litmuse",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Installer for LitMuse: skills, hooks and agents that help Meta's Muse Code plan, build, check and hand off work.",
5
5
  "keywords": [
6
6
  "muse",
@@ -47,7 +47,8 @@
47
47
  "README.md",
48
48
  "README_ko-KR.md",
49
49
  "CHANGELOG.md",
50
- "LICENSE"
50
+ "LICENSE",
51
+ "TRADEMARK.md"
51
52
  ],
52
53
  "publishConfig": {
53
54
  "access": "public"
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": 1,
3
3
  "name": "litmuse",
4
4
  "displayName": "LitMuse",
5
- "version": "0.1.1",
5
+ "version": "0.1.3",
6
6
  "description": "LitFamily workflows for Muse Code: bare lit activation, planning, evidence-bound execution, review, research, handoff and Korean prose care.",
7
7
  "compat": {
8
8
  "source": "native",
@@ -115,6 +115,16 @@
115
115
  "path": "skills/lit-handoff/SKILL.md",
116
116
  "enabledDefault": true
117
117
  },
118
+ {
119
+ "id": "lit-hijack",
120
+ "path": "skills/lit-hijack/SKILL.md",
121
+ "enabledDefault": true
122
+ },
123
+ {
124
+ "id": "lit-adhd",
125
+ "path": "skills/lit-adhd/SKILL.md",
126
+ "enabledDefault": true
127
+ },
118
128
  {
119
129
  "id": "lit-init",
120
130
  "path": "skills/lit-init/SKILL.md",
@@ -150,6 +160,11 @@
150
160
  "path": "skills/lit-diagram-drawer/SKILL.md",
151
161
  "enabledDefault": true
152
162
  },
163
+ {
164
+ "id": "lit-schematic",
165
+ "path": "skills/lit-schematic/SKILL.md",
166
+ "enabledDefault": true
167
+ },
153
168
  {
154
169
  "id": "lit-typographic-motion",
155
170
  "path": "skills/lit-typographic-motion/SKILL.md",
@@ -236,7 +251,7 @@
236
251
  "node",
237
252
  "hooks/session-start.mjs",
238
253
  "--digest",
239
- "b8961789243b3149"
254
+ "aa3c8c817b3b5263"
240
255
  ],
241
256
  "timeoutMs": 5000
242
257
  },
@@ -247,7 +262,7 @@
247
262
  "node",
248
263
  "hooks/user-prompt-submit.mjs",
249
264
  "--digest",
250
- "91a1d749ba4c3fd3"
265
+ "17cbcfe331b17df6"
251
266
  ],
252
267
  "timeoutMs": 5000,
253
268
  "statusMessage": "LitMuse route check"
@@ -259,7 +274,7 @@
259
274
  "node",
260
275
  "hooks/pre-tool-use.mjs",
261
276
  "--digest",
262
- "eedfd1f3ebe5cb38"
277
+ "a46607c7dd5c7dcd"
263
278
  ],
264
279
  "timeoutMs": 5000
265
280
  },
@@ -270,7 +285,7 @@
270
285
  "node",
271
286
  "hooks/post-tool-use.mjs",
272
287
  "--digest",
273
- "dac8628eaa6da79a"
288
+ "0c70692956033463"
274
289
  ],
275
290
  "timeoutMs": 5000
276
291
  },
@@ -281,7 +296,7 @@
281
296
  "node",
282
297
  "hooks/post-tool-use-failure.mjs",
283
298
  "--digest",
284
- "b905e80e38695ee0"
299
+ "6904dd5da8def1dd"
285
300
  ],
286
301
  "timeoutMs": 5000
287
302
  },
@@ -292,7 +307,7 @@
292
307
  "node",
293
308
  "hooks/stop.mjs",
294
309
  "--digest",
295
- "d7f72526de2e1053"
310
+ "ffd3ec1cb2687eb2"
296
311
  ],
297
312
  "timeoutMs": 5000
298
313
  },
@@ -303,7 +318,7 @@
303
318
  "node",
304
319
  "hooks/subagent-start.mjs",
305
320
  "--digest",
306
- "20285c4542661b42"
321
+ "b97c259487df63c1"
307
322
  ],
308
323
  "timeoutMs": 5000
309
324
  },
@@ -314,7 +329,7 @@
314
329
  "node",
315
330
  "hooks/subagent-stop.mjs",
316
331
  "--digest",
317
- "35624765c5646ff0"
332
+ "6d4dbf1e969d4d7b"
318
333
  ],
319
334
  "timeoutMs": 5000
320
335
  },
@@ -325,7 +340,7 @@
325
340
  "node",
326
341
  "hooks/session-end.mjs",
327
342
  "--digest",
328
- "6e0bc285570a4cc2"
343
+ "b0f6069317813e37"
329
344
  ],
330
345
  "timeoutMs": 5000
331
346
  },
@@ -336,7 +351,7 @@
336
351
  "node",
337
352
  "hooks/pre-compact.mjs",
338
353
  "--digest",
339
- "9c089c69dc07f94a"
354
+ "c844b43a044a2533"
340
355
  ],
341
356
  "timeoutMs": 5000
342
357
  }
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Read-only LIT card for this workspace: route, time active, plan n/m, running lanes, goal, last handoff"
2
+ description: "Read-only LIT card for this workspace: route, plan n/m, lanes, threads, goal, last handoff"
3
3
  argument-hint: "[slug]"
4
4
  ---
5
5
  Print the LitMuse status card for this workspace. Scope: $ARGUMENTS (empty means everything). Write nothing.
@@ -9,6 +9,8 @@ Print the LitMuse status card for this workspace. Scope: $ARGUMENTS (empty means
9
9
  - Route and time active: the newest record from `latest.json` (route, activatedAt, kind), or else the `route` on the last line of the newest `.litmuse/ledger/*.jsonl`.
10
10
  - Plan: the plan named in the record, or else the newest `plans/*.md`. Count `- [x] N.` against all `- [ ] N.` and `- [x] N.` rows, and name the first open row.
11
11
  - Lanes: the record's `lanes` entries with `status` running, done or failed, and their elapsed time (`endedAt` or now, minus `startedAt`).
12
+ - Threads: `.litmuse/workflow-stack/<session>.json` frames (paused spines above running sides) at the project state root (a linked worktree keeps its own), then other sessions of this project from their fresh stack tops and their liveness records (`stage/liveness/<session>.json`: `alive`, `idle`, `ended`). Other sessions read `running`, `idle` or `done`, running first; a session that ended or whose start-work plan is fully ticked reads `done` for one minute, then leaves; a session in a herdr pane is named `<skill> · <pane>`; a lone other session still gets its row. A real gauge when the count is known, the `… N steps` fact line otherwise — never a placeholder. Six rows at most, then `+N more`; an idle card offers `lit adhd` instead.
13
+ - Restart chip: when the installed bundle (`$XDG_DATA_HOME/litmuse/bundle/.muse-plugin/plugin.json`) is newer than the `loadedVersion` SessionStart recorded, add `restart to <version>`; when either is unknown, add nothing.
12
14
  - Goal: each `.litmuse/goals/*.json` whose status is `active`, with its objective and the criteria that are not `pass`.
13
15
  3. Add the first lines of `.litmuse/handoff/latest.md` if present, and the count of tool events and failures in the newest ledger.
14
16