@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.
- package/CHANGELOG.md +38 -0
- package/README-Ko-KR.md +6 -6
- package/README.md +6 -6
- package/TRADEMARK.md +12 -0
- package/dist/activation-primary-prompts.js +5 -1
- package/dist/activation-probe.js +1 -0
- package/dist/activation-prompt-utils.d.ts +1 -1
- package/dist/activation-reentry.d.ts +20 -0
- package/dist/activation-reentry.js +110 -1
- package/dist/activation-routing.d.ts +2 -1
- package/dist/activation-routing.js +100 -11
- package/dist/activation-workflow-prompts.d.ts +4 -0
- package/dist/activation-workflow-prompts.js +30 -0
- package/dist/activation.d.ts +1 -1
- package/dist/activation.js +44 -5
- package/dist/adhd-next.d.ts +51 -0
- package/dist/adhd-next.js +150 -0
- package/dist/agents/defaults.js +1 -1
- package/dist/cli/managed-skill-assets.d.ts +1 -1
- package/dist/cli/managed-skill-assets.js +7 -1
- package/dist/cli/native-skill-integrity.js +1 -1
- package/dist/cli.js +7 -1
- package/dist/commands.d.ts +28 -1
- package/dist/commands.js +58 -5
- package/dist/durable-plan.d.ts +5 -1
- package/dist/durable-plan.js +14 -2
- package/dist/features.d.ts +80 -1
- package/dist/features.js +105 -1
- package/dist/hooks.js +3 -0
- package/dist/ledger.js +12 -1
- package/dist/plan-scope-roots.d.ts +23 -0
- package/dist/plan-scope-roots.js +116 -0
- package/dist/restart-notice.d.ts +7 -0
- package/dist/restart-notice.js +40 -0
- package/dist/secret-shapes.js +5 -5
- package/dist/server.js +4 -0
- package/dist/session-liveness.d.ts +20 -0
- package/dist/session-liveness.js +99 -0
- package/dist/skills.d.ts +22 -1
- package/dist/skills.js +36 -0
- package/dist/start-work-typed.d.ts +34 -0
- package/dist/start-work-typed.js +167 -0
- package/dist/state.d.ts +3 -0
- package/dist/state.js +3 -0
- package/dist/tools.js +22 -2
- package/dist/tui/mission-band.d.ts +22 -1
- package/dist/tui/mission-band.js +75 -16
- package/dist/tui/mission-looks.d.ts +38 -0
- package/dist/tui/mission-looks.js +73 -0
- package/dist/tui/mission-model.d.ts +2 -0
- package/dist/tui/mission-model.js +3 -1
- package/dist/tui/mission-rainbow.d.ts +33 -0
- package/dist/tui/mission-rainbow.js +90 -0
- package/dist/tui/mission-source.d.ts +49 -0
- package/dist/tui/mission-source.js +217 -2
- package/dist/tui/mission-text.d.ts +2 -0
- package/dist/tui/mission-text.js +9 -1
- package/dist/tui/mission-threads.d.ts +58 -0
- package/dist/tui/mission-threads.js +128 -0
- package/dist/tui.js +112 -7
- package/dist/uiux-visual-catalog.js +8 -1
- package/dist/v2/events.js +3 -0
- package/dist/v2/session-hooks.js +38 -5
- package/dist/workflow-stack.d.ts +53 -0
- package/dist/workflow-stack.js +196 -0
- package/docs/assets/readme/badge-version.svg +1 -1
- package/docs/assets/skills/lit-schematic.webp +0 -0
- package/docs/reference-Ko-KR.md +48 -3
- package/docs/reference.md +54 -3
- package/package.json +1 -1
- package/skills/frontend-ui-ux/SKILL.md +3 -2
- package/skills/frontend-ui-ux/kit/components.css +414 -0
- package/skills/frontend-ui-ux/kit/fonts.json +22 -0
- package/skills/frontend-ui-ux/kit/layouts/landing.html +164 -0
- package/skills/frontend-ui-ux/kit/layouts/settings.html +114 -0
- package/skills/frontend-ui-ux/kit/layouts/workspace.html +115 -0
- package/skills/frontend-ui-ux/kit/styles/computational-brutalism.json +227 -0
- package/skills/frontend-ui-ux/kit/styles/field-notes.json +205 -0
- package/skills/frontend-ui-ux/kit/styles/graphite.json +200 -0
- package/skills/frontend-ui-ux/kit/styles/meadow.json +199 -0
- package/skills/frontend-ui-ux/kit/styles/neo-brutalism.json +222 -0
- package/skills/frontend-ui-ux/kit/ui.js +226 -0
- package/skills/frontend-ui-ux/references/brand-and-imagery.md +2 -2
- package/skills/frontend-ui-ux/references/complete-contract.md +2 -1
- package/skills/frontend-ui-ux/references/craft-floor.md +6 -2
- package/skills/frontend-ui-ux/references/default-editorial-pixel.json +3 -0
- package/skills/frontend-ui-ux/references/house-styles.md +236 -0
- package/skills/frontend-ui-ux/references/motion-guide.md +2 -2
- package/skills/frontend-ui-ux/references/production.md +3 -1
- package/skills/frontend-ui-ux/references/slop-register.md +4 -4
- package/skills/frontend-ui-ux/scripts/design-lock.mjs +400 -0
- package/skills/frontend-ui-ux/scripts/pixel-art.mjs +60 -0
- package/skills/frontend-ui-ux/scripts/probe-lock.mjs +235 -0
- package/skills/frontend-ui-ux/scripts/probe-page.mjs +34 -12
- package/skills/frontend-ui-ux/scripts/probe-static.mjs +16 -3
- package/skills/frontend-ui-ux/scripts/probe-thresholds.json +8 -2
- package/skills/frontend-ui-ux/scripts/probe.mjs +35 -7
- package/skills/lit-adhd/SKILL.md +209 -0
- package/skills/lit-adhd/references/brief-format.md +46 -0
- package/skills/lit-adhd/references/card-examples.md +103 -0
- package/skills/lit-adhd/references/status-taxonomy.md +34 -0
- package/skills/lit-adhd/scripts/rewind.mjs +933 -0
- package/skills/lit-diagram-drawer/SKILL.md +4 -3
- package/skills/lit-diagram-drawer/references/style-guide.md +20 -11
- package/skills/lit-diagram-drawer/references/type-architecture.md +3 -3
- package/skills/lit-diagram-drawer/references/type-dependency.md +1 -1
- package/skills/lit-diagram-drawer/references/type-tree.md +3 -3
- package/skills/lit-diagram-drawer/references/type-wardley.md +1 -1
- package/skills/lit-diagram-drawer/references/verifier-guide.md +1 -0
- package/skills/lit-diagram-drawer/scripts/craft-thresholds.json +1 -2
- package/skills/lit-diagram-drawer/scripts/visual-quality.mjs +1 -2
- package/skills/lit-docx/SKILL.md +2 -1
- package/skills/lit-handoff/SKILL.md +2 -0
- package/skills/lit-hijack/SKILL.md +422 -0
- package/skills/lit-hijack/references/capture-and-provenance.md +87 -0
- package/skills/lit-hijack/references/clean-room-build.md +111 -0
- package/skills/lit-hijack/references/distil-and-licence.md +100 -0
- package/skills/lit-hijack/references/gap-and-port-design.md +126 -0
- package/skills/lit-hijack/references/parity-and-report.md +110 -0
- package/skills/lit-hijack/scripts/hijack.mjs +993 -0
- package/skills/lit-plan/SKILL.md +8 -0
- package/skills/lit-pptx/SKILL.md +27 -11
- package/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Bold.ttf +0 -0
- package/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Regular.ttf +0 -0
- package/skills/lit-pptx/fonts/jetbrains-mono/OFL.txt +93 -0
- package/skills/lit-pptx/fonts/jetbrains-mono/SOURCE.md +17 -0
- package/skills/lit-pptx/references/density-and-fill.md +9 -3
- package/skills/lit-pptx/references/direction-step.md +21 -6
- package/skills/lit-pptx/references/examples/04-lecture-chalk-ko.md +3 -6
- package/skills/lit-pptx/references/examples/05-research-talk-paper-en.md +1 -5
- package/skills/lit-pptx/references/examples/08-reliability-keynote-night-en.md +0 -4
- package/skills/lit-pptx/references/examples/09-status-update-ledger-en.md +2 -2
- package/skills/lit-pptx/references/examples/11-forecast-review-night-ko.md +4 -7
- package/skills/lit-pptx/references/examples/13-engineering-review-computational-brutalism-ko.md +173 -0
- package/skills/lit-pptx/references/examples/14-launch-pitch-neo-brutalism-ko.md +154 -0
- package/skills/lit-pptx/references/examples/15-design-lecture-bauhaus-ko.md +139 -0
- package/skills/lit-pptx/references/examples/16-community-programme-riso-ko.md +158 -0
- package/skills/lit-pptx/references/examples/17-public-data-briefing-newsroom-ko.md +179 -0
- package/skills/lit-pptx/references/layout-families.md +65 -47
- package/skills/lit-pptx/references/title-treatments.md +83 -134
- package/skills/lit-pptx/references/tonalities/atlas.md +3 -3
- package/skills/lit-pptx/references/tonalities/bauhaus.md +140 -0
- package/skills/lit-pptx/references/tonalities/chalk.md +7 -6
- package/skills/lit-pptx/references/tonalities/computational-brutalism.md +150 -0
- package/skills/lit-pptx/references/tonalities/gazette.md +1 -1
- package/skills/lit-pptx/references/tonalities/ledger.md +1 -1
- package/skills/lit-pptx/references/tonalities/neo-brutalism.md +161 -0
- package/skills/lit-pptx/references/tonalities/newsroom.md +144 -0
- package/skills/lit-pptx/references/tonalities/night.md +1 -1
- package/skills/lit-pptx/references/tonalities/paper.md +2 -2
- package/skills/lit-pptx/references/tonalities/riso.md +137 -0
- package/skills/lit-pptx/references/tonalities/signal.md +3 -3
- package/skills/lit-pptx/references/tonalities/studio.md +7 -6
- package/skills/lit-pptx/run.mjs +2 -1
- package/skills/lit-pptx/scripts/compile-deck.js +1 -1
- package/skills/lit-pptx/scripts/craft-thresholds.json +4 -8
- package/skills/lit-pptx/scripts/craft_extras.py +56 -3
- package/skills/lit-pptx/scripts/deck_output.py +75 -90
- package/skills/lit-pptx/scripts/embed_fonts.py +13 -1
- package/skills/lit-pptx/scripts/layout_inventory.py +12 -5
- package/skills/lit-pptx/scripts/lib/grid-resolver.js +101 -110
- package/skills/lit-pptx/scripts/lib/layout-resolver.js +9 -15
- package/skills/lit-pptx/scripts/lib/render-pack.js +373 -566
- package/skills/lit-pptx/scripts/lib/slide-grid.js +104 -0
- package/skills/lit-pptx/scripts/lib/template-registry.js +57 -6
- package/skills/lit-pptx/scripts/qa_deck.py +10 -11
- package/skills/lit-pptx/scripts/render_pages.py +118 -0
- package/skills/lit-pptx/templates/tonalities/atlas/pack.yaml +1 -1
- package/skills/lit-pptx/templates/tonalities/bauhaus/pack.yaml +98 -0
- package/skills/lit-pptx/templates/tonalities/chalk/pack.yaml +1 -1
- package/skills/lit-pptx/templates/tonalities/computational-brutalism/pack.yaml +99 -0
- package/skills/lit-pptx/templates/tonalities/gazette/pack.yaml +1 -1
- package/skills/lit-pptx/templates/tonalities/ledger/pack.yaml +1 -1
- package/skills/lit-pptx/templates/tonalities/neo-brutalism/pack.yaml +107 -0
- package/skills/lit-pptx/templates/tonalities/newsroom/pack.yaml +99 -0
- package/skills/lit-pptx/templates/tonalities/night/pack.yaml +1 -1
- package/skills/lit-pptx/templates/tonalities/paper/pack.yaml +1 -1
- package/skills/lit-pptx/templates/tonalities/riso/pack.yaml +99 -0
- package/skills/lit-pptx/templates/tonalities/signal/pack.yaml +2 -2
- package/skills/lit-pptx/templates/tonalities/studio/pack.yaml +1 -1
- package/skills/lit-recap/SKILL.md +4 -0
- package/skills/lit-schematic/SKILL.md +118 -0
- package/skills/lit-schematic/examples/iso-heat-exchanger/build.mjs +38 -0
- package/skills/lit-schematic/examples/iso-heat-exchanger/scene.mjs +133 -0
- package/skills/lit-schematic/examples/journal-adsorption-rig/build.mjs +87 -0
- package/skills/lit-schematic/examples/pid-dosing-skid/build.mjs +85 -0
- package/skills/lit-schematic/references/cutaway-outputs.md +70 -0
- package/skills/lit-schematic/references/isometric-craft.md +101 -0
- package/skills/lit-schematic/references/journal-figures.md +72 -0
- package/skills/lit-schematic/references/kit-api.md +134 -0
- package/skills/lit-schematic/references/pfd-and-layout.md +53 -0
- package/skills/lit-schematic/references/pid-drafting.md +103 -0
- package/skills/lit-schematic/references/pid-symbols.md +163 -0
- package/skills/lit-schematic/references/verification.md +100 -0
- package/skills/lit-schematic/scripts/doctor.mjs +57 -0
- package/skills/lit-schematic/scripts/lib/figure.mjs +81 -0
- package/skills/lit-schematic/scripts/lib/fonts.mjs +25 -0
- package/skills/lit-schematic/scripts/lib/geom.mjs +113 -0
- package/skills/lit-schematic/scripts/lib/interactive.mjs +292 -0
- package/skills/lit-schematic/scripts/lib/isa.mjs +115 -0
- package/skills/lit-schematic/scripts/lib/iso.mjs +719 -0
- package/skills/lit-schematic/scripts/lib/legend-sheet.mjs +162 -0
- package/skills/lit-schematic/scripts/lib/pid.mjs +937 -0
- package/skills/lit-schematic/scripts/lib/png.mjs +132 -0
- package/skills/lit-schematic/scripts/lib/qa-core.mjs +658 -0
- package/skills/lit-schematic/scripts/lib/route.mjs +218 -0
- package/skills/lit-schematic/scripts/lib/sheet.mjs +890 -0
- package/skills/lit-schematic/scripts/lib/svg.mjs +82 -0
- package/skills/lit-schematic/scripts/lib/theme.mjs +115 -0
- package/skills/lit-schematic/scripts/motion.mjs +129 -0
- package/skills/lit-schematic/scripts/qa.mjs +92 -0
- package/skills/lit-schematic/scripts/render.mjs +233 -0
- package/skills/lit-schematic/scripts/scaffold.mjs +60 -0
- package/skills/lit-scientific-visualization/SKILL.md +27 -4
- package/skills/lit-typographic-motion/SKILL.md +19 -17
- package/skills/lit-typographic-motion/THIRD_PARTY_NOTICES +9 -0
- package/skills/lit-typographic-motion/engine/accents.mjs +6 -0
- package/skills/lit-typographic-motion/engine/assets.mjs +282 -0
- package/skills/lit-typographic-motion/engine/blender/runner.py +228 -0
- package/skills/lit-typographic-motion/engine/blender.mjs +126 -0
- package/skills/lit-typographic-motion/engine/board.mjs +138 -0
- package/skills/lit-typographic-motion/engine/cover/assets.mjs +11 -8
- package/skills/lit-typographic-motion/engine/cover/capture.mjs +6 -6
- package/skills/lit-typographic-motion/engine/cover/render.mjs +20 -7
- package/skills/lit-typographic-motion/engine/cover/treatment.mjs +30 -3
- package/skills/lit-typographic-motion/engine/fill.mjs +54 -0
- package/skills/lit-typographic-motion/engine/gallery.mjs +118 -0
- package/skills/lit-typographic-motion/engine/house.mjs +42 -0
- package/skills/lit-typographic-motion/engine/look.mjs +65 -8
- package/skills/lit-typographic-motion/engine/loudness.mjs +101 -0
- package/skills/lit-typographic-motion/engine/scaffold.mjs +219 -0
- package/skills/lit-typographic-motion/engine/score.mjs +594 -0
- package/skills/lit-typographic-motion/engine/sound.mjs +9 -57
- package/skills/lit-typographic-motion/engine/stage/capture.mjs +23 -9
- package/skills/lit-typographic-motion/engine/stage/clock.js +8 -2
- package/skills/lit-typographic-motion/engine/stage/cover-init.js +12 -1
- package/skills/lit-typographic-motion/engine/stage/frame-worker.mjs +15 -7
- package/skills/lit-typographic-motion/engine/stage/gate.mjs +48 -4
- package/skills/lit-typographic-motion/engine/stage/qa-page.js +16 -5
- package/skills/lit-typographic-motion/engine/stage/qa.mjs +148 -7
- package/skills/lit-typographic-motion/engine/stage/render.mjs +69 -7
- package/skills/lit-typographic-motion/engine/stage/scan.mjs +20 -1
- package/skills/lit-typographic-motion/engine/stage/stage-kit.js +85 -4
- package/skills/lit-typographic-motion/engine/stills.mjs +1 -1
- package/skills/lit-typographic-motion/engine/styles.mjs +221 -0
- package/skills/lit-typographic-motion/engine/text.mjs +1 -1
- package/skills/lit-typographic-motion/engine/treatment.mjs +190 -6
- package/skills/lit-typographic-motion/engine/vendor/three/LICENSE +21 -0
- package/skills/lit-typographic-motion/engine/vendor/three/addons/environments/RoomEnvironment.js +144 -0
- package/skills/lit-typographic-motion/engine/vendor/three/addons/geometries/RoundedBoxGeometry.js +155 -0
- package/skills/lit-typographic-motion/engine/vendor/three/three.module.js +54571 -0
- package/skills/lit-typographic-motion/gate.mjs +18 -2
- package/skills/lit-typographic-motion/probe.mjs +13 -1
- package/skills/lit-typographic-motion/recipes/hero-3d/expected.json +64 -0
- package/skills/lit-typographic-motion/recipes/hero-3d/index.html +132 -0
- package/skills/lit-typographic-motion/recipes/orbit-loop/expected.json +2 -0
- package/skills/lit-typographic-motion/recipes/painted-light/expected.json +2 -0
- package/skills/lit-typographic-motion/recipes/weight-tide/expected.json +2 -0
- package/skills/lit-typographic-motion/references/cover.md +56 -13
- package/skills/lit-typographic-motion/references/craft-loop.md +20 -7
- package/skills/lit-typographic-motion/references/depth.md +112 -0
- package/skills/lit-typographic-motion/references/runtime.md +21 -6
- package/skills/lit-typographic-motion/references/sound.md +76 -0
- package/skills/lit-typographic-motion/references/stage.md +50 -7
- package/skills/lit-typographic-motion/references/studio.md +162 -0
- package/skills/lit-typographic-motion/references/style-bibles.md +18 -0
- package/skills/lit-typographic-motion/references/treatment.md +108 -9
- package/skills/lit-typographic-motion/render.mjs +60 -3
- package/skills/lit-typographic-motion/styles/paper.json +185 -0
- package/skills/lit-typographic-motion/styles/swiss-signal.json +188 -0
- package/skills/lit-typographic-motion/styles/terminalcore.json +182 -0
- package/skills/lit-typographic-motion/styles/tidal.json +187 -0
- package/skills/litresearch/SKILL.md +2 -0
- package/skills/managed-skill-manifest.json +517 -88
- package/skills/readme-studio/SKILL.md +1 -1
- package/skills/review-work/SKILL.md +2 -0
- package/skills/start-work/SKILL.md +8 -0
- package/skills/workflow-loop/SKILL.md +4 -0
- package/tools/check-pack-payload.mjs +5 -2
- package/tools/payload-substance-parity.json +4 -3
- package/tools/qa-cover-recipes.mjs +4 -3
- package/tools/version-manifests.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,44 @@ are tracked separately from this product history.
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
## 1.0.33 - 2026-10-28
|
|
9
|
+
|
|
10
|
+
- After `/start-work save-plan` saves an approved plan, typing `go` in the same session within 30 minutes starts the work. A `go` from another session, or later, is an ordinary word.
|
|
11
|
+
|
|
12
|
+
- A plan that names a folder outside the project needs a `Scope roots: <folder> (<actions>)` line. Saving the plan without one is refused with the exact line to add. When the work starts, each line becomes a permission for that run, so it no longer stops to ask about folders the plan already named.
|
|
13
|
+
|
|
14
|
+
- The status card shows other sessions more honestly. One other session is already enough for a row, working sessions come first, and a finished session shows `done` for one minute before it leaves. Each session keeps a small record in `.litopencode/liveness/`, so idle and ended come from the session itself instead of a five-minute guess. A session in a herdr pane is named after that pane.
|
|
15
|
+
|
|
16
|
+
- When a newer LitOpenCode is installed than the one this OpenCode start loaded, the card shows `restart to <version>` and one toast says the same. Nothing restarts on its own.
|
|
17
|
+
|
|
18
|
+
- The `lit-adhd` brief opens with three lines: done so far, doing now, next. Finished plans and completed runs count as done, plans older than seven days stay out, the next step never repeats a finished one, and the worktree's `HANDOFF.md` next item is used when nothing else is armed.
|
|
19
|
+
|
|
20
|
+
- The repository has a `TRADEMARK.md`: the code stays MIT, and the LitOpenCode and LitFamily names and artwork are kept for the official project.
|
|
21
|
+
|
|
22
|
+
## 1.0.32 - 2026-10-27
|
|
23
|
+
|
|
24
|
+
- `lit-hijack` takes the technique from someone else's published work (posts, articles, repos, PDFs, transcripts) and ports it into your own skill. It records each source's author, date and licence, keeps none of the wording, writes a spec, has a separate subagent build from that spec in its own git worktree, and checks that the new skill behaves differently before reporting what was taken. Use `lit hijack <url> into skills/<name>` or `/lit-hijack`.
|
|
25
|
+
|
|
26
|
+
- `lit-adhd` (also `lit-rewind`) picks the work back up after a break. It reads the earlier sessions of this worktree read-only and prints one brief: a badge per session, what is done and next, a roadmap and one recommended step that a bare `go` follows. Nothing in the brief shows a placeholder count, and secrets are redacted. The band suggests `lit adhd` after a 30-minute break and shows its colour look on every route that opens it.
|
|
27
|
+
|
|
28
|
+
- A lit discipline interrupted by another lit command now pauses and resumes with `lit continue` or `go`. Typed `start-work`, `lit approve` and `lit deny` drive a bounded run without pasted JSON.
|
|
29
|
+
|
|
30
|
+
- The status card shows parallel lanes (workflow frames, running subagents, other sessions here), a breathing `◆ YOUR TURN` while the session waits on you, and the five `review-work` lanes as they report. A subagent that is still working no longer reads as idle after five minutes.
|
|
31
|
+
|
|
32
|
+
- `lit-schematic` draws real equipment: P&IDs with ISA-5.1 tags, PFDs, journal apparatus figures and isometric cutaways, as editable SVG, PDF and 600 DPI PNG, checked by a QA script and a look at the render.
|
|
33
|
+
|
|
34
|
+
- `lit-pptx` has thirteen design directions, five of them new (computational brutalism, neo-brutalism, Bauhaus, riso, newsroom), all on one slide grid so changing the style never moves the content. Decks are richer by default, and `run.mjs render` turns a deck into PDF and page images through LibreOffice. A deck asked for by slide count and style alone now reaches the skill.
|
|
35
|
+
|
|
36
|
+
- `frontend-ui-ux` locks a house style, layout and tokens before it builds a page, and checks the rendered page against that lock. Diagrams and scientific figures are denser by default; ask for minimal and you get it.
|
|
37
|
+
|
|
38
|
+
- The design skills (`lit-pptx`, `lit-docx`, `frontend-ui-ux`, `lit-schematic`, `lit-diagram-drawer`, `readme-studio`, `lit-typographic-motion`) ask which look you want before they build, unless the prompt names one or says "you choose".
|
|
39
|
+
|
|
40
|
+
- `lit-typographic-motion` films take one of four house styles, check a storyboard before any frame is encoded, carry a story and the product's own images from a link, get a layered score and can use three.js or an optional Blender pass.
|
|
41
|
+
|
|
42
|
+
- Security fixes from an independent review: `lit-hijack` captures and motion asset fetches check every redirect hop for a public host, connect only to the address that check approved (no DNS rebinding), and stop reading at the size cap. GitHub tree links stay inside the clone, the redactors catch quoted-JSON and URL-encoded secrets, the status card drops terminal control sequences, and the brief file is replaced through a rename.
|
|
43
|
+
|
|
44
|
+
- The GitHub README has a "What you can make" gallery with real renders; those images stay out of the npm package.
|
|
45
|
+
|
|
8
46
|
## 1.0.31 - 2026-10-26
|
|
9
47
|
|
|
10
48
|
- The motion and README cover tools pick up upstream fixes in their pinned dependencies: `certifi` 2026.10.19 for motion audio, and newer `hono` and `fast-uri` in the HyperFrames and Remotion template lockfiles. A fresh setup installs these versions; nothing else about how the skills run changes.
|
package/README-Ko-KR.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
<p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.
|
|
1
|
+
<p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/assets/cover-motion-still.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/assets/cover-motion.webp" width="100%" alt="LitFamily 모션 커버: 일곱 로봇 패널이 차례로 켜지고, LitOpenCode 로봇의 눈과 테두리가 빛난 뒤 LITFAMILY와 KEEP THE WORK LIT. 문구가 밝아지는 영상" /></picture></p>
|
|
2
2
|
|
|
3
3
|
# LitOpenCode
|
|
4
4
|
|
|
5
5
|
**LitOpenCode는 OpenCode용 워크플로 플러그인입니다. 프롬프트에 `lit`만 붙이면 계획하고, 만들고, 확인하고, 기록까지 남겨서 다음 세션이 어디서 멈췄는지 바로 압니다.**
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
<a href="https://www.npmjs.com/package/@litfamily/litopencode"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.
|
|
8
|
+
<a href="https://www.npmjs.com/package/@litfamily/litopencode"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/assets/readme/badge-version.svg" alt="1.0.33" /></a>
|
|
9
9
|
<a href="https://www.npmjs.com/package/@litfamily/litopencode"><img src="https://img.shields.io/npm/dm/@litfamily/litopencode?label=downloads&color=D7F75B" alt="월간 npm 다운로드 수" /></a>
|
|
10
|
-
<a href="https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.
|
|
10
|
+
<a href="https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/assets/readme/badge-license.svg" alt="MIT 라이선스" /></a>
|
|
11
11
|
<a href="https://github.com/wjgoarxiv/litopencode"><img src="https://img.shields.io/github/stars/wjgoarxiv/litopencode?style=social" alt="GitHub 스타" /></a>
|
|
12
12
|
</p>
|
|
13
13
|
|
|
@@ -57,9 +57,9 @@ npm uninstall -g @litfamily/litopencode
|
|
|
57
57
|
## 더 보기
|
|
58
58
|
|
|
59
59
|
- [GitHub의 사용 안내](https://github.com/wjgoarxiv/litopencode/blob/main/docs/guide-Ko-KR.md): 설치 옵션, 자동 인수인계, 문제 해결, 제거
|
|
60
|
-
- [워크플로 상세 안내](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.
|
|
61
|
-
- [마이그레이션 안내](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.
|
|
62
|
-
- [LitFamily 허브](https://github.com/wjgoarxiv/litfamily) · [MIT 라이선스](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.
|
|
60
|
+
- [워크플로 상세 안내](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/reference-Ko-KR.md) · [English reference](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/reference.md)
|
|
61
|
+
- [마이그레이션 안내](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/migration.md) · [Changelog](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/CHANGELOG.md) · [개인정보와 네트워크 동작](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/privacy.md)
|
|
62
|
+
- [LitFamily 허브](https://github.com/wjgoarxiv/litfamily) · [MIT 라이선스](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/LICENSE) · [상표 정책](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/TRADEMARK.md) · [ASCII 글꼴 라이선스](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/assets/readme/JetBrainsMono-OFL.txt)
|
|
63
63
|
|
|
64
64
|
<details>
|
|
65
65
|
<summary>ASCII 로고 복사</summary>
|
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
<p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.
|
|
1
|
+
<p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/assets/cover-motion-still.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/assets/cover-motion.webp" width="100%" alt="LitFamily motion cover: seven armored robots power on one by one, the LitOpenCode robot wakes with glowing eyes and a lit frame, then LITFAMILY and KEEP THE WORK LIT. light up." /></picture></p>
|
|
2
2
|
|
|
3
3
|
# LitOpenCode
|
|
4
4
|
|
|
5
5
|
**LitOpenCode is a workflow plugin for OpenCode. Add `lit` to a prompt and the work gets planned, built, checked and written down, so the next session knows where you stopped.**
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
<a href="https://www.npmjs.com/package/@litfamily/litopencode"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.
|
|
8
|
+
<a href="https://www.npmjs.com/package/@litfamily/litopencode"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/assets/readme/badge-version.svg" alt="1.0.33" /></a>
|
|
9
9
|
<a href="https://www.npmjs.com/package/@litfamily/litopencode"><img src="https://img.shields.io/npm/dm/@litfamily/litopencode?label=downloads&color=D7F75B" alt="npm downloads per month" /></a>
|
|
10
|
-
<a href="https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.
|
|
10
|
+
<a href="https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/assets/readme/badge-license.svg" alt="MIT license" /></a>
|
|
11
11
|
<a href="https://github.com/wjgoarxiv/litopencode"><img src="https://img.shields.io/github/stars/wjgoarxiv/litopencode?style=social" alt="GitHub stars" /></a>
|
|
12
12
|
</p>
|
|
13
13
|
|
|
@@ -57,9 +57,9 @@ npm uninstall -g @litfamily/litopencode
|
|
|
57
57
|
## More
|
|
58
58
|
|
|
59
59
|
- [Guide on GitHub](https://github.com/wjgoarxiv/litopencode/blob/main/docs/guide.md): install options, automatic handoff, troubleshooting and removal.
|
|
60
|
-
- [Workflow reference](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.
|
|
61
|
-
- [Migration notes](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.
|
|
62
|
-
- [LitFamily hub](https://github.com/wjgoarxiv/litfamily) · [MIT license](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.
|
|
60
|
+
- [Workflow reference](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/reference.md)
|
|
61
|
+
- [Migration notes](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/migration.md) · [Changelog](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/CHANGELOG.md) · [Privacy and network behavior](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/privacy.md)
|
|
62
|
+
- [LitFamily hub](https://github.com/wjgoarxiv/litfamily) · [MIT license](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/LICENSE) · [Trademark policy](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/TRADEMARK.md) · [ASCII font license](https://cdn.jsdelivr.net/npm/@litfamily/litopencode@1.0.33/docs/assets/readme/JetBrainsMono-OFL.txt)
|
|
63
63
|
|
|
64
64
|
<details>
|
|
65
65
|
<summary>Copy ASCII logo</summary>
|
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 **LitOpenCode**
|
|
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
|
+
LitOpenCode maintainers made or endorse it.
|
|
9
|
+
- You can say in plain text that your project is "based on LitOpenCode" or "a fork of LitOpenCode".
|
|
10
|
+
- Unchanged copies, such as mirrors and package caches, may keep the name.
|
|
11
|
+
|
|
12
|
+
Questions: open an issue at https://github.com/wjgoarxiv/litopencode/issues.
|
|
@@ -165,7 +165,11 @@ decisions that cannot be derived from files, commands, docs, or current config.
|
|
|
165
165
|
When the user approves the plan, hand execution to lit-implement through /start-work
|
|
166
166
|
command so OpenCode can switch agents. Do not call the start-work tool from lit-plan:
|
|
167
167
|
tool execution cannot switch the active OpenCode agent and may leave work running in
|
|
168
|
-
planning mode. Tell the user to run /start-work instead.
|
|
168
|
+
planning mode. Tell the user to run /start-work instead. Once /start-work save-plan has saved the
|
|
169
|
+
approved plan, the user may instead type \`go\` within 30 minutes in that same session to start it;
|
|
170
|
+
say so in one line. When a checklist item names an absolute path outside the project, put a
|
|
171
|
+
\`Scope roots: <folder> (read|write|execute)\` line near the top of the plan; save-plan refuses
|
|
172
|
+
an uncovered outside folder and start-work grants each line. Do not start implementation yourself. After implementation is complete,
|
|
169
173
|
use /review-work or the review-work tool to check behavior, tests, docs, safety, and
|
|
170
174
|
package readiness.
|
|
171
175
|
|
package/dist/activation-probe.js
CHANGED
|
@@ -5,6 +5,7 @@ export function activationDiscipline(skillId) {
|
|
|
5
5
|
case "lit-work":
|
|
6
6
|
case "workflow-loop": return "lit-loop";
|
|
7
7
|
case "lit-research": return "litresearch";
|
|
8
|
+
case "lit-rewind": return "lit-adhd";
|
|
8
9
|
case "lit-goal":
|
|
9
10
|
case "durable-litgoal": return "litgoal";
|
|
10
11
|
case "lit-korean":
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type StaticSkillPromptId = "workflow-loop" | "litgoal" | "lit-plan" | "start-work" | "review-work" | "litresearch" | "lit-init" | "lit-crucible" | "lit-brainstorm" | "lit-burnoff-file" | "lit-fetch" | "refactor" | "lit-burnoff" | "lit-code" | "debugging" | "lit-commit" | "lsp" | "lsp-setup" | "rules" | "deep-interview" | "structural-search" | "browser-drive" | "lit-recap" | "lit-comprehend" | "lit-humanizer" | "lit-handoff" | "lit-scientific-visualization" | "frontend-ui-ux" | "visual-qa";
|
|
1
|
+
export type StaticSkillPromptId = "workflow-loop" | "litgoal" | "lit-plan" | "start-work" | "review-work" | "litresearch" | "lit-init" | "lit-crucible" | "lit-brainstorm" | "lit-hijack" | "lit-adhd" | "lit-burnoff-file" | "lit-fetch" | "refactor" | "lit-burnoff" | "lit-code" | "debugging" | "lit-commit" | "lsp" | "lsp-setup" | "rules" | "deep-interview" | "structural-search" | "browser-drive" | "lit-recap" | "lit-comprehend" | "lit-humanizer" | "lit-handoff" | "lit-scientific-visualization" | "frontend-ui-ux" | "visual-qa";
|
|
2
2
|
export declare const litActivationBanner: string;
|
|
3
3
|
export declare function readStaticSkillBody(skillId: StaticSkillPromptId): string;
|
|
4
4
|
export declare function readManagedSkillAsset(skillId: "lit-handoff" | "lit-scientific-visualization", relativePath: string): string;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type FrameProgress } from "./workflow-stack.ts";
|
|
1
2
|
import type { ChatActivationMode } from "./activation-routing.ts";
|
|
2
3
|
export type ActivationMemory = {
|
|
3
4
|
readonly active: (sessionID: string) => ChatActivationMode | undefined;
|
|
@@ -5,6 +6,25 @@ export type ActivationMemory = {
|
|
|
5
6
|
readonly forget: (sessionID: string) => void;
|
|
6
7
|
};
|
|
7
8
|
export declare function createActivationMemory(): ActivationMemory;
|
|
9
|
+
/**
|
|
10
|
+
* Where a spine discipline stands, read from the records the band reads: the bounded work run's plan
|
|
11
|
+
* checklist, else the goal ledger's criteria. A total that no record knows stays absent.
|
|
12
|
+
*/
|
|
13
|
+
export declare function spineProgress(projectRoot: string, sessionID: string, skill: string): Promise<FrameProgress>;
|
|
14
|
+
/**
|
|
15
|
+
* Remembers an activation. A spine skill (lit-loop, lit-plan, start-work, lit-task) starts a fresh
|
|
16
|
+
* stack; a side skill started over a running spine pauses it, keeping its stage and counts, and the
|
|
17
|
+
* returned line tells the model and the user how to come back.
|
|
18
|
+
*/
|
|
19
|
+
export declare function recordActivation(input: {
|
|
20
|
+
readonly memory: ActivationMemory;
|
|
21
|
+
readonly projectRoot: string;
|
|
22
|
+
readonly sessionID: string;
|
|
23
|
+
readonly mode: ChatActivationMode;
|
|
24
|
+
readonly now?: number;
|
|
25
|
+
}): Promise<{
|
|
26
|
+
readonly line?: string;
|
|
27
|
+
}>;
|
|
8
28
|
export type ReentryDecision = {
|
|
9
29
|
readonly kind: "full";
|
|
10
30
|
} | {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
2
3
|
import { resolveLatestDurablePlan } from "./durable-plan.js";
|
|
3
4
|
import { activationDiscipline } from "./activation-probe.js";
|
|
4
5
|
import { createRuntimePaths } from "./state.js";
|
|
6
|
+
import { planChecklist, readActiveGoal, readWorkState } from "./tui/mission-model.js";
|
|
7
|
+
import { emptyStack, isSpineSkill, pushSide, readStack, resumeSpine, startSpine, writeStack } from "./workflow-stack.js";
|
|
5
8
|
// What a second `lit ...` in the same session does. The first lit of a session, a different
|
|
6
9
|
// discipline, `lit new` and `lit restart` all send the full activation. The same discipline sends a
|
|
7
10
|
// short note instead, and a bare `lit` over saved work resumes it. Session identity is the host's
|
|
@@ -18,6 +21,101 @@ export function createActivationMemory() {
|
|
|
18
21
|
forget: (sessionID) => { active.delete(sessionID); }
|
|
19
22
|
};
|
|
20
23
|
}
|
|
24
|
+
// A paused spine older than this belongs to earlier work, so a later side skill does not claim to pause it.
|
|
25
|
+
const spineStaleMs = 6 * 60 * 60 * 1000;
|
|
26
|
+
const progressByteLimit = 1024 * 1024;
|
|
27
|
+
async function readSmallJson(file) {
|
|
28
|
+
try {
|
|
29
|
+
const stat = await fs.lstat(file);
|
|
30
|
+
if (!stat.isFile() || stat.size > progressByteLimit)
|
|
31
|
+
return undefined;
|
|
32
|
+
return JSON.parse(await fs.readFile(file, "utf8"));
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Where a spine discipline stands, read from the records the band reads: the bounded work run's plan
|
|
40
|
+
* checklist, else the goal ledger's criteria. A total that no record knows stays absent.
|
|
41
|
+
*/
|
|
42
|
+
export async function spineProgress(projectRoot, sessionID, skill) {
|
|
43
|
+
const paths = createRuntimePaths(projectRoot);
|
|
44
|
+
const work = readWorkState(await readSmallJson(paths.lifecycleStateFile), sessionID);
|
|
45
|
+
let counts;
|
|
46
|
+
if (work !== undefined && work.planPath !== "" && path.isAbsolute(work.planPath) && !path.relative(paths.projectRoot, work.planPath).startsWith("..")) {
|
|
47
|
+
try {
|
|
48
|
+
const stat = await fs.lstat(work.planPath);
|
|
49
|
+
const checklist = stat.isFile() && stat.size <= progressByteLimit ? planChecklist(await fs.readFile(work.planPath, "utf8")) : undefined;
|
|
50
|
+
if (checklist !== undefined)
|
|
51
|
+
counts = { done: checklist.done, total: checklist.total };
|
|
52
|
+
}
|
|
53
|
+
catch { // no-excuse-ok: catch -- an unreadable plan leaves the count to the goal ledger.
|
|
54
|
+
// The next source in the chain answers.
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const goal = readActiveGoal(await readSmallJson(paths.goalsFile));
|
|
58
|
+
if (counts === undefined && goal !== undefined && goal.criteria.length > 0) {
|
|
59
|
+
counts = { done: goal.criteria.filter((criterion) => criterion.status === "pass").length, total: goal.criteria.length };
|
|
60
|
+
}
|
|
61
|
+
const phase = skill === "lit-plan" ? "plan" : work !== undefined || counts !== undefined ? "work" : undefined;
|
|
62
|
+
return { ...(phase === undefined ? {} : { phase }), ...(counts ?? {}) };
|
|
63
|
+
}
|
|
64
|
+
function where(frame) {
|
|
65
|
+
if (frame.phase === undefined)
|
|
66
|
+
return "";
|
|
67
|
+
return frame.done !== undefined && frame.total !== undefined ? ` at ${frame.phase} ${frame.done}/${frame.total}` : ` at ${frame.phase}`;
|
|
68
|
+
}
|
|
69
|
+
async function freshStack(projectRoot, sessionID, now) {
|
|
70
|
+
const stack = await readStack(projectRoot, sessionID);
|
|
71
|
+
return stack !== undefined && now - stack.updatedAt <= spineStaleMs ? stack : emptyStack(sessionID);
|
|
72
|
+
}
|
|
73
|
+
async function persist(projectRoot, stack) {
|
|
74
|
+
try {
|
|
75
|
+
await writeStack(projectRoot, stack);
|
|
76
|
+
}
|
|
77
|
+
catch { // no-excuse-ok: catch -- the stack is a convenience record; activation must not fail on it.
|
|
78
|
+
// The in-memory activation still answers this turn.
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Remembers an activation. A spine skill (lit-loop, lit-plan, start-work, lit-task) starts a fresh
|
|
83
|
+
* stack; a side skill started over a running spine pauses it, keeping its stage and counts, and the
|
|
84
|
+
* returned line tells the model and the user how to come back.
|
|
85
|
+
*/
|
|
86
|
+
export async function recordActivation(input) {
|
|
87
|
+
const now = input.now ?? Date.now();
|
|
88
|
+
let stack = await freshStack(input.projectRoot, input.sessionID, now);
|
|
89
|
+
if (isSpineSkill(input.mode)) {
|
|
90
|
+
input.memory.remember(input.sessionID, input.mode);
|
|
91
|
+
await persist(input.projectRoot, startSpine(stack, input.mode, now));
|
|
92
|
+
return {};
|
|
93
|
+
}
|
|
94
|
+
const remembered = input.memory.active(input.sessionID);
|
|
95
|
+
if (!stack.frames.some((frame) => isSpineSkill(frame.skill)) && remembered !== undefined && isSpineSkill(remembered)) {
|
|
96
|
+
stack = startSpine(stack, remembered, now);
|
|
97
|
+
}
|
|
98
|
+
const spine = stack.frames.find((frame) => isSpineSkill(frame.skill));
|
|
99
|
+
if (spine === undefined) {
|
|
100
|
+
input.memory.remember(input.sessionID, input.mode);
|
|
101
|
+
// A lone side discipline leaves no file of its own; only a stack that already exists is updated.
|
|
102
|
+
if (stack.frames.length > 0)
|
|
103
|
+
await persist(input.projectRoot, pushSide(stack, input.mode, now, undefined));
|
|
104
|
+
return {};
|
|
105
|
+
}
|
|
106
|
+
const progress = await spineProgress(input.projectRoot, input.sessionID, spine.skill);
|
|
107
|
+
const next = pushSide(stack, input.mode, now, progress);
|
|
108
|
+
await persist(input.projectRoot, next);
|
|
109
|
+
const paused = next.frames[0];
|
|
110
|
+
return { line: `LitOpenCode: ${activationDiscipline(paused.skill)} is paused${where(paused)}. Say lit continue to return to it.` };
|
|
111
|
+
}
|
|
112
|
+
function resumeNote(frame) {
|
|
113
|
+
const discipline = activationDiscipline(frame.skill);
|
|
114
|
+
const gate = frame.skill === "lit-plan"
|
|
115
|
+
? " Stay planning-only: no edits or mutating commands until the user approves the plan and runs /start-work."
|
|
116
|
+
: "";
|
|
117
|
+
return `LitOpenCode: back in ${discipline}${where(frame)}, where it paused. Keeping its criteria, plan and run state; the user's message above is the next instruction. Do not start a new brief, plan or goal.${gate}`;
|
|
118
|
+
}
|
|
21
119
|
export function continueNote(mode) {
|
|
22
120
|
const discipline = activationDiscipline(mode);
|
|
23
121
|
const gate = mode === "lit-plan"
|
|
@@ -51,6 +149,17 @@ async function resumableWork(projectRoot, now) {
|
|
|
51
149
|
export async function decideReentry(input) {
|
|
52
150
|
if (restartRequest.test(input.text))
|
|
53
151
|
return { kind: "full" };
|
|
152
|
+
const now = input.now ?? Date.now();
|
|
153
|
+
const stack = await freshStack(input.projectRoot, input.sessionID, now);
|
|
154
|
+
const paused = stack.frames.find((frame) => isSpineSkill(frame.skill) && frame.status === "paused");
|
|
155
|
+
if (paused !== undefined && (bareLitOrContinue.test(input.text) || input.mode === paused.skill)) {
|
|
156
|
+
const resumed = resumeSpine(stack, now).resumed;
|
|
157
|
+
if (resumed !== undefined) {
|
|
158
|
+
await persist(input.projectRoot, resumeSpine(stack, now).stack);
|
|
159
|
+
input.memory.remember(input.sessionID, resumed.skill);
|
|
160
|
+
return { kind: "continue", mode: resumed.skill, text: resumeNote(resumed) };
|
|
161
|
+
}
|
|
162
|
+
}
|
|
54
163
|
const active = input.memory.active(input.sessionID);
|
|
55
164
|
if (active !== undefined && continuableModes.has(active)) {
|
|
56
165
|
if (bareLitOrContinue.test(input.text))
|
|
@@ -60,7 +169,7 @@ export async function decideReentry(input) {
|
|
|
60
169
|
}
|
|
61
170
|
if (input.mode !== "lit-task" || !bareLitOrContinue.test(input.text))
|
|
62
171
|
return { kind: "full" };
|
|
63
|
-
const work = await resumableWork(input.projectRoot,
|
|
172
|
+
const work = await resumableWork(input.projectRoot, now);
|
|
64
173
|
if (work !== undefined) {
|
|
65
174
|
return {
|
|
66
175
|
kind: "resume",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type WorkflowFamilyMode } from "./workflow-families.ts";
|
|
2
|
-
export type ChatActivationMode = WorkflowFamilyMode | "lit-task" | "lit-loop" | "lit-plan" | "start-work" | "review-work" | "lit-research" | "litgoal" | "lit-init" | "lit-crucible" | "lit-brainstorm" | "lit-burnoff-file" | "lit-fetch" | "lit-humanizer" | "refactor" | "lit-burnoff" | "lit-code" | "debugging" | "lit-commit" | "lsp" | "lsp-setup" | "deep-interview" | "structural-search" | "browser-drive" | "frontend-ui-ux" | "visual-qa" | "lit-recap" | "lit-comprehend" | "lit-handoff" | "lit-scientific-visualization";
|
|
2
|
+
export type ChatActivationMode = WorkflowFamilyMode | "lit-task" | "lit-loop" | "lit-plan" | "start-work" | "review-work" | "lit-research" | "litgoal" | "lit-init" | "lit-crucible" | "lit-brainstorm" | "lit-hijack" | "lit-adhd" | "lit-burnoff-file" | "lit-fetch" | "lit-humanizer" | "refactor" | "lit-burnoff" | "lit-code" | "debugging" | "lit-commit" | "lsp" | "lsp-setup" | "deep-interview" | "structural-search" | "browser-drive" | "frontend-ui-ux" | "visual-qa" | "lit-recap" | "lit-comprehend" | "lit-handoff" | "lit-scientific-visualization";
|
|
3
3
|
export declare function hasMotionVideoIntent(raw: string): boolean;
|
|
4
|
+
export declare function hasSchematicRequest(raw: string): boolean;
|
|
4
5
|
export declare function typeLedCue(raw: string): string | undefined;
|
|
5
6
|
export declare function containsStandaloneLitTrigger(text: string): boolean;
|
|
6
7
|
export declare function endsWithStandaloneLitInvocation(raw: string): boolean;
|
|
@@ -7,7 +7,7 @@ import { litHandoffPromptInjection, scientificVisualizationPromptInjection } fro
|
|
|
7
7
|
import { litLoopPromptInjection, litPlanPromptInjection, litTaskPromptInjection } from "./activation-primary-prompts.js";
|
|
8
8
|
import { interfaceWorkHandoff } from "./interface-handoff.js";
|
|
9
9
|
import { detectWorkflowFamilyChatMode, isWorkflowFamilyMode, workflowFamilyPrompt } from "./workflow-families.js";
|
|
10
|
-
import { comprehendPromptInjection, debuggingPromptInjection, deepInterviewPromptInjection, frontendUiUxPromptInjection, gitMasterPromptInjection, litBrainstormPromptInjection, litCruciblePromptInjection, initDeepPromptInjection, litGoalPromptInjection, litRecapPromptInjection, litResearchPromptInjection, lspPromptInjection, lspSetupPromptInjection, litCodePromptInjection, refactorPromptInjection, removeAiSlopsPromptInjection, reviewModeForcedNote, reviewWorkPromptInjection, browserDrivePromptInjection, structuralSearchPromptInjection, startWorkChatPromptInjection, visualQaPromptInjection, litBurnoffFilePromptInjection, litFetchPromptInjection, litHumanizerPromptInjection } from "./activation-workflow-prompts.js";
|
|
10
|
+
import { comprehendPromptInjection, debuggingPromptInjection, deepInterviewPromptInjection, frontendUiUxPromptInjection, gitMasterPromptInjection, litBrainstormPromptInjection, litHijackPromptInjection, litAdhdPromptInjection, litCruciblePromptInjection, initDeepPromptInjection, litGoalPromptInjection, litRecapPromptInjection, litResearchPromptInjection, lspPromptInjection, lspSetupPromptInjection, litCodePromptInjection, refactorPromptInjection, removeAiSlopsPromptInjection, reviewModeForcedNote, reviewWorkPromptInjection, browserDrivePromptInjection, structuralSearchPromptInjection, startWorkChatPromptInjection, visualQaPromptInjection, litBurnoffFilePromptInjection, litFetchPromptInjection, litHumanizerPromptInjection } from "./activation-workflow-prompts.js";
|
|
11
11
|
const compoundWordBoundary = /^[A-Za-z0-9_-]$/;
|
|
12
12
|
const recapWordCharacter = /^[A-Za-z0-9_\u{AC00}-\u{D7A3}\u{1100}-\u{11FF}\u{3130}-\u{318F}]$/u;
|
|
13
13
|
const recapBoundedWords = Object.freeze(["recap", "litrecap", "리캡"]);
|
|
@@ -58,16 +58,48 @@ const structuralVerb = /(?<![a-z])(?:find|locate|search|rewrite|replace|migrate|
|
|
|
58
58
|
const structuralShape = /(?<![a-z])(?:call ?sites?|callsites?|declarations?|import statements?|imports|(?:function|method) signatures?|syntax shapes?|syntax trees?|ast)(?![a-z])/u;
|
|
59
59
|
const uiIntentVerb = /(?<![a-z])(?:design|redesign|restyle|revamp|polish|lay\s?out|mock\s?up|build|create|make|implement|add|wire up)(?![a-z])|디자인|만들|제작|개편|다듬|꾸미|구현|추가/u;
|
|
60
60
|
const uiIntentNoun = /(?<![a-z])(?:ui|ux|user interface|screen|page|layout|dashboard|modal|navbar|sidebar|stylesheet|css|design system|landing page|front[- ]?end|component|button|card|form|checkout|notification center|comparison table)(?![a-z])|화면|페이지|레이아웃|대시보드|컴포넌트|모달|사이드바|내비게이션|네비게이션|스타일시트|디자인 시스템|랜딩 페이지|프런트엔드|프론트엔드|버튼|카드|폼|체크아웃/u;
|
|
61
|
+
// An English build request ("build a landing page for ...") reaches the interface route through the
|
|
62
|
+
// generic verbs. A target that is not an interface (a hosted BI tool, a backend, an endpoint, a CLI,
|
|
63
|
+
// a schema, a container image) named before the interface noun takes it back out; a design verb
|
|
64
|
+
// ("design", "restyle", "polish" ...) is always an interface request. Hangul is left as it was.
|
|
65
|
+
const uiDesignVerb = /(?<![a-z])(?:design|redesign|restyle|revamp|polish|lay\s?out|mock\s?up)(?![a-z])|디자인|개편|다듬|꾸미/u;
|
|
66
|
+
const uiNonInterfaceTarget = /(?<![a-z])(?:grafana|kibana|datadog|metabase|looker|tableau|power\s?bi|back\s?end|api|endpoint|docker(?:\s?file|\s+image)?|cli|migration|schema)(?![a-z])/u;
|
|
67
|
+
function hasUiBuildIntent(raw) {
|
|
68
|
+
const verbs = raw.replace(/(?<![a-z])make\s+sure(?![a-z])/gu, " ");
|
|
69
|
+
if (!uiIntentVerb.test(verbs))
|
|
70
|
+
return false;
|
|
71
|
+
if (uiDesignVerb.test(verbs))
|
|
72
|
+
return true;
|
|
73
|
+
const noun = uiIntentNoun.exec(raw);
|
|
74
|
+
const target = uiNonInterfaceTarget.exec(raw);
|
|
75
|
+
return !(noun && target && target.index < noun.index);
|
|
76
|
+
}
|
|
61
77
|
const uiPolishCue = /\b(?:polish|tighten up|clean up the styling)\b|다듬/u;
|
|
62
78
|
const uiAuditCue = /\b(?:audit|review this page read.only|just check|don't fix)\b|점검|검토만/u;
|
|
63
79
|
const uiHardenCue = /\b(?:harden|stress.test|hold up under|robust to)\b|튼튼하게|견고하게/u;
|
|
64
80
|
const uiReadOnlyCue = /\b(?:read.only|don't (?:touch|change|fix)|just (?:check|tell))\b|수정은 하지|건드리지 말|고치지는 말|목록만/u;
|
|
65
81
|
const uiBuildCue = /\b(?:redesign|new layout|brand.new|add|implement|build|create|make|wire up)\b|새로|추가|구현|다시 짜|재구성/u;
|
|
66
82
|
const diagramCreationIntent = /^\s*(?:lit[,:]?\s+)?(?:please\s+)?(?:create|draw|make|design|render|build)\b[^.!?\n]*\b(?:diagrams?|flowcharts?|architecture maps?)\b|^\s*(?:lit\s+)?[^.!?\n]*(?:다이어그램|흐름도|구성도|구조도)[^.!?\n]*(?:그려|만들어|제작해)/mu;
|
|
83
|
+
// lit-schematic: a drawing of real hardware (P&ID, PFD, apparatus figure, isometric cutaway). A strong
|
|
84
|
+
// noun names a drawing by itself; a weak one (schematic, isometric, apparatus) also needs a drawing or
|
|
85
|
+
// making verb and no web-interface noun. A chart of data, a question about a drawing, a review of one,
|
|
86
|
+
// or a report or deck about one is not a drawing request, and a whole interface that merely shows a
|
|
87
|
+
// drawing belongs to frontend-ui-ux unless the user asked to draw. Hangul terms are bare substrings.
|
|
88
|
+
const schematicStrongNoun = /(?<![a-z])p\s?&\s?i\s?ds?(?![a-z])|(?<![a-z])pfds?(?![a-z])|(?<![a-z])bfds?(?![a-z])|piping\s+(?:and|&)\s+instrumentation|process\s+flow\s+(?:diagram|sheet)s?|block\s+flow\s+diagrams?|(?<![a-z])plot\s+plans?(?![a-z])|equipment\s+layouts?|experimental\s+(?:set\s?up|apparatus)|(?<![a-z])cut\s?aways?(?![a-z])|컷어웨이|배관\s?계장도|계장도|공정\s?흐름도|공정도|모식도|장치도|실험\s?장치|피앤아이디|배치도|계통도|단면도/u;
|
|
89
|
+
const schematicWeakNoun = /(?<![a-z])schematics?(?![a-z])|(?<![a-z])isometric(?![a-z])|(?<![a-z])apparatus(?![a-z])|사시도|개략도|아이소메트릭|도면/u;
|
|
90
|
+
const schematicChartNoun = /차트|그래프|(?<![a-z])(?:charts?|graphs?|plots?(?!\s+plans?(?![a-z])))(?![a-z])/u;
|
|
91
|
+
const schematicDrawVerb = /(?<![a-z])(?:draw|drawing|drew|sketch|sketching|illustrate|illustrating|render|rendering|redraw)(?![a-z])|그려|그리|그림|도식|작도/u;
|
|
92
|
+
const schematicMakeVerb = /(?<![a-z])(?:make|making|create|creating|design|designing|build|lay\s?out)(?![a-z])|만들|만드/u;
|
|
93
|
+
const schematicInterfaceNoun = /(?<![a-z])(?:dashboards?|landing\s?pages?|web\s?pages?|websites?|homepages?|web\s?apps?|apps?|screens?|admin\s?(?:panel|console)|user\s?interface|ui)(?![a-z])|대시보드|웹사이트|랜딩|페이지|화면|앱/u;
|
|
94
|
+
const schematicInquiryCue = /(?<![a-z])(?:explain|how (?:do|to|can|does)|what is|what's|review|critique|audit|summari[sz]e|proofread)(?![a-z])|설명|알려|리뷰|검토|점검|요약|뭐야|무엇/u;
|
|
67
95
|
// "turn X into a deck/report" also authors an Office file. Within the clause, a dot followed by a
|
|
68
96
|
// non-space (notes.md, q3.v2.csv) is part of a file name and does not end the sentence.
|
|
69
97
|
const officeAuthoringVerb = /(?<![a-z])(?:make|create|write|draft|prepare|produce|generate|convert|edit|build)(?![a-z])|(?<![a-z])turn(?=(?:[^.!?\n]|\.(?=\S))*?(?<![a-z])into(?![a-z])(?:[^.!?\n]|\.(?=\S))*?(?<![a-z])(?:slides?|decks?|presentations?|pptx?|reports?|documents?|docx|word)(?![a-z]))|만들|작성|써줘|제작|변환|편집/u;
|
|
70
98
|
const reportNoun = /(?<![a-z])(?:reports?|documents?|docx|word)(?![a-z])|보고서|리포트|기획서|제안서|문서|워드/u;
|
|
99
|
+
// A slide count beside a deck noun ("덱 10장", "a 10-slide launch deck") asks for the deck without a making verb.
|
|
100
|
+
// The noun is narrower than slidesNoun: a bare 발표 beside "10장" is a talk or a photo set, not a deck.
|
|
101
|
+
const slideCount = /\d+\s?장|(?<![a-z\d])\d+[\s-]?slides?(?![a-z])/u;
|
|
102
|
+
const countedDeckNoun = /(?<![a-z])(?:slides?|decks?|presentations?|pptx?)(?![a-z])|발표자료|슬라이드|피피티|덱/u;
|
|
71
103
|
const slidesNoun = /(?<![a-z])(?:slides?|decks?|presentations?|pptx?)(?![a-z])|발표자료|발표|슬라이드|피피티|덱/u;
|
|
72
104
|
// A deliverable the user asked to receive as Markdown or plain text ("saved as report.md", "in Markdown",
|
|
73
105
|
// "as plain text"). An input file such as "turn notes.md into slides" is not one. A named Office or PDF
|
|
@@ -101,6 +133,21 @@ export function hasMotionVideoIntent(raw) {
|
|
|
101
133
|
return false;
|
|
102
134
|
return true;
|
|
103
135
|
}
|
|
136
|
+
export function hasSchematicRequest(raw) {
|
|
137
|
+
const strong = schematicStrongNoun.test(raw);
|
|
138
|
+
if (!strong && !schematicWeakNoun.test(raw))
|
|
139
|
+
return false;
|
|
140
|
+
if (schematicInquiryCue.test(raw) || schematicChartNoun.test(raw))
|
|
141
|
+
return false;
|
|
142
|
+
const draws = schematicDrawVerb.test(raw);
|
|
143
|
+
if (!strong && !(draws || schematicMakeVerb.test(raw)))
|
|
144
|
+
return false;
|
|
145
|
+
if (!strong && uiContainer.test(raw))
|
|
146
|
+
return false;
|
|
147
|
+
if (schematicInterfaceNoun.test(raw) && !draws)
|
|
148
|
+
return false;
|
|
149
|
+
return draws || !(reportNoun.test(raw) || slidesNoun.test(raw));
|
|
150
|
+
}
|
|
104
151
|
// The route context names the installed render and gate scripts by absolute path. The installed
|
|
105
152
|
// managed tree wins; the package's own copy is the fallback when no install is found. Plugin code
|
|
106
153
|
// runs inside OpenCode's Bun host, so the command is `node <path>`, never process.execPath.
|
|
@@ -140,8 +187,8 @@ function motionRouteContext(original) {
|
|
|
140
187
|
const gate = `node ${shellQuote(installedMotionScript("gate.mjs"))}`;
|
|
141
188
|
const cue = typeLedCue(original.toLowerCase());
|
|
142
189
|
return `
|
|
143
|
-
This is a film request. After the workspace check, load lit-typographic-motion with OpenCode's native skill tool and write treatment.json in the film's output directory before any render. Path rule: the type path when the words themselves are the film, at 16:9; the stage path for every other film and every 9:16 film.
|
|
144
|
-
Commands: ${render} (film, stills, stage, cover, sound, look, gate); ${gate} (<dir>, --cover <file>, --done <dir>).${cue ? `\ntype-led cue found: ${cue}` : ""}
|
|
190
|
+
This is a film request. After the workspace check, load lit-typographic-motion with OpenCode's native skill tool and write treatment.json in the film's output directory before any render. Path rule: the type path when the words themselves are the film, at 16:9; the stage path for every other film and every 9:16 film. ${designChoiceFirst} One call covers path, style, format and register. Ask nothing else; label every invented subject, line and default, and any generated sound, in the reply. Hand-encoded films are not the deliverable. Open the stills with the read tool and record each look. Finish when --done exits 0, else say what it reports open. A README cover or banner loop takes cover mode (references/cover.md).
|
|
191
|
+
Commands: ${render} (film, stills, stage, scaffold, styles, assets, blender, cover, sound, look, gate); ${gate} (<dir>, --cover <file>, --done <dir>, --out <dir>).${cue ? `\ntype-led cue found: ${cue}` : ""}
|
|
145
192
|
`;
|
|
146
193
|
}
|
|
147
194
|
const litSlashCommands = Object.freeze([
|
|
@@ -162,6 +209,9 @@ const litSlashCommands = Object.freeze([
|
|
|
162
209
|
"lit-init",
|
|
163
210
|
"lit-crucible",
|
|
164
211
|
"lit-brainstorm",
|
|
212
|
+
"lit-hijack",
|
|
213
|
+
"lit-adhd",
|
|
214
|
+
"lit-rewind",
|
|
165
215
|
"refactor",
|
|
166
216
|
"lit-burnoff",
|
|
167
217
|
"lit-code",
|
|
@@ -250,6 +300,22 @@ function startsBrainstormRoute(raw) {
|
|
|
250
300
|
const token = standaloneLitToken.exec(raw);
|
|
251
301
|
return token !== null && brainstormRouteAfterLit.test(raw.slice(token.index + token[0].length));
|
|
252
302
|
}
|
|
303
|
+
// The hijack route follows the brainstorm rule: the word right after the FIRST standalone `lit` token.
|
|
304
|
+
// `lit debug the session hijack` and `how do attackers hijack a session cookie` stay with their own
|
|
305
|
+
// routes because the route word is not adjacent to `lit`. The Hangul forms attach particles and verb
|
|
306
|
+
// endings directly (하이재킹해줘, 하이잭해서), so they carry no trailing boundary.
|
|
307
|
+
const hijackRouteAfterLit = new RegExp("^(?:\\s+hijack(?:ing)?|-hijack)(?![\\w/\\\\-]|\\.\\w)|^\\s+(?:하이재킹|하이잭)", "u");
|
|
308
|
+
function startsHijackRoute(raw) {
|
|
309
|
+
const token = standaloneLitToken.exec(raw);
|
|
310
|
+
return token !== null && hijackRouteAfterLit.test(raw.slice(token.index + token[0].length));
|
|
311
|
+
}
|
|
312
|
+
// `lit adhd` and `lit rewind` follow the same rule: the route word is the word right after the first `lit`.
|
|
313
|
+
// `lit debug the adhd screening form` and `how to rewind a git branch` keep their own routes.
|
|
314
|
+
const adhdRouteAfterLit = /^(?:\s+(?:adhd|rewind)|-(?:adhd|rewind))(?![\w/\\-]|\.\w)/iu;
|
|
315
|
+
function startsAdhdRoute(raw) {
|
|
316
|
+
const token = standaloneLitToken.exec(raw);
|
|
317
|
+
return token !== null && adhdRouteAfterLit.test(raw.slice(token.index + token[0].length));
|
|
318
|
+
}
|
|
253
319
|
function startsWithStartWorkInvocation(raw, normalized) {
|
|
254
320
|
const rawStart = raw.trimStart();
|
|
255
321
|
if (/^start-work(?:$|[\s,.:;!?])/u.test(rawStart))
|
|
@@ -288,6 +354,13 @@ export function detectChatActivationMode(text, agent) {
|
|
|
288
354
|
// "refactor", "plan" or "dashboard" in the same sentence cannot steal the open question.
|
|
289
355
|
if (startsBrainstormRoute(raw))
|
|
290
356
|
return "lit-brainstorm";
|
|
357
|
+
// Same precedence for `lit hijack ...`: porting a published technique outranks the plan, review and
|
|
358
|
+
// research words that its sources and targets usually contain.
|
|
359
|
+
if (startsHijackRoute(raw))
|
|
360
|
+
return "lit-hijack";
|
|
361
|
+
// Coming back to earlier work outranks the plan and research words a brief request may contain.
|
|
362
|
+
if (startsAdhdRoute(raw))
|
|
363
|
+
return "lit-adhd";
|
|
291
364
|
const workflowFamilyMode = detectWorkflowFamilyChatMode(raw);
|
|
292
365
|
if (workflowFamilyMode !== undefined)
|
|
293
366
|
return workflowFamilyMode;
|
|
@@ -360,7 +433,8 @@ export function detectChatActivationMode(text, agent) {
|
|
|
360
433
|
return undefined;
|
|
361
434
|
if (!motion && hasLitTrigger(raw) && uiContainer.test(raw) && insertVideo.test(raw) && motionVideoNoun.test(raw))
|
|
362
435
|
return "frontend-ui-ux";
|
|
363
|
-
|
|
436
|
+
const schematic = hasLitTrigger(raw) && hasSchematicRequest(raw);
|
|
437
|
+
if (!motion && !schematic && uiIntentNoun.test(raw) && (hasUiBuildIntent(raw) || uiAuditCue.test(raw) || uiHardenCue.test(raw)))
|
|
364
438
|
return "frontend-ui-ux";
|
|
365
439
|
if (!hasLitTrigger(raw))
|
|
366
440
|
return undefined;
|
|
@@ -377,8 +451,11 @@ export function detectChatActivationMode(text, agent) {
|
|
|
377
451
|
return undefined;
|
|
378
452
|
if (agent === "lit-plan")
|
|
379
453
|
return "lit-plan";
|
|
454
|
+
if (schematic)
|
|
455
|
+
return "lit-task";
|
|
380
456
|
return containsLitRoute(words, "loop") || explicitlyRequestsLongWork(raw) ? "lit-loop" : "lit-task";
|
|
381
457
|
}
|
|
458
|
+
const designChoiceFirst = `Before building, unless the prompt names the theme, style or preset or says "you choose", ask the user to pick it with OpenCode's question tool: two to four options, the recommended one first. In a non-interactive run with no question tool, take the recommended option and say so in one line.`;
|
|
382
459
|
export function promptForChatActivationMode(mode, triggerText = "") {
|
|
383
460
|
const prompt = canonicalChatPrompt(mode);
|
|
384
461
|
const raw = rawTriggerText(triggerText);
|
|
@@ -386,31 +463,39 @@ export function promptForChatActivationMode(mode, triggerText = "") {
|
|
|
386
463
|
if (mode === "frontend-ui-ux") {
|
|
387
464
|
const uiMode = frontendUiUxModeForPrompt(raw);
|
|
388
465
|
targetedPrompt += `\nSelected interface mode: ${uiMode}. Follow references/production.md for that mode's edit boundary and probe gate.`;
|
|
466
|
+
if (uiMode === "build")
|
|
467
|
+
targetedPrompt += `\nNew page or screen: ${designChoiceFirst} Then, before any markup, lock the look with scripts/design-lock.mjs (one house style, one layout family, one signature moment; existing brand tokens win) and build only from the generated ui/tokens.css, ui/components.css and layout starter, as references/house-styles.md describes. Rich density is the default; calm only when the request asks for minimal or calm. The probe also checks the lock: fix HIGH findings, answer its LOOK questions on the screenshots, and report a missing capture as BLOCKED.`;
|
|
389
468
|
}
|
|
390
469
|
if (mode === "review-work")
|
|
391
470
|
targetedPrompt += reviewModeForcedNote(forcedReviewMode(routeWords(normalizedTriggerText(triggerText))) ?? "");
|
|
392
471
|
if (mode === "lit-loop" && needsInterfaceHandoff(raw))
|
|
393
472
|
targetedPrompt += `\nInterface hand-off for this request: ${interfaceWorkHandoff}`;
|
|
394
|
-
|
|
473
|
+
const schematic = mode === "lit-task" && hasSchematicRequest(raw);
|
|
474
|
+
if (schematic) {
|
|
475
|
+
targetedPrompt = targetedPrompt.replace("</lit-task-mode>", `
|
|
476
|
+
After the workspace check, use OpenCode's native skill tool to load lit-schematic before drawing the requested physical schematic: a P&ID, PFD, apparatus figure or isometric cutaway. Resolve its scripts and references from the skill location returned by OpenCode. ${designChoiceFirst} Write the process truth and parts list first, build with the skill's kit, run its qa.mjs until QA PASS, render the PNG and open it. Under lit, when data is missing, draw a realistic example without asking and label every invented value in the reply. A cutaway asked as an animation is drawn there as a silent loop; a titled or narrated film goes to lit-typographic-motion. If the skill is unavailable, report that limit instead of claiming it ran.
|
|
477
|
+
</lit-task-mode>`);
|
|
478
|
+
}
|
|
479
|
+
if (!schematic && (mode === "lit-task" || mode === "lit-loop") && hasMotionVideoIntent(raw)) {
|
|
395
480
|
return mode === "lit-task"
|
|
396
481
|
? targetedPrompt.replace("</lit-task-mode>", `${motionRouteContext(triggerText)}</lit-task-mode>`)
|
|
397
482
|
: `${targetedPrompt}\nFilm request:${motionRouteContext(triggerText)}`;
|
|
398
483
|
}
|
|
399
|
-
if (mode === "lit-task" && diagramCreationIntent.test(raw)) {
|
|
484
|
+
if (mode === "lit-task" && !schematic && diagramCreationIntent.test(raw)) {
|
|
400
485
|
targetedPrompt = targetedPrompt.replace("</lit-task-mode>", `
|
|
401
|
-
After the workspace check, use OpenCode's native skill tool to load lit-diagram-drawer before authoring the requested conceptual diagram. This is the one narrowly relevant skill for this bounded task. Resolve resources from the skill location returned by OpenCode
|
|
486
|
+
After the workspace check, use OpenCode's native skill tool to load lit-diagram-drawer before authoring the requested conceptual diagram. This is the one narrowly relevant skill for this bounded task. Resolve resources from the skill location returned by OpenCode. ${designChoiceFirst} Follow its verification and export steps, and inspect the final PNG. If the skill is unavailable, report that limit instead of claiming it ran.
|
|
402
487
|
</lit-task-mode>`);
|
|
403
488
|
}
|
|
404
|
-
if (mode === "lit-task" && officeAuthoringVerb.test(raw) && markdownDeliverable.test(raw) && !officeFileFormat.test(raw) && (reportNoun.test(raw) || slidesNoun.test(raw))) {
|
|
489
|
+
if (mode === "lit-task" && !schematic && officeAuthoringVerb.test(raw) && markdownDeliverable.test(raw) && !officeFileFormat.test(raw) && (reportNoun.test(raw) || slidesNoun.test(raw))) {
|
|
405
490
|
targetedPrompt = targetedPrompt.replace("</lit-task-mode>", `
|
|
406
491
|
The requested deliverable is a Markdown or plain-text file, not an Office file. Write each named file as ordinary Markdown that a reader opens directly: headings, paragraphs, lists and tables, with no YAML front matter, no \`:::\` directive blocks and no tonality, layout or title-treatment keys. Do not build a DOCX or PPTX and do not load lit-docx or lit-pptx for it; their Markdown is converter source and belongs only beside a file that skill renders.
|
|
407
492
|
</lit-task-mode>`);
|
|
408
493
|
}
|
|
409
|
-
else if (mode === "lit-task" && officeAuthoringVerb.test(raw)) {
|
|
494
|
+
else if (mode === "lit-task" && !schematic && (officeAuthoringVerb.test(raw) || (slideCount.test(raw) && countedDeckNoun.test(raw)))) {
|
|
410
495
|
const skills = [reportNoun.test(raw) ? "lit-docx" : undefined, slidesNoun.test(raw) ? "lit-pptx" : undefined].filter(Boolean);
|
|
411
496
|
if (skills.length > 0)
|
|
412
497
|
targetedPrompt = targetedPrompt.replace("</lit-task-mode>", `
|
|
413
|
-
After the workspace check, use OpenCode's native skill tool to load ${skills.join(" and ")} before drafting the requested Office deliverable. Resolve scripts and templates from the installed skill location. Under lit, create the editable ${skills.includes("lit-docx") ? "DOCX" : ""}${skills.length === 2 ? " and " : ""}${skills.includes("lit-pptx") ? "PPTX" : ""} with its Markdown source; unless the user selected a tonality, profile or template,
|
|
498
|
+
After the workspace check, use OpenCode's native skill tool to load ${skills.join(" and ")} before drafting the requested Office deliverable. Resolve scripts and templates from the installed skill location. Under lit, create the editable ${skills.includes("lit-docx") ? "DOCX" : ""}${skills.length === 2 ? " and " : ""}${skills.includes("lit-pptx") ? "PPTX" : ""} with its Markdown source; unless the user selected a tonality, profile or template, rank its design direction (tonality) with two alternatives. ${designChoiceFirst} If facts are missing, complete a realistic example without asking or leaving placeholders; mark invented names and figures as sample assumptions in the file and reply. Run its QA and inspect rendered pages or slides. Report missing optional host tools honestly. If a skill is unavailable, report that limit instead of claiming it ran.
|
|
414
499
|
</lit-task-mode>`);
|
|
415
500
|
}
|
|
416
501
|
const alias = Object.keys(renamedSkillAliases).find((id) => id === mode && renamedSkillAliases[id].some((name) => containsCompoundBoundedWord(raw, name)));
|
|
@@ -451,7 +536,7 @@ export function frontendUiUxModeForPrompt(text) {
|
|
|
451
536
|
function needsInterfaceHandoff(raw) {
|
|
452
537
|
if (/\b(?:cli|backend|api|server)[- ]only\b/u.test(raw))
|
|
453
538
|
return false;
|
|
454
|
-
return
|
|
539
|
+
return hasUiBuildIntent(raw) && (uiIntentNoun.test(raw) || /\b(?:web ?app|website)\b|웹앱|웹사이트|홈페이지/u.test(raw));
|
|
455
540
|
}
|
|
456
541
|
function canonicalChatPrompt(mode) {
|
|
457
542
|
if (isWorkflowFamilyMode(mode))
|
|
@@ -483,6 +568,10 @@ function canonicalChatPrompt(mode) {
|
|
|
483
568
|
return litCruciblePromptInjection;
|
|
484
569
|
case "lit-brainstorm":
|
|
485
570
|
return litBrainstormPromptInjection;
|
|
571
|
+
case "lit-hijack":
|
|
572
|
+
return litHijackPromptInjection;
|
|
573
|
+
case "lit-adhd":
|
|
574
|
+
return litAdhdPromptInjection;
|
|
486
575
|
case "refactor":
|
|
487
576
|
return refactorPromptInjection;
|
|
488
577
|
case "lit-burnoff":
|
|
@@ -5,6 +5,10 @@ export declare const litResearchPromptInjection: string;
|
|
|
5
5
|
export declare const litGoalPromptInjection: string;
|
|
6
6
|
export declare const litCruciblePromptInjection: string;
|
|
7
7
|
export declare const litBrainstormPromptInjection: string;
|
|
8
|
+
export declare const litHijackPromptInjection: string;
|
|
9
|
+
export declare const litAdhdPromptInjection: string;
|
|
10
|
+
/** The session id the collector needs for --session; the activation prompt itself is the same for every session. */
|
|
11
|
+
export declare function adhdSessionNote(sessionID: string): string;
|
|
8
12
|
export declare const initDeepPromptInjection: string;
|
|
9
13
|
export declare const refactorPromptInjection: string;
|
|
10
14
|
export declare const removeAiSlopsPromptInjection: string;
|