@litfamily/litopencode 1.0.31 → 1.0.33

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 (282) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README-Ko-KR.md +6 -6
  3. package/README.md +6 -6
  4. package/TRADEMARK.md +12 -0
  5. package/dist/activation-primary-prompts.js +5 -1
  6. package/dist/activation-probe.js +1 -0
  7. package/dist/activation-prompt-utils.d.ts +1 -1
  8. package/dist/activation-reentry.d.ts +20 -0
  9. package/dist/activation-reentry.js +110 -1
  10. package/dist/activation-routing.d.ts +2 -1
  11. package/dist/activation-routing.js +100 -11
  12. package/dist/activation-workflow-prompts.d.ts +4 -0
  13. package/dist/activation-workflow-prompts.js +30 -0
  14. package/dist/activation.d.ts +1 -1
  15. package/dist/activation.js +44 -5
  16. package/dist/adhd-next.d.ts +51 -0
  17. package/dist/adhd-next.js +150 -0
  18. package/dist/agents/defaults.js +1 -1
  19. package/dist/cli/managed-skill-assets.d.ts +1 -1
  20. package/dist/cli/managed-skill-assets.js +7 -1
  21. package/dist/cli/native-skill-integrity.js +1 -1
  22. package/dist/cli.js +7 -1
  23. package/dist/commands.d.ts +28 -1
  24. package/dist/commands.js +58 -5
  25. package/dist/durable-plan.d.ts +5 -1
  26. package/dist/durable-plan.js +14 -2
  27. package/dist/features.d.ts +80 -1
  28. package/dist/features.js +105 -1
  29. package/dist/hooks.js +3 -0
  30. package/dist/ledger.js +12 -1
  31. package/dist/plan-scope-roots.d.ts +23 -0
  32. package/dist/plan-scope-roots.js +116 -0
  33. package/dist/restart-notice.d.ts +7 -0
  34. package/dist/restart-notice.js +40 -0
  35. package/dist/secret-shapes.js +5 -5
  36. package/dist/server.js +4 -0
  37. package/dist/session-liveness.d.ts +20 -0
  38. package/dist/session-liveness.js +99 -0
  39. package/dist/skills.d.ts +22 -1
  40. package/dist/skills.js +36 -0
  41. package/dist/start-work-typed.d.ts +34 -0
  42. package/dist/start-work-typed.js +167 -0
  43. package/dist/state.d.ts +3 -0
  44. package/dist/state.js +3 -0
  45. package/dist/tools.js +22 -2
  46. package/dist/tui/mission-band.d.ts +22 -1
  47. package/dist/tui/mission-band.js +75 -16
  48. package/dist/tui/mission-looks.d.ts +38 -0
  49. package/dist/tui/mission-looks.js +73 -0
  50. package/dist/tui/mission-model.d.ts +2 -0
  51. package/dist/tui/mission-model.js +3 -1
  52. package/dist/tui/mission-rainbow.d.ts +33 -0
  53. package/dist/tui/mission-rainbow.js +90 -0
  54. package/dist/tui/mission-source.d.ts +49 -0
  55. package/dist/tui/mission-source.js +217 -2
  56. package/dist/tui/mission-text.d.ts +2 -0
  57. package/dist/tui/mission-text.js +9 -1
  58. package/dist/tui/mission-threads.d.ts +58 -0
  59. package/dist/tui/mission-threads.js +128 -0
  60. package/dist/tui.js +112 -7
  61. package/dist/uiux-visual-catalog.js +8 -1
  62. package/dist/v2/events.js +3 -0
  63. package/dist/v2/session-hooks.js +38 -5
  64. package/dist/workflow-stack.d.ts +53 -0
  65. package/dist/workflow-stack.js +196 -0
  66. package/docs/assets/readme/badge-version.svg +1 -1
  67. package/docs/assets/skills/lit-schematic.webp +0 -0
  68. package/docs/reference-Ko-KR.md +48 -3
  69. package/docs/reference.md +54 -3
  70. package/package.json +1 -1
  71. package/skills/frontend-ui-ux/SKILL.md +3 -2
  72. package/skills/frontend-ui-ux/kit/components.css +414 -0
  73. package/skills/frontend-ui-ux/kit/fonts.json +22 -0
  74. package/skills/frontend-ui-ux/kit/layouts/landing.html +164 -0
  75. package/skills/frontend-ui-ux/kit/layouts/settings.html +114 -0
  76. package/skills/frontend-ui-ux/kit/layouts/workspace.html +115 -0
  77. package/skills/frontend-ui-ux/kit/styles/computational-brutalism.json +227 -0
  78. package/skills/frontend-ui-ux/kit/styles/field-notes.json +205 -0
  79. package/skills/frontend-ui-ux/kit/styles/graphite.json +200 -0
  80. package/skills/frontend-ui-ux/kit/styles/meadow.json +199 -0
  81. package/skills/frontend-ui-ux/kit/styles/neo-brutalism.json +222 -0
  82. package/skills/frontend-ui-ux/kit/ui.js +226 -0
  83. package/skills/frontend-ui-ux/references/brand-and-imagery.md +2 -2
  84. package/skills/frontend-ui-ux/references/complete-contract.md +2 -1
  85. package/skills/frontend-ui-ux/references/craft-floor.md +6 -2
  86. package/skills/frontend-ui-ux/references/default-editorial-pixel.json +3 -0
  87. package/skills/frontend-ui-ux/references/house-styles.md +236 -0
  88. package/skills/frontend-ui-ux/references/motion-guide.md +2 -2
  89. package/skills/frontend-ui-ux/references/production.md +3 -1
  90. package/skills/frontend-ui-ux/references/slop-register.md +4 -4
  91. package/skills/frontend-ui-ux/scripts/design-lock.mjs +400 -0
  92. package/skills/frontend-ui-ux/scripts/pixel-art.mjs +60 -0
  93. package/skills/frontend-ui-ux/scripts/probe-lock.mjs +235 -0
  94. package/skills/frontend-ui-ux/scripts/probe-page.mjs +34 -12
  95. package/skills/frontend-ui-ux/scripts/probe-static.mjs +16 -3
  96. package/skills/frontend-ui-ux/scripts/probe-thresholds.json +8 -2
  97. package/skills/frontend-ui-ux/scripts/probe.mjs +35 -7
  98. package/skills/lit-adhd/SKILL.md +209 -0
  99. package/skills/lit-adhd/references/brief-format.md +46 -0
  100. package/skills/lit-adhd/references/card-examples.md +103 -0
  101. package/skills/lit-adhd/references/status-taxonomy.md +34 -0
  102. package/skills/lit-adhd/scripts/rewind.mjs +933 -0
  103. package/skills/lit-diagram-drawer/SKILL.md +4 -3
  104. package/skills/lit-diagram-drawer/references/style-guide.md +20 -11
  105. package/skills/lit-diagram-drawer/references/type-architecture.md +3 -3
  106. package/skills/lit-diagram-drawer/references/type-dependency.md +1 -1
  107. package/skills/lit-diagram-drawer/references/type-tree.md +3 -3
  108. package/skills/lit-diagram-drawer/references/type-wardley.md +1 -1
  109. package/skills/lit-diagram-drawer/references/verifier-guide.md +1 -0
  110. package/skills/lit-diagram-drawer/scripts/craft-thresholds.json +1 -2
  111. package/skills/lit-diagram-drawer/scripts/visual-quality.mjs +1 -2
  112. package/skills/lit-docx/SKILL.md +2 -1
  113. package/skills/lit-handoff/SKILL.md +2 -0
  114. package/skills/lit-hijack/SKILL.md +422 -0
  115. package/skills/lit-hijack/references/capture-and-provenance.md +87 -0
  116. package/skills/lit-hijack/references/clean-room-build.md +111 -0
  117. package/skills/lit-hijack/references/distil-and-licence.md +100 -0
  118. package/skills/lit-hijack/references/gap-and-port-design.md +126 -0
  119. package/skills/lit-hijack/references/parity-and-report.md +110 -0
  120. package/skills/lit-hijack/scripts/hijack.mjs +993 -0
  121. package/skills/lit-plan/SKILL.md +8 -0
  122. package/skills/lit-pptx/SKILL.md +27 -11
  123. package/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Bold.ttf +0 -0
  124. package/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Regular.ttf +0 -0
  125. package/skills/lit-pptx/fonts/jetbrains-mono/OFL.txt +93 -0
  126. package/skills/lit-pptx/fonts/jetbrains-mono/SOURCE.md +17 -0
  127. package/skills/lit-pptx/references/density-and-fill.md +9 -3
  128. package/skills/lit-pptx/references/direction-step.md +21 -6
  129. package/skills/lit-pptx/references/examples/04-lecture-chalk-ko.md +3 -6
  130. package/skills/lit-pptx/references/examples/05-research-talk-paper-en.md +1 -5
  131. package/skills/lit-pptx/references/examples/08-reliability-keynote-night-en.md +0 -4
  132. package/skills/lit-pptx/references/examples/09-status-update-ledger-en.md +2 -2
  133. package/skills/lit-pptx/references/examples/11-forecast-review-night-ko.md +4 -7
  134. package/skills/lit-pptx/references/examples/13-engineering-review-computational-brutalism-ko.md +173 -0
  135. package/skills/lit-pptx/references/examples/14-launch-pitch-neo-brutalism-ko.md +154 -0
  136. package/skills/lit-pptx/references/examples/15-design-lecture-bauhaus-ko.md +139 -0
  137. package/skills/lit-pptx/references/examples/16-community-programme-riso-ko.md +158 -0
  138. package/skills/lit-pptx/references/examples/17-public-data-briefing-newsroom-ko.md +179 -0
  139. package/skills/lit-pptx/references/layout-families.md +65 -47
  140. package/skills/lit-pptx/references/title-treatments.md +83 -134
  141. package/skills/lit-pptx/references/tonalities/atlas.md +3 -3
  142. package/skills/lit-pptx/references/tonalities/bauhaus.md +140 -0
  143. package/skills/lit-pptx/references/tonalities/chalk.md +7 -6
  144. package/skills/lit-pptx/references/tonalities/computational-brutalism.md +150 -0
  145. package/skills/lit-pptx/references/tonalities/gazette.md +1 -1
  146. package/skills/lit-pptx/references/tonalities/ledger.md +1 -1
  147. package/skills/lit-pptx/references/tonalities/neo-brutalism.md +161 -0
  148. package/skills/lit-pptx/references/tonalities/newsroom.md +144 -0
  149. package/skills/lit-pptx/references/tonalities/night.md +1 -1
  150. package/skills/lit-pptx/references/tonalities/paper.md +2 -2
  151. package/skills/lit-pptx/references/tonalities/riso.md +137 -0
  152. package/skills/lit-pptx/references/tonalities/signal.md +3 -3
  153. package/skills/lit-pptx/references/tonalities/studio.md +7 -6
  154. package/skills/lit-pptx/run.mjs +2 -1
  155. package/skills/lit-pptx/scripts/compile-deck.js +1 -1
  156. package/skills/lit-pptx/scripts/craft-thresholds.json +4 -8
  157. package/skills/lit-pptx/scripts/craft_extras.py +56 -3
  158. package/skills/lit-pptx/scripts/deck_output.py +75 -90
  159. package/skills/lit-pptx/scripts/embed_fonts.py +13 -1
  160. package/skills/lit-pptx/scripts/layout_inventory.py +12 -5
  161. package/skills/lit-pptx/scripts/lib/grid-resolver.js +101 -110
  162. package/skills/lit-pptx/scripts/lib/layout-resolver.js +9 -15
  163. package/skills/lit-pptx/scripts/lib/render-pack.js +373 -566
  164. package/skills/lit-pptx/scripts/lib/slide-grid.js +104 -0
  165. package/skills/lit-pptx/scripts/lib/template-registry.js +57 -6
  166. package/skills/lit-pptx/scripts/qa_deck.py +10 -11
  167. package/skills/lit-pptx/scripts/render_pages.py +118 -0
  168. package/skills/lit-pptx/templates/tonalities/atlas/pack.yaml +1 -1
  169. package/skills/lit-pptx/templates/tonalities/bauhaus/pack.yaml +98 -0
  170. package/skills/lit-pptx/templates/tonalities/chalk/pack.yaml +1 -1
  171. package/skills/lit-pptx/templates/tonalities/computational-brutalism/pack.yaml +99 -0
  172. package/skills/lit-pptx/templates/tonalities/gazette/pack.yaml +1 -1
  173. package/skills/lit-pptx/templates/tonalities/ledger/pack.yaml +1 -1
  174. package/skills/lit-pptx/templates/tonalities/neo-brutalism/pack.yaml +107 -0
  175. package/skills/lit-pptx/templates/tonalities/newsroom/pack.yaml +99 -0
  176. package/skills/lit-pptx/templates/tonalities/night/pack.yaml +1 -1
  177. package/skills/lit-pptx/templates/tonalities/paper/pack.yaml +1 -1
  178. package/skills/lit-pptx/templates/tonalities/riso/pack.yaml +99 -0
  179. package/skills/lit-pptx/templates/tonalities/signal/pack.yaml +2 -2
  180. package/skills/lit-pptx/templates/tonalities/studio/pack.yaml +1 -1
  181. package/skills/lit-recap/SKILL.md +4 -0
  182. package/skills/lit-schematic/SKILL.md +118 -0
  183. package/skills/lit-schematic/examples/iso-heat-exchanger/build.mjs +38 -0
  184. package/skills/lit-schematic/examples/iso-heat-exchanger/scene.mjs +133 -0
  185. package/skills/lit-schematic/examples/journal-adsorption-rig/build.mjs +87 -0
  186. package/skills/lit-schematic/examples/pid-dosing-skid/build.mjs +85 -0
  187. package/skills/lit-schematic/references/cutaway-outputs.md +70 -0
  188. package/skills/lit-schematic/references/isometric-craft.md +101 -0
  189. package/skills/lit-schematic/references/journal-figures.md +72 -0
  190. package/skills/lit-schematic/references/kit-api.md +134 -0
  191. package/skills/lit-schematic/references/pfd-and-layout.md +53 -0
  192. package/skills/lit-schematic/references/pid-drafting.md +103 -0
  193. package/skills/lit-schematic/references/pid-symbols.md +163 -0
  194. package/skills/lit-schematic/references/verification.md +100 -0
  195. package/skills/lit-schematic/scripts/doctor.mjs +57 -0
  196. package/skills/lit-schematic/scripts/lib/figure.mjs +81 -0
  197. package/skills/lit-schematic/scripts/lib/fonts.mjs +25 -0
  198. package/skills/lit-schematic/scripts/lib/geom.mjs +113 -0
  199. package/skills/lit-schematic/scripts/lib/interactive.mjs +292 -0
  200. package/skills/lit-schematic/scripts/lib/isa.mjs +115 -0
  201. package/skills/lit-schematic/scripts/lib/iso.mjs +719 -0
  202. package/skills/lit-schematic/scripts/lib/legend-sheet.mjs +162 -0
  203. package/skills/lit-schematic/scripts/lib/pid.mjs +937 -0
  204. package/skills/lit-schematic/scripts/lib/png.mjs +132 -0
  205. package/skills/lit-schematic/scripts/lib/qa-core.mjs +658 -0
  206. package/skills/lit-schematic/scripts/lib/route.mjs +218 -0
  207. package/skills/lit-schematic/scripts/lib/sheet.mjs +890 -0
  208. package/skills/lit-schematic/scripts/lib/svg.mjs +82 -0
  209. package/skills/lit-schematic/scripts/lib/theme.mjs +115 -0
  210. package/skills/lit-schematic/scripts/motion.mjs +129 -0
  211. package/skills/lit-schematic/scripts/qa.mjs +92 -0
  212. package/skills/lit-schematic/scripts/render.mjs +233 -0
  213. package/skills/lit-schematic/scripts/scaffold.mjs +60 -0
  214. package/skills/lit-scientific-visualization/SKILL.md +27 -4
  215. package/skills/lit-typographic-motion/SKILL.md +19 -17
  216. package/skills/lit-typographic-motion/THIRD_PARTY_NOTICES +9 -0
  217. package/skills/lit-typographic-motion/engine/accents.mjs +6 -0
  218. package/skills/lit-typographic-motion/engine/assets.mjs +282 -0
  219. package/skills/lit-typographic-motion/engine/blender/runner.py +228 -0
  220. package/skills/lit-typographic-motion/engine/blender.mjs +126 -0
  221. package/skills/lit-typographic-motion/engine/board.mjs +138 -0
  222. package/skills/lit-typographic-motion/engine/cover/assets.mjs +11 -8
  223. package/skills/lit-typographic-motion/engine/cover/capture.mjs +6 -6
  224. package/skills/lit-typographic-motion/engine/cover/render.mjs +20 -7
  225. package/skills/lit-typographic-motion/engine/cover/treatment.mjs +30 -3
  226. package/skills/lit-typographic-motion/engine/fill.mjs +54 -0
  227. package/skills/lit-typographic-motion/engine/gallery.mjs +118 -0
  228. package/skills/lit-typographic-motion/engine/house.mjs +42 -0
  229. package/skills/lit-typographic-motion/engine/look.mjs +65 -8
  230. package/skills/lit-typographic-motion/engine/loudness.mjs +101 -0
  231. package/skills/lit-typographic-motion/engine/scaffold.mjs +219 -0
  232. package/skills/lit-typographic-motion/engine/score.mjs +594 -0
  233. package/skills/lit-typographic-motion/engine/sound.mjs +9 -57
  234. package/skills/lit-typographic-motion/engine/stage/capture.mjs +23 -9
  235. package/skills/lit-typographic-motion/engine/stage/clock.js +8 -2
  236. package/skills/lit-typographic-motion/engine/stage/cover-init.js +12 -1
  237. package/skills/lit-typographic-motion/engine/stage/frame-worker.mjs +15 -7
  238. package/skills/lit-typographic-motion/engine/stage/gate.mjs +48 -4
  239. package/skills/lit-typographic-motion/engine/stage/qa-page.js +16 -5
  240. package/skills/lit-typographic-motion/engine/stage/qa.mjs +148 -7
  241. package/skills/lit-typographic-motion/engine/stage/render.mjs +69 -7
  242. package/skills/lit-typographic-motion/engine/stage/scan.mjs +20 -1
  243. package/skills/lit-typographic-motion/engine/stage/stage-kit.js +85 -4
  244. package/skills/lit-typographic-motion/engine/stills.mjs +1 -1
  245. package/skills/lit-typographic-motion/engine/styles.mjs +221 -0
  246. package/skills/lit-typographic-motion/engine/text.mjs +1 -1
  247. package/skills/lit-typographic-motion/engine/treatment.mjs +190 -6
  248. package/skills/lit-typographic-motion/engine/vendor/three/LICENSE +21 -0
  249. package/skills/lit-typographic-motion/engine/vendor/three/addons/environments/RoomEnvironment.js +144 -0
  250. package/skills/lit-typographic-motion/engine/vendor/three/addons/geometries/RoundedBoxGeometry.js +155 -0
  251. package/skills/lit-typographic-motion/engine/vendor/three/three.module.js +54571 -0
  252. package/skills/lit-typographic-motion/gate.mjs +18 -2
  253. package/skills/lit-typographic-motion/probe.mjs +13 -1
  254. package/skills/lit-typographic-motion/recipes/hero-3d/expected.json +64 -0
  255. package/skills/lit-typographic-motion/recipes/hero-3d/index.html +132 -0
  256. package/skills/lit-typographic-motion/recipes/orbit-loop/expected.json +2 -0
  257. package/skills/lit-typographic-motion/recipes/painted-light/expected.json +2 -0
  258. package/skills/lit-typographic-motion/recipes/weight-tide/expected.json +2 -0
  259. package/skills/lit-typographic-motion/references/cover.md +56 -13
  260. package/skills/lit-typographic-motion/references/craft-loop.md +20 -7
  261. package/skills/lit-typographic-motion/references/depth.md +112 -0
  262. package/skills/lit-typographic-motion/references/runtime.md +21 -6
  263. package/skills/lit-typographic-motion/references/sound.md +76 -0
  264. package/skills/lit-typographic-motion/references/stage.md +50 -7
  265. package/skills/lit-typographic-motion/references/studio.md +162 -0
  266. package/skills/lit-typographic-motion/references/style-bibles.md +18 -0
  267. package/skills/lit-typographic-motion/references/treatment.md +108 -9
  268. package/skills/lit-typographic-motion/render.mjs +60 -3
  269. package/skills/lit-typographic-motion/styles/paper.json +185 -0
  270. package/skills/lit-typographic-motion/styles/swiss-signal.json +188 -0
  271. package/skills/lit-typographic-motion/styles/terminalcore.json +182 -0
  272. package/skills/lit-typographic-motion/styles/tidal.json +187 -0
  273. package/skills/litresearch/SKILL.md +2 -0
  274. package/skills/managed-skill-manifest.json +517 -88
  275. package/skills/readme-studio/SKILL.md +1 -1
  276. package/skills/review-work/SKILL.md +2 -0
  277. package/skills/start-work/SKILL.md +8 -0
  278. package/skills/workflow-loop/SKILL.md +4 -0
  279. package/tools/check-pack-payload.mjs +5 -2
  280. package/tools/payload-substance-parity.json +4 -3
  281. package/tools/qa-cover-recipes.mjs +4 -3
  282. package/tools/version-manifests.json +2 -2
@@ -1,3 +1,7 @@
1
+ /** The plan reaches a folder outside the project that no `Scope roots:` line names; the message says what to add. */
2
+ export declare class PlanScopeError extends Error {
3
+ constructor(message: string);
4
+ }
1
5
  export type ApprovedPlanRequest = {
2
6
  readonly schemaVersion: 1;
3
7
  readonly slug: string;
@@ -20,4 +24,4 @@ export declare function parsePlanSaveArgument(argumentsText: string): ApprovedPl
20
24
  export declare function persistApprovedPlan(projectRoot: string, request: ApprovedPlanRequest): Promise<DurablePlan>;
21
25
  export declare function resolveLatestDurablePlan(projectRoot: string): Promise<DurablePlan | undefined>;
22
26
  export declare function formatResolvedPlanNotice(plan: DurablePlan): string;
23
- export declare function formatSavedPlanNotice(plan: DurablePlan, replayed: boolean): string;
27
+ export declare function formatSavedPlanNotice(plan: DurablePlan, replayed: boolean, goArmed?: boolean): string;
@@ -1,6 +1,14 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
  import fs from "node:fs/promises";
3
3
  import path from "node:path";
4
+ import { describeUncoveredScopePaths, uncoveredScopePaths } from "./plan-scope-roots.js";
5
+ /** The plan reaches a folder outside the project that no `Scope roots:` line names; the message says what to add. */
6
+ export class PlanScopeError extends Error {
7
+ constructor(message) {
8
+ super(message);
9
+ this.name = "PlanScopeError";
10
+ }
11
+ }
4
12
  const PLAN_DIRECTORY = path.join(".litopencode", "plans");
5
13
  const MAX_PLAN_BYTES = 256 * 1024;
6
14
  const MAX_ARGUMENT_BYTES = 512 * 1024;
@@ -261,6 +269,9 @@ export async function persistApprovedPlan(projectRoot, request) {
261
269
  const validationError = validateRequest(request);
262
270
  if (validationError !== "")
263
271
  throw new Error(validationError);
272
+ const uncovered = uncoveredScopePaths(request.markdown, projectRoot);
273
+ if (uncovered.length > 0)
274
+ throw new PlanScopeError(describeUncoveredScopePaths(uncovered));
264
275
  const body = normalizeMarkdown(request.markdown);
265
276
  const directory = path.join(projectRoot, PLAN_DIRECTORY);
266
277
  const name = `${request.slug}.md`;
@@ -343,7 +354,8 @@ export async function resolveLatestDurablePlan(projectRoot) {
343
354
  export function formatResolvedPlanNotice(plan) {
344
355
  return `Durable plan: ${plan.relativePath}. Discovery only. This does not grant start-work authority.\n\n<durable-plan>\n${plan.text}</durable-plan>`;
345
356
  }
346
- export function formatSavedPlanNotice(plan, replayed) {
357
+ export function formatSavedPlanNotice(plan, replayed, goArmed = false) {
347
358
  const verb = replayed ? "Durable plan already persisted" : "Saved durable plan";
348
- return `${verb}: ${plan.relativePath}. Discovery only. This does not grant start-work authority.`;
359
+ const go = goArmed ? " To start it, type `go` within 30 minutes in this session." : "";
360
+ return `${verb}: ${plan.relativePath}. Discovery only. This does not grant start-work authority.${go}`;
349
361
  }
@@ -1,5 +1,5 @@
1
1
  export type LitOpenCodeBindingKind = "agent" | "cli" | "command" | "config" | "hook" | "tool";
2
- export type LitOpenCodeFeatureId = "planning-start-work-loop" | "lit-litwork-activation" | "start-work" | "review-work" | "litresearch" | "durable-ledger" | "bounded-authority-lifecycle" | "agent-roster" | "lit-plan" | "reference-benchmark-claims" | "native-goal-verdict" | "doctor-install" | "search-workflow-ideas" | "lit-fetch" | "guardrails" | "lit-init" | "lit-crucible" | "lit-brainstorm" | "refactor" | "lit-burnoff" | "lit-burnoff-file" | "comment-checker" | "lit-code" | "debugging" | "lit-commit" | "lsp" | "lsp-setup" | "rules" | "deep-interview" | "structural-search" | "browser-drive" | "lit-humanizer" | "lit-recap" | "lit-comprehend" | "lit-handoff" | "lit-scientific-visualization" | "lit-diagram-drawer" | "lit-pptx" | "lit-typographic-motion" | "lit-docx" | "readme-studio" | "frontend-ui-ux" | "visual-qa" | "autoresearch" | "autoconference" | "wikify";
2
+ export type LitOpenCodeFeatureId = "planning-start-work-loop" | "lit-litwork-activation" | "start-work" | "review-work" | "litresearch" | "durable-ledger" | "bounded-authority-lifecycle" | "agent-roster" | "lit-plan" | "reference-benchmark-claims" | "native-goal-verdict" | "doctor-install" | "search-workflow-ideas" | "lit-fetch" | "guardrails" | "lit-init" | "lit-crucible" | "lit-brainstorm" | "lit-hijack" | "lit-adhd" | "workflow-stack" | "refactor" | "lit-burnoff" | "lit-burnoff-file" | "comment-checker" | "lit-code" | "debugging" | "lit-commit" | "lsp" | "lsp-setup" | "rules" | "deep-interview" | "structural-search" | "browser-drive" | "lit-humanizer" | "lit-recap" | "lit-comprehend" | "lit-handoff" | "lit-scientific-visualization" | "lit-diagram-drawer" | "lit-schematic" | "lit-pptx" | "lit-typographic-motion" | "lit-docx" | "readme-studio" | "frontend-ui-ux" | "visual-qa" | "autoresearch" | "autoconference" | "wikify";
3
3
  export type LitOpenCodeFeatureBinding = {
4
4
  readonly kind: LitOpenCodeBindingKind;
5
5
  readonly id: string;
@@ -441,6 +441,64 @@ export declare const litOpenCodeFeatures: readonly ({
441
441
  description: string;
442
442
  })[];
443
443
  verification: string[];
444
+ } | {
445
+ id: "lit-hijack";
446
+ title: string;
447
+ summary: string;
448
+ bindings: ({
449
+ kind: "config";
450
+ id: string;
451
+ surface: string;
452
+ description: string;
453
+ } | {
454
+ kind: "command";
455
+ id: string;
456
+ surface: string;
457
+ description: string;
458
+ } | {
459
+ kind: "agent";
460
+ id: string;
461
+ surface: string;
462
+ description: string;
463
+ })[];
464
+ verification: string[];
465
+ } | {
466
+ id: "lit-adhd";
467
+ title: string;
468
+ summary: string;
469
+ bindings: ({
470
+ kind: "config";
471
+ id: string;
472
+ surface: string;
473
+ description: string;
474
+ } | {
475
+ kind: "command";
476
+ id: string;
477
+ surface: string;
478
+ description: string;
479
+ } | {
480
+ kind: "hook";
481
+ id: string;
482
+ surface: string;
483
+ description: string;
484
+ })[];
485
+ verification: string[];
486
+ } | {
487
+ id: "workflow-stack";
488
+ title: string;
489
+ summary: string;
490
+ bindings: ({
491
+ kind: "config";
492
+ id: string;
493
+ surface: string;
494
+ description: string;
495
+ } | {
496
+ kind: "hook";
497
+ id: string;
498
+ surface: string;
499
+ description: string;
500
+ })[];
501
+ verification: string[];
444
502
  } | {
445
503
  id: "refactor";
446
504
  title: string;
@@ -845,6 +903,27 @@ export declare const litOpenCodeFeatures: readonly ({
845
903
  description: string;
846
904
  })[];
847
905
  verification: string[];
906
+ } | {
907
+ id: "lit-schematic";
908
+ title: string;
909
+ summary: string;
910
+ bindings: ({
911
+ kind: "config";
912
+ id: string;
913
+ surface: string;
914
+ description: string;
915
+ } | {
916
+ kind: "hook";
917
+ id: string;
918
+ surface: string;
919
+ description: string;
920
+ } | {
921
+ kind: "cli";
922
+ id: string;
923
+ surface: string;
924
+ description: string;
925
+ })[];
926
+ verification: string[];
848
927
  } | {
849
928
  id: "lit-typographic-motion";
850
929
  title: string;
package/dist/features.js CHANGED
@@ -532,6 +532,78 @@ export const litOpenCodeFeatures = Object.freeze([
532
532
  ],
533
533
  verification: ["node --test test/lit-brainstorm.test.mjs", "node --test test/runtime-skills.test.mjs", "node --test test/docs.test.mjs"]
534
534
  },
535
+ {
536
+ id: "lit-hijack",
537
+ title: "Lit Hijack",
538
+ summary: "Ports the mechanism in someone else's published work into the user's own skill or system through capture, licence gate, gap, source-free spec, separate build, parity proof and report, with a bundled script deciding when each phase is done.",
539
+ bindings: [
540
+ {
541
+ kind: "config",
542
+ id: "skills/lit-hijack/SKILL.md",
543
+ surface: "LitOpenCode native-installed managed skill",
544
+ description: "Ships the phase procedure with five references and the zero-dependency hijack.mjs helper, installed together so the script the skill names can run."
545
+ },
546
+ {
547
+ kind: "command",
548
+ id: "lit-hijack",
549
+ surface: "OpenCode command /lit-hijack",
550
+ description: "Makes Lit Hijack directly invocable; chat routes lit hijack, lit hijacking, lit 하이재킹 and lit 하이잭 reach the same surface."
551
+ },
552
+ {
553
+ kind: "agent",
554
+ id: "isolated implementer and optional lanes",
555
+ surface: "OpenCode task delegation",
556
+ description: "Builds from the brief alone in a separate git worktree through a write-capable task lane, with optional read-only capture, distil and verifier lanes at depth one; the lit-plan agent stays planning-only."
557
+ }
558
+ ],
559
+ verification: ["node --test test/lit-hijack.test.mjs", "node --test test/runtime-skills.test.mjs", "node --test test/docs.test.mjs"]
560
+ },
561
+ {
562
+ id: "lit-adhd",
563
+ title: "Lit Adhd",
564
+ summary: "Briefs the earlier sessions of this worktree family from a read-only collector (status, goal, real progress or known facts, done, next, roadmap), recommends one next step, and follows it on go; typed start-work, lit approve and lit deny drive the bounded run without pasted JSON.",
565
+ bindings: [
566
+ {
567
+ kind: "config",
568
+ id: "skills/lit-adhd/SKILL.md",
569
+ surface: "LitOpenCode native-installed managed skill",
570
+ description: "Ships the skill with three references and the zero-dependency rewind.mjs collector, installed together so the script the skill names can run."
571
+ },
572
+ {
573
+ kind: "command",
574
+ id: "lit-adhd",
575
+ surface: "OpenCode commands /lit-adhd and /lit-rewind",
576
+ description: "Makes the brief directly invocable; chat routes lit adhd and lit rewind reach the same surface, and a live go follows the armed step."
577
+ },
578
+ {
579
+ kind: "hook",
580
+ id: "chat.message typed prompts",
581
+ surface: "OpenCode chat.message and command.execute.before hooks, and the OpenCode 2 prompt hook",
582
+ description: "Routes go, lit approve, lit deny and start-work [plan] from the user's own root-session prompt into the existing re-entry and bounded-authority lifecycle."
583
+ }
584
+ ],
585
+ verification: ["node --test test/lit-adhd.test.mjs", "node --test test/adhd-go.test.mjs", "node --test test/start-work-typed.test.mjs", "node --test test/runtime-skills.test.mjs", "node --test test/docs.test.mjs"]
586
+ },
587
+ {
588
+ id: "workflow-stack",
589
+ title: "Workflow Stack",
590
+ summary: "Pauses a running long discipline when another lit command interrupts it, keeping its stage and real count in a per-session record, and returns to it on lit continue; the mission band and the lit-adhd collector read the same record.",
591
+ bindings: [
592
+ {
593
+ kind: "config",
594
+ id: ".litopencode/workflow-stack/<session>.json",
595
+ surface: "LitOpenCode runtime state",
596
+ description: "One small guarded file per session: link-refusing, size-capped, atomically replaced, with a stale spine never resumed."
597
+ },
598
+ {
599
+ kind: "hook",
600
+ id: "chat.message activation memory",
601
+ surface: "OpenCode chat.message hook and the OpenCode 2 prompt hook",
602
+ description: "Pushes an interjected discipline over the running one, appends the paused-at line, and resumes the paused discipline on lit continue or go."
603
+ }
604
+ ],
605
+ verification: ["node --test test/workflow-stack.test.mjs", "node --test test/workflow-interleave.test.mjs", "node --test test/runtime-skills.test.mjs"]
606
+ },
535
607
  {
536
608
  id: "refactor",
537
609
  title: "Refactor",
@@ -1145,6 +1217,38 @@ export const litOpenCodeFeatures = Object.freeze([
1145
1217
  ],
1146
1218
  verification: ["node --test test/lit-diagram-drawer.test.mjs", "npm run check:managed-skill-manifest", "npm run check:pack-payload"]
1147
1219
  },
1220
+ {
1221
+ id: "lit-schematic",
1222
+ title: "Lit Schematic",
1223
+ summary: "Installs an OpenCode native skill with a plain-Node drawing kit, symbol library, QA gate, renderer and worked examples for P&IDs, apparatus figures and isometric cutaways, and routes bounded lit drawing requests to it.",
1224
+ bindings: [
1225
+ {
1226
+ kind: "config",
1227
+ id: "skills/lit-schematic/SKILL.md",
1228
+ surface: "OpenCode native skill picker",
1229
+ description: "Selects the physical-schematic workflow and its complete managed skill tree; no dedicated slash command or bare-id chat route is registered."
1230
+ },
1231
+ {
1232
+ kind: "hook",
1233
+ id: "lit-task schematic drawing intent",
1234
+ surface: "OpenCode chat.message activation",
1235
+ description: "Directs bounded lit P&ID, PFD, apparatus and cutaway drawing requests to load the native skill before drawing, ahead of the diagram, film and Office hand-offs; questions, reviews, charts and reports stay inert."
1236
+ },
1237
+ {
1238
+ kind: "cli",
1239
+ id: "litopencode install",
1240
+ surface: "LitOpenCode managed native skill installer",
1241
+ description: "Installs every hash-pinned reference, script, kit module and example."
1242
+ },
1243
+ {
1244
+ kind: "cli",
1245
+ id: "litopencode doctor",
1246
+ surface: "LitOpenCode managed native skill doctor",
1247
+ description: "Verifies the exact installed file closure; the skill's own doctor script reports Chrome, fonts and encoders without installing tools."
1248
+ }
1249
+ ],
1250
+ verification: ["node --test test/lit-schematic.test.mjs test/lit-schematic-symbols.test.mjs test/lit-schematic-outputs.test.mjs", "npm run check:managed-skill-manifest", "npm run check:pack-payload"]
1251
+ },
1148
1252
  {
1149
1253
  id: "lit-typographic-motion",
1150
1254
  title: "Film director",
@@ -1154,7 +1258,7 @@ export const litOpenCodeFeatures = Object.freeze([
1154
1258
  { kind: "hook", id: "lit-task motion-video intent", surface: "OpenCode chat.message activation", description: "Routes bounded film requests before slide and interface guidance with a neutral film context." },
1155
1259
  { kind: "hook", id: "tool.execute.after", surface: "OpenCode tool.execute.after hook", description: "Records each read of a film's or a cover's stills so the done check can confirm the frames were viewed." },
1156
1260
  { kind: "cli", id: "litopencode motion-runtime install|status", surface: "LitOpenCode runtime", description: "Pre-warms pinned dependencies and fonts outside the render session." },
1157
- { kind: "cli", id: "litopencode doctor", surface: "LitOpenCode doctor", description: "Reports Chrome, ffmpeg, WebGL2 tier, software warning, pre-warm status and the cover encoder." }
1261
+ { kind: "cli", id: "litopencode doctor", surface: "LitOpenCode doctor", description: "Reports Chrome, ffmpeg, WebGL2 tier, software warning, pre-warm status, the cover encoder and, as information only, whether Blender is installed." }
1158
1262
  ],
1159
1263
  verification: ["node --test test/lit-typographic-motion.test.mjs", "node --test test/motion-cover.test.mjs", "npm run check:managed-skill-manifest", "npm run check:pack-payload"]
1160
1264
  },
package/dist/hooks.js CHANGED
@@ -3,6 +3,7 @@ import { dynamicRulesForPaths } from "./rules/hooks.js";
3
3
  import { applyLitOpenCodePostEditHook, applyLitOpenCodeToolAfterHook, applyLitOpenCodeToolBeforeHook, applyTaskRecursionGuard, mutatedFilePaths } from "./tool-guards.js";
4
4
  import { captureKnowledgeEvent } from "./knowledge.js";
5
5
  import { recordMotionImageRead } from "./motion-image-reads.js";
6
+ import { markLiveness } from "./session-liveness.js";
6
7
  export function createToolExecuteBeforeHook(options = {}) {
7
8
  return async (input, output) => {
8
9
  await applyTaskRecursionGuard(input, options.getSession);
@@ -13,6 +14,8 @@ export function createToolExecuteBeforeHook(options = {}) {
13
14
  }
14
15
  export function createToolExecuteAfterHook(options = {}) {
15
16
  return async (input, output) => {
17
+ if (options.projectRoot !== undefined)
18
+ await markLiveness(options.projectRoot, input.sessionID, "alive");
16
19
  applyLitOpenCodeToolAfterHook(input, output);
17
20
  applyLitOpenCodePostEditHook(input, output);
18
21
  recordMotionImageRead(input, options.projectRoot);
package/dist/ledger.js CHANGED
@@ -407,7 +407,18 @@ async function writeEvidenceLedger(projectRoot, state) {
407
407
  await removeIfPresent(tempFile);
408
408
  throw new LedgerIoError(`Failed to write goals.json: ${error instanceof Error ? error.message : String(error)}`);
409
409
  }
410
- await fs.writeFile(paths.briefFile, renderEvidenceBrief(state), "utf8");
410
+ // The brief is replaced through a temp file and a rename, so a link planted at brief.md is swapped out,
411
+ // never written through.
412
+ goalsTempCounter += 1;
413
+ const briefTemp = path.join(paths.litLoopDir, `${goalsTempPrefix}${process.pid}-${goalsTempCounter}`);
414
+ try {
415
+ await fs.writeFile(briefTemp, renderEvidenceBrief(state), { encoding: "utf8", flag: "wx" });
416
+ await fs.rename(briefTemp, paths.briefFile);
417
+ }
418
+ catch (error) {
419
+ await removeIfPresent(briefTemp);
420
+ throw new LedgerIoError(`Failed to write brief.md: ${error instanceof Error ? error.message : String(error)}`);
421
+ }
411
422
  return state;
412
423
  }
413
424
  function evidenceMutationPaths(projectRoot) {
@@ -0,0 +1,23 @@
1
+ import type { SemanticAuthorityAction } from "./bounded-authority.ts";
2
+ export type ScopeRoot = {
3
+ readonly root: string;
4
+ readonly actions: readonly SemanticAuthorityAction[];
5
+ };
6
+ export type UncoveredScopePath = {
7
+ readonly path: string;
8
+ readonly line: string;
9
+ } | {
10
+ readonly path: string;
11
+ readonly problem: string;
12
+ };
13
+ /**
14
+ * `Scope roots:` lines outside code fences, with paths resolved against the project. A line naming a broad
15
+ * folder, or any action other than read, write and execute, grants nothing.
16
+ */
17
+ export declare function parseScopeRoots(planText: string, projectRoot: string): ScopeRoot[];
18
+ /**
19
+ * Each outside folder the plan's todo section reaches that neither the project nor a `Scope roots:` line
20
+ * covers, once per folder: with the exact line to paste, or with a problem when only a broad folder exists.
21
+ */
22
+ export declare function uncoveredScopePaths(planText: string, projectRoot: string): UncoveredScopePath[];
23
+ export declare function describeUncoveredScopePaths(entries: readonly UncoveredScopePath[]): string;
@@ -0,0 +1,116 @@
1
+ import { realpathSync, statSync } from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ const scopeLine = /^Scope roots?:[ \t]*(\S+)[ \t]*\(([^()\r\n]+)\)[ \t]*$/u;
5
+ const semanticActions = new Set(["read", "write", "execute"]);
6
+ // Two or more absolute segments; a lone `/` or a relative path is not a folder the work reaches.
7
+ const absolutePath = /(?<![\w.~/-])\/[\w.@+%,=~-]+(?:\/[\w.@+%,=~-]+)+\/?/gu;
8
+ function linesOutsideFences(text) {
9
+ const kept = [];
10
+ let fence;
11
+ for (const line of text.split(/\r?\n/u)) {
12
+ const marker = /^\s{0,3}(`{3,}|~{3,})/u.exec(line)?.[1];
13
+ if (marker !== undefined && (fence === undefined || marker.startsWith(fence))) {
14
+ fence = fence === undefined ? marker : undefined;
15
+ continue;
16
+ }
17
+ if (fence === undefined)
18
+ kept.push(line);
19
+ }
20
+ return kept;
21
+ }
22
+ /** Real path of the deepest existing ancestor, with the missing tail appended unchanged. */
23
+ function realish(target) {
24
+ const missing = [];
25
+ for (let at = path.resolve(target);; at = path.dirname(at)) {
26
+ try {
27
+ return path.join(realpathSync(at), ...missing.reverse());
28
+ }
29
+ catch {
30
+ if (path.dirname(at) === at)
31
+ return path.resolve(target);
32
+ missing.push(path.basename(at));
33
+ }
34
+ }
35
+ }
36
+ function nearestDirectory(target) {
37
+ for (let at = path.resolve(target);; at = path.dirname(at)) {
38
+ try {
39
+ if (statSync(at).isDirectory())
40
+ return realish(at);
41
+ }
42
+ catch {
43
+ // Not created yet; try the parent.
44
+ }
45
+ if (path.dirname(at) === at)
46
+ return at;
47
+ }
48
+ }
49
+ /** The filesystem root, a top-level folder or the home folder itself is too broad to grant. */
50
+ function tooBroad(directory) {
51
+ const parent = path.dirname(directory);
52
+ return parent === directory || path.dirname(parent) === parent || directory === realish(os.homedir());
53
+ }
54
+ function within(root, candidate) {
55
+ const relative = path.relative(root, candidate);
56
+ return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
57
+ }
58
+ /**
59
+ * `Scope roots:` lines outside code fences, with paths resolved against the project. A line naming a broad
60
+ * folder, or any action other than read, write and execute, grants nothing.
61
+ */
62
+ export function parseScopeRoots(planText, projectRoot) {
63
+ const roots = [];
64
+ for (const line of linesOutsideFences(planText)) {
65
+ const match = scopeLine.exec(line.trim());
66
+ if (match === null)
67
+ continue;
68
+ const actions = match[2].split(",").map((action) => action.trim().toLowerCase());
69
+ if (actions.length === 0 || !actions.every((action) => semanticActions.has(action)))
70
+ continue;
71
+ const root = path.resolve(projectRoot, match[1]);
72
+ if (tooBroad(realish(root)))
73
+ continue;
74
+ roots.push({ root, actions: [...new Set(actions)] });
75
+ }
76
+ return roots;
77
+ }
78
+ /** Absolute paths of a todo line; a code span holding a command (it has a space) is data, not a reach. */
79
+ function pathMentions(line) {
80
+ const spansAsText = line.replace(/`([^`]*)`/gu, (_, span) => (/\s/u.test(span.trim()) ? " " : ` ${span.trim()} `));
81
+ return (spansAsText.match(absolutePath) ?? []).map((mention) => mention.replace(/[.,:;)]+$/u, ""));
82
+ }
83
+ /**
84
+ * Each outside folder the plan's todo section reaches that neither the project nor a `Scope roots:` line
85
+ * covers, once per folder: with the exact line to paste, or with a problem when only a broad folder exists.
86
+ */
87
+ export function uncoveredScopePaths(planText, projectRoot) {
88
+ const project = realish(projectRoot);
89
+ const covered = [project, ...parseScopeRoots(planText, project).map((scope) => realish(scope.root))];
90
+ const found = new Map();
91
+ let inTodos = false;
92
+ for (const line of linesOutsideFences(planText)) {
93
+ const heading = /^#{1,2}\s+(.+?)\s*$/u.exec(line)?.[1];
94
+ if (heading !== undefined)
95
+ inTodos = /^todos\b/iu.test(heading);
96
+ if (!inTodos)
97
+ continue;
98
+ for (const mention of pathMentions(line)) {
99
+ const real = realish(mention);
100
+ if (covered.some((root) => within(root, real)))
101
+ continue;
102
+ const directory = nearestDirectory(mention);
103
+ if (found.has(directory))
104
+ continue;
105
+ found.set(directory, tooBroad(directory)
106
+ ? { path: mention, problem: `${mention} is outside the project; name a narrower existing folder on a Scope roots line.` }
107
+ : { path: mention, line: `Scope roots: ${directory} (read)` });
108
+ }
109
+ }
110
+ return [...found.values()];
111
+ }
112
+ export function describeUncoveredScopePaths(entries) {
113
+ return entries.map((entry) => ("line" in entry
114
+ ? `${entry.path} is outside the project and no Scope roots line covers it; add this line to the plan: ${entry.line}`
115
+ : entry.problem)).join(" ");
116
+ }
@@ -0,0 +1,7 @@
1
+ /** The newest stable installed version strictly newer than the loaded one, or undefined. */
2
+ export declare function restartVersion(loaded: unknown, installed: readonly unknown[]): string | undefined;
3
+ /**
4
+ * What is installed now: the package.json version under `packageRoot`, then the target of an automatic
5
+ * update whose receipt says it was installed. Unreadable or malformed sources are left out.
6
+ */
7
+ export declare function readInstalledVersions(packageRoot: string, homeDir?: string): Promise<string[]>;
@@ -0,0 +1,40 @@
1
+ import fs from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { readAutoUpdateReceipt } from "./cli/auto-update.js";
5
+ import { compareStableVersions } from "./cli/update-notifier.js";
6
+ // OpenCode keeps running the plugin code it loaded at start, so an update installed meanwhile (by the
7
+ // automatic update at start, or by the CLI from a terminal) waits for the next start. The TUI compares
8
+ // the version it loaded with what is installed now and, when the install is newer, asks for a restart.
9
+ // It never starts anything itself: inside the OpenCode host, `process.execPath` is the host binary.
10
+ /** The newest stable installed version strictly newer than the loaded one, or undefined. */
11
+ export function restartVersion(loaded, installed) {
12
+ let newest;
13
+ for (const candidate of installed) {
14
+ if (compareStableVersions(candidate, loaded) !== 1)
15
+ continue;
16
+ if (newest === undefined || compareStableVersions(candidate, newest) === 1)
17
+ newest = candidate;
18
+ }
19
+ return newest;
20
+ }
21
+ /**
22
+ * What is installed now: the package.json version under `packageRoot`, then the target of an automatic
23
+ * update whose receipt says it was installed. Unreadable or malformed sources are left out.
24
+ */
25
+ export async function readInstalledVersions(packageRoot, homeDir = os.homedir()) {
26
+ const versions = [];
27
+ try {
28
+ const parsed = JSON.parse(await fs.readFile(path.join(packageRoot, "package.json"), "utf8"));
29
+ const version = typeof parsed === "object" && parsed !== null ? parsed.version : undefined;
30
+ if (typeof version === "string")
31
+ versions.push(version);
32
+ }
33
+ catch {
34
+ // No readable package.json; the receipt may still say what was installed.
35
+ }
36
+ const receipt = await readAutoUpdateReceipt(homeDir).catch(() => undefined);
37
+ if (receipt !== undefined && receipt.status === "updated" && receipt.targetVersion !== undefined)
38
+ versions.push(receipt.targetVersion);
39
+ return versions;
40
+ }
@@ -25,13 +25,13 @@ const secretShapeAlternatives = [
25
25
  String.raw `(?<![A-Za-z0-9_])eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+(?![A-Za-z0-9_])`,
26
26
  String.raw `\b(?:authorization|proxy-authorization)\s*:\s*\S+\s+\S+`,
27
27
  String.raw `\b(?:bearer|basic)\s+[A-Za-z0-9._~+/=-]{8,}(?=$|[^A-Za-z0-9._~+/=-])`,
28
- String.raw `\b(?:password|passwd|secret|token|api[_-]?key|access[_-]?token)\s*[:=]\s*[^\s,;]{8,}`,
29
- String.raw `\b[A-Za-z][A-Za-z0-9]*(?:[_-][A-Za-z0-9]+)*[_-](?:token|secret|key)(?:[_-][A-Za-z0-9]+)*\s*[:=]\s*[^\s,;]{8,}`,
30
- String.raw `\b_?auth(?:[_-]?token)?\s*[:=]\s*[^\s,;]{8,}`,
28
+ String.raw `\b(?:password|passwd|secret|token|api[_-]?key|access[_-]?token)["']?\s*[:=]\s*[^\s,;]{8,}`,
29
+ String.raw `\b[A-Za-z][A-Za-z0-9]*(?:[_-][A-Za-z0-9]+)*[_-](?:token|secret|key)(?:[_-][A-Za-z0-9]+)*["']?\s*[:=]\s*[^\s,;]{8,}`,
30
+ String.raw `\b_?auth(?:[_-]?token)?["']?\s*[:=]\s*[^\s,;]{8,}`,
31
31
  String.raw `(?<![A-Za-z0-9+.-])(?:[A-Za-z][A-Za-z0-9+.-]*:)?\/\/[^/?#\s]+@`
32
32
  ];
33
- const shortKeyValueSecretShape = /(?<![A-Za-z0-9_])(?:password|passwd|passphrase|secret|token|api[_-]?key|access[_-]?token|auth[_-]?token|[A-Za-z][A-Za-z0-9]*(?:[_-][A-Za-z0-9]+)*[_-](?:password|passwd|passphrase|secret|token|key)(?:[_-][A-Za-z0-9]+)*)\s*=\s*(?:"[^"\r\n]+"|'[^'\r\n]+'|[^\s,;]+)/iu;
34
- const shortUppercaseColonSecretShape = /(?<![A-Za-z0-9_])(?:PASSWORD|PASSWD|PASSPHRASE|SECRET|TOKEN|API[_-]?KEY|ACCESS[_-]?TOKEN|AUTH[_-]?TOKEN|[A-Z][A-Z0-9]*(?:[_-][A-Z0-9]+)*[_-](?:PASSWORD|PASSWD|PASSPHRASE|SECRET|TOKEN|KEY)(?:[_-][A-Z0-9]+)*)\s*:\s*(?:"[^"\r\n]+"|'[^'\r\n]+'|[^\s,;]+)/u;
33
+ const shortKeyValueSecretShape = /(?<![A-Za-z0-9_])(?:password|passwd|passphrase|secret|token|api[_-]?key|access[_-]?token|auth[_-]?token|[A-Za-z][A-Za-z0-9]*(?:[_-][A-Za-z0-9]+)*[_-](?:password|passwd|passphrase|secret|token|key)(?:[_-][A-Za-z0-9]+)*)["']?\s*=\s*(?:"[^"\r\n]+"|'[^'\r\n]+'|[^\s,;]+)/iu;
34
+ const shortUppercaseColonSecretShape = /(?<![A-Za-z0-9_])(?:PASSWORD|PASSWD|PASSPHRASE|SECRET|TOKEN|API[_-]?KEY|ACCESS[_-]?TOKEN|AUTH[_-]?TOKEN|[A-Z][A-Z0-9]*(?:[_-][A-Z0-9]+)*[_-](?:PASSWORD|PASSWD|PASSPHRASE|SECRET|TOKEN|KEY)(?:[_-][A-Z0-9]+)*)["']?\s*:\s*(?:"[^"\r\n]+"|'[^'\r\n]+'|[^\s,;]+)/u;
35
35
  /** The guarded credential shape. Exported so a consumer can read it, never widen it. */
36
36
  export const secretShape = new RegExp(`(?:${secretShapeAlternatives.join("|")})`, "iu");
37
37
  const lowercaseTokenShape = /\btoken\s+[A-Za-z0-9._~+/=-]{8,}(?=$|[^A-Za-z0-9._~+/=-])/u;
package/dist/server.js CHANGED
@@ -11,6 +11,7 @@ import { createToolExecuteAfterHook, createToolExecuteBeforeHook } from "./hooks
11
11
  import { createLogger } from "./logger.js";
12
12
  import { createIgnitionState } from "./ignition.js";
13
13
  import { createSessionLookup } from "./session-lineage.js";
14
+ import { markLiveness } from "./session-liveness.js";
14
15
  import { applyCompactionRuleReset, applyStaticRuleInjection } from "./rules/hooks.js";
15
16
  import { defaultOpenCodeConfigRoot } from "./state.js";
16
17
  import { litOpenCodeTools } from "./tools.js";
@@ -78,7 +79,10 @@ export function createLitOpenCodePlugin(autoUpdateRunner = runPluginAutoUpdate)
78
79
  registerLitOpenCodeAgents(config, loaded.config);
79
80
  },
80
81
  event: async (eventInput) => {
82
+ if (eventInput.event.type === "session.idle")
83
+ await markLiveness(root, eventInput.event.properties.sessionID, "idle");
81
84
  if (eventInput.event.type === "session.deleted") {
85
+ await markLiveness(root, eventInput.event.properties.info.id, "ended");
82
86
  ignitionState.clear(eventInput.event.properties.info.id);
83
87
  activationMemory.forget(eventInput.event.properties.info.id);
84
88
  trustedCommandActivations.delete(eventInput.event.properties.info.id);
@@ -0,0 +1,20 @@
1
+ export type LivenessState = "alive" | "idle" | "ended";
2
+ export type LivenessRecord = {
3
+ readonly version: 1;
4
+ readonly sessionId: string;
5
+ readonly state: LivenessState;
6
+ readonly at: string;
7
+ readonly herdrPane: string | null;
8
+ };
9
+ export declare const livenessRepeatMs = 30000;
10
+ export declare function livenessFile(projectRoot: string, sessionID: string): string;
11
+ /** The session's record, or undefined when the id is unsafe or the file is missing, a link, oversized or malformed. */
12
+ export declare function readLivenessSync(projectRoot: string, sessionID: string): LivenessRecord | undefined;
13
+ /**
14
+ * Records the session's state; true when a record was written. Never throws: a missing project state folder,
15
+ * a linked folder or record, an unsafe id or a failed write all return false so the calling hook carries on.
16
+ */
17
+ export declare function markLiveness(projectRoot: string, sessionID: string, state: LivenessState, options?: {
18
+ readonly now?: number;
19
+ readonly env?: NodeJS.ProcessEnv;
20
+ }): Promise<boolean>;