Organize skill script support modules

This commit is contained in:
Paul Bakaus
2026-06-08 16:58:55 -07:00
parent 972f5b18be
commit 325aeaf239
49 changed files with 70 additions and 66 deletions
+1 -1
View File
@@ -46,7 +46,7 @@ Use ESM, semicolons, and the existing two-space indentation style in JS, HTML, a
Tests use Buns test runner plus Nodes built-in `--test`. Name tests `*.test.js` or `*.test.mjs` and place new fixtures near the behavior they cover, usually under `tests/fixtures/`. Prefer targeted test runs while iterating, then finish with `bun run test`. If you change generated outputs or provider transforms, verify both source parsing and at least one affected provider path in `dist/`.
For changes to `skill/scripts/live-*.{mjs,js}`, also run `bun run test:live-e2e` (kept out of the default suite because it does real `npm install` per fixture and boots framework dev servers). Scope to one fixture with `IMPECCABLE_E2E_ONLY=<fixture-name>` while iterating; pass `IMPECCABLE_E2E_DEBUG=1` for page-DOM and dev-server-log dumps on failure. Schema and authoring guide for new fixtures live in `tests/framework-fixtures/README.md`.
For changes to `skill/scripts/live-*.{mjs,js}` or `skill/scripts/live/**`, also run `bun run test:live-e2e` (kept out of the default suite because it does real `npm install` per fixture and boots framework dev servers). Scope to one fixture with `IMPECCABLE_E2E_ONLY=<fixture-name>` while iterating; pass `IMPECCABLE_E2E_DEBUG=1` for page-DOM and dev-server-log dumps on failure. Schema and authoring guide for new fixtures live in `tests/framework-fixtures/README.md`.
Set `IMPECCABLE_E2E_AGENT=llm` to swap the deterministic fake agent for an API-backed one (`tests/live-e2e/agents/llm-agent.mjs`). Claude Haiku 4.5 is the primary path whenever `ANTHROPIC_API_KEY` is set. DeepSeek V4 Flash is the secondary cheap fallback when only `DEEPSEEK_API_KEY` is set, and can be forced with `IMPECCABLE_E2E_LLM_PROVIDER=deepseek` or `bun run test:live-e2e -- --llm-provider=deepseek`; override either model via `IMPECCABLE_E2E_LLM_MODEL` or `--llm-model=<model>`. Tests skip cleanly when the selected provider key is unset. This path hits the API — use it for verification, not CI.
+1 -1
View File
@@ -159,7 +159,7 @@ IMPECCABLE_E2E_DEBUG=1 bun run test:live-e2e # dump page DOM + de
**One-time setup**: `npx playwright install chromium` (the suite uses a specific Chromium build keyed to the bundled Playwright version).
**Kept out of the default `bun run test`** because (a) it does real `npm install` per fixture, (b) it boots framework dev servers, (c) wall time is ~2 minutes, and (d) it requires Playwright's browser cache. Run it locally before shipping changes to anything in `skill/scripts/live-*.{mjs,js}`.
**Kept out of the default `bun run test`** because (a) it does real `npm install` per fixture, (b) it boots framework dev servers, (c) wall time is ~2 minutes, and (d) it requires Playwright's browser cache. Run it locally before shipping changes to anything in `skill/scripts/live-*.{mjs,js}` or `skill/scripts/live/**`.
The agent is pluggable via a one-method interface in `tests/live-e2e/agent.mjs`: `generateVariants(event, context) → { scopedCss, variants[] }`. The default fake agent emits canned variants that exercise all three param kinds (`range`, `steps`, `toggle`). The orchestrator (wrap, write, accept, carbonize) is agent-agnostic.
+8 -4
View File
@@ -92,7 +92,7 @@ export const SUITES = {
description: 'Fast live-mode unit and local-server integration tests, excluding full browser fixture sweeps.',
triggers: [
...COMMON_INFRA_PATTERNS,
/^skill\/(reference\/live\.md|scripts\/(detect-csp|is-generated|live|live-|modern-screenshot|pin|palette))/,
/^skill\/(reference\/live\.md|scripts\/(detect-csp|lib\/is-generated|live\/|live|live-|modern-screenshot|pin|palette))/,
/^tests\/live-/,
/^tests\/live-e2e\/(agent|agents\/llm-agent|cli-options|preactions|session|steer|ui)\.mjs$/,
/^tests\/live-e2e\/agent-insert\.test\.mjs$/,
@@ -138,7 +138,9 @@ export const SUITES = {
...COMMON_INFRA_PATTERNS,
/^tests\/framework-fixtures/,
/^tests\/framework-fixtures\.test\.mjs$/,
/^skill\/scripts\/(detect-csp|is-generated|live-inject|live-sveltekit-adapter|live-wrap)\.mjs$/,
/^skill\/scripts\/(detect-csp|live-inject|live-wrap)\.mjs$/,
/^skill\/scripts\/lib\/is-generated\.mjs$/,
/^skill\/scripts\/live\/sveltekit-adapter\.mjs$/,
],
commands: [
{
@@ -197,7 +199,8 @@ export const SUITES = {
needsPlaywright: true,
triggers: [
...COMMON_INFRA_PATTERNS,
/^skill\/scripts\/(live-accept|live-browser|live-server|live-sveltekit-adapter|live-wrap)\.mjs$/,
/^skill\/scripts\/(live-accept|live-browser|live-server|live-wrap)\.mjs$/,
/^skill\/scripts\/live\/sveltekit-adapter\.mjs$/,
/^tests\/live-e2e-accept-cleanup-regression\.test\.mjs$/,
/^tests\/live-e2e\//,
],
@@ -242,7 +245,8 @@ export const SUITES = {
needsPlaywright: true,
triggers: [
...COMMON_INFRA_PATTERNS,
/^skill\/scripts\/(live-sveltekit-adapter|live-svelte-component|live-server|live-wrap)\.mjs$/,
/^skill\/scripts\/(live-server|live-wrap)\.mjs$/,
/^skill\/scripts\/live\/(sveltekit-adapter|svelte-component)\.mjs$/,
/^tests\/framework-fixtures\/vite8-sveltekit-stateful\//,
/^tests\/live-svelte-adapter-deepseek\.test\.mjs$/,
],
+2 -2
View File
@@ -4,9 +4,9 @@
// lands on the `pick` verb.
//
// Values/labels/icons come from the same canonical source the real picker uses
// (skill/scripts/live-vocabulary.mjs), imported at build time, so the demo and
// (skill/scripts/live/vocabulary.mjs), imported at build time, so the demo and
// the product never drift.
import { LIVE_COMMANDS } from '../../skill/scripts/live-vocabulary.mjs';
import { LIVE_COMMANDS } from '../../skill/scripts/live/vocabulary.mjs';
interface Props {
pick: string;
+1 -1
View File
@@ -22,7 +22,7 @@ import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { execFileSync } from 'node:child_process';
import { loadContext, extractRegister } from './context.mjs';
import { getCritiqueDir } from './impeccable-paths.mjs';
import { getCritiqueDir } from './lib/impeccable-paths.mjs';
/** Is there code here at all, or just context files / an empty repo? */
function hasCode(cwd) {
+1 -1
View File
@@ -28,7 +28,7 @@
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { getCritiqueDir } from './impeccable-paths.mjs';
import { getCritiqueDir } from './lib/impeccable-paths.mjs';
const SLUG_MAX = 50;
+3 -3
View File
@@ -15,14 +15,14 @@
import fs from 'node:fs';
import path from 'node:path';
import { isGeneratedFile } from './is-generated.mjs';
import { readBuffer as readManualEditsBuffer, writeBuffer as writeManualEditsBuffer } from './live-manual-edits-buffer.mjs';
import { isGeneratedFile } from './lib/is-generated.mjs';
import { readBuffer as readManualEditsBuffer, writeBuffer as writeManualEditsBuffer } from './live/manual-edits-buffer.mjs';
import {
applyDeferredSvelteComponentAccepts,
findSvelteComponentManifest,
inlineSvelteComponentAccept,
removeSvelteComponentSession,
} from './live-svelte-component.mjs';
} from './live/svelte-component.mjs';
const EXTENSIONS = ['.html', '.jsx', '.tsx', '.vue', '.svelte', '.astro'];
+2 -2
View File
@@ -82,7 +82,7 @@
]);
// Command vocabulary (values + labels + icons) comes from the canonical source,
// skill/scripts/live-vocabulary.mjs, which live-server.mjs serializes into
// skill/scripts/live/vocabulary.mjs, which live-server.mjs serializes into
// window.__IMPECCABLE_VOCAB__ when it serves /live.js (same injection path as
// the token/port above, so it is always present here). The icons stack above
// each chip label and recolor to C.brand when selected (strokes use
@@ -1216,7 +1216,7 @@
: (focused ? BP.accentSoft : BP.hairline);
}
// Insert mode helpers (mirrors skill/scripts/live-insert-ui.mjs)
// Insert mode helpers (mirrors skill/scripts/live/insert-ui.mjs)
function detectInsertAxisFromStyle(style) {
const display = style?.display || 'block';
+2 -2
View File
@@ -16,8 +16,8 @@
*/
import { buildManualEditEvidence } from './live-manual-edit-evidence.mjs';
import { readBuffer, readBufferStrict, writeBuffer, countByPage } from './live-manual-edits-buffer.mjs';
import { isGeneratedFile } from './is-generated.mjs';
import { readBuffer, readBufferStrict, writeBuffer, countByPage } from './live/manual-edits-buffer.mjs';
import { isGeneratedFile } from './lib/is-generated.mjs';
import {
runCopyEditBatchAgent,
runCopyEditPostApplyChecks,
+2 -2
View File
@@ -3,8 +3,8 @@
* Canonical durable completion acknowledgement for Impeccable live sessions.
*/
import { createLiveSessionStore } from './live-session-store.mjs';
import { readLiveServerInfo } from './impeccable-paths.mjs';
import { createLiveSessionStore } from './live/session-store.mjs';
import { readLiveServerInfo } from './lib/impeccable-paths.mjs';
function parseArgs(argv) {
const out = { status: 'complete' };
+1 -1
View File
@@ -16,7 +16,7 @@
* Output JSON: { discarded: N, entries: [...discardedEntries], totalCount: N }
*/
import { readBuffer, removeEntries, truncateBuffer } from './live-manual-edits-buffer.mjs';
import { readBuffer, removeEntries, truncateBuffer } from './live/manual-edits-buffer.mjs';
function argVal(args, name) {
const prefix = name + '=';
+2 -2
View File
@@ -16,12 +16,12 @@
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { resolveLiveConfigPath } from './impeccable-paths.mjs';
import { resolveLiveConfigPath } from './lib/impeccable-paths.mjs';
import {
applySvelteKitLiveAdapter,
detectSvelteKitProject,
removeSvelteKitLiveAdapter,
} from './live-sveltekit-adapter.mjs';
} from './live/sveltekit-adapter.mjs';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const CONFIG_PATH = resolveLiveConfigPath({ cwd: process.cwd(), scriptsDir: __dirname });
+2 -2
View File
@@ -9,7 +9,7 @@
import fs from 'node:fs';
import path from 'node:path';
import { isGeneratedFile } from './is-generated.mjs';
import { isGeneratedFile } from './lib/is-generated.mjs';
import {
buildSearchQueries,
findElement,
@@ -25,7 +25,7 @@ import {
buildSvelteComponentCssAuthoring,
scaffoldSvelteComponentInsertSession,
shouldUseSvelteComponentInjection,
} from './live-svelte-component.mjs';
} from './live/svelte-component.mjs';
const INSERT_POSITIONS = new Set(['before', 'after']);
+2 -2
View File
@@ -10,8 +10,8 @@
import fs from 'node:fs';
import path from 'node:path';
import { isGeneratedFile } from './is-generated.mjs';
import { readBuffer, getBufferPath } from './live-manual-edits-buffer.mjs';
import { isGeneratedFile } from './lib/is-generated.mjs';
import { readBuffer, getBufferPath } from './live/manual-edits-buffer.mjs';
const EVIDENCE_VERSION = 1;
const TEXT_EXTENSIONS = new Set(['.html', '.jsx', '.tsx', '.vue', '.svelte', '.astro', '.js', '.mjs', '.ts']);
+2 -2
View File
@@ -12,8 +12,8 @@
import { execFileSync } from 'node:child_process';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { completionAckForAcceptResult, completionTypeForAcceptResult } from './live-completion.mjs';
import { readLiveServerInfo } from './impeccable-paths.mjs';
import { completionAckForAcceptResult, completionTypeForAcceptResult } from './live/completion.mjs';
import { readLiveServerInfo } from './lib/impeccable-paths.mjs';
// Node's built-in fetch (undici under the hood) enforces a 300s headers
// timeout that can't be lowered per-request. We cap each request below
+1 -1
View File
@@ -3,7 +3,7 @@
* Recover the next agent action from the durable live-session journal.
*/
import { createLiveSessionStore } from './live-session-store.mjs';
import { createLiveSessionStore } from './live/session-store.mjs';
function manualApplyReplyCommand(eventOrId = 'EVENT_ID') {
const id = typeof eventOrId === 'string' ? eventOrId : eventOrId?.id || 'EVENT_ID';
+7 -7
View File
@@ -20,11 +20,11 @@ import fs from 'node:fs';
import path from 'node:path';
import net from 'node:net';
import { fileURLToPath } from 'node:url';
import { parseDesignMd } from './design-parser.mjs';
import { parseDesignMd } from './lib/design-parser.mjs';
import { resolveContextDir } from './context.mjs';
import { createLiveSessionStore } from './live-session-store.mjs';
import { validateEvent } from './live-event-validation.mjs';
import { LIVE_COMMANDS } from './live-vocabulary.mjs';
import { createLiveSessionStore } from './live/session-store.mjs';
import { validateEvent } from './live/event-validation.mjs';
import { LIVE_COMMANDS } from './live/vocabulary.mjs';
import {
getDesignSidecarPath,
getLiveDir,
@@ -33,20 +33,20 @@ import {
removeLiveServerInfo,
resolveDesignSidecarPath,
writeLiveServerInfo,
} from './impeccable-paths.mjs';
} from './lib/impeccable-paths.mjs';
import {
countByPage as countPendingByPage,
readBuffer as readManualEditsBuffer,
removeEntries as removeManualEditEntries,
stageEntry as stageManualEditEntry,
truncateBuffer as truncateManualEditsBuffer,
} from './live-manual-edits-buffer.mjs';
} from './live/manual-edits-buffer.mjs';
import { buildManualEditEvidence } from './live-manual-edit-evidence.mjs';
import { commitManualEdits } from './live-commit-manual-edits.mjs';
import {
applyDeferredSvelteComponentAccepts,
removeAllSvelteComponentSessions,
} from './live-svelte-component.mjs';
} from './live/svelte-component.mjs';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
// PRODUCT.md / DESIGN.md live wherever context.mjs resolves. The generated
+2 -2
View File
@@ -3,8 +3,8 @@
* Print durable recovery status for Impeccable live sessions.
*/
import { createLiveSessionStore } from './live-session-store.mjs';
import { readLiveServerInfo } from './impeccable-paths.mjs';
import { createLiveSessionStore } from './live/session-store.mjs';
import { readLiveServerInfo } from './lib/impeccable-paths.mjs';
import { manualApplyResumeHint } from './live-resume.mjs';
function readServerInfo() {
+3 -3
View File
@@ -13,13 +13,13 @@
import fs from 'node:fs';
import path from 'node:path';
import { isGeneratedFile } from './is-generated.mjs';
import { readBuffer as readManualEditsBuffer } from './live-manual-edits-buffer.mjs';
import { isGeneratedFile } from './lib/is-generated.mjs';
import { readBuffer as readManualEditsBuffer } from './live/manual-edits-buffer.mjs';
import {
buildSvelteComponentCssAuthoring,
scaffoldSvelteComponentSession,
shouldUseSvelteComponentInjection,
} from './live-svelte-component.mjs';
} from './live/svelte-component.mjs';
const EXTENSIONS = ['.html', '.jsx', '.tsx', '.vue', '.svelte', '.astro'];
+1 -1
View File
@@ -23,7 +23,7 @@ import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { loadContext } from './context.mjs';
import { resolveFiles } from './live-inject.mjs';
import { readLiveServerInfo } from './impeccable-paths.mjs';
import { readLiveServerInfo } from './lib/impeccable-paths.mjs';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -3,12 +3,12 @@
* Extracted for unit testing (insert mode rules).
*/
import { canCreateInsert } from './live-insert-ui.mjs';
import { canCreateInsert } from './insert-ui.mjs';
// The accepted visual action values come from the canonical vocabulary so the
// validator, the picker UI, and the marketing demo never drift. Imported (not
// just re-exported) so it is also in scope for the validators below.
import { VISUAL_ACTIONS } from './live-vocabulary.mjs';
import { VISUAL_ACTIONS } from './vocabulary.mjs';
export { VISUAL_ACTIONS };
const ID_PATTERN = /^[0-9a-f]{8}$/;
@@ -12,7 +12,7 @@
import fs from 'node:fs';
import path from 'node:path';
import { getLiveDir } from './impeccable-paths.mjs';
import { getLiveDir } from '../lib/impeccable-paths.mjs';
const BUFFER_VERSION = 1;
const BUFFER_FILENAME = 'pending-manual-edits.json';
@@ -1,6 +1,6 @@
import fs from 'node:fs';
import path from 'node:path';
import { getLegacyLiveSessionsDir, getLiveSessionsDir } from './impeccable-paths.mjs';
import { getLegacyLiveSessionsDir, getLiveSessionsDir } from '../lib/impeccable-paths.mjs';
const COMPLETED_PHASES = new Set(['completed', 'discarded']);
@@ -4,7 +4,7 @@
* so the icon recolors when its chip is selected.
*
* Single source of truth, consumed by:
* - skill/scripts/live-event-validation.mjs re-exports VISUAL_ACTIONS.
* - skill/scripts/live/event-validation.mjs re-exports VISUAL_ACTIONS.
* - skill/scripts/live-browser.js the real picker. It is served raw and
* injected as an IIFE, so it cannot import this at runtime; live-server.mjs
* serializes LIVE_COMMANDS into window.__IMPECCABLE_VOCAB__ alongside the
+1 -1
View File
@@ -5,7 +5,7 @@
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { parseDesignMd } from '../skill/scripts/design-parser.mjs';
import { parseDesignMd } from '../skill/scripts/lib/design-parser.mjs';
describe('parseDesignMd frontmatter branch', () => {
it('returns null frontmatter when the file has no YAML header', () => {
+1 -1
View File
@@ -17,7 +17,7 @@ import { tmpdir } from 'node:os';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { isGeneratedFile } from '../skill/scripts/is-generated.mjs';
import { isGeneratedFile } from '../skill/scripts/lib/is-generated.mjs';
import { detectCsp } from '../skill/scripts/detect-csp.mjs';
const __dirname = dirname(fileURLToPath(import.meta.url));
+1 -1
View File
@@ -1,6 +1,6 @@
# Framework fixtures
Representative project shapes for exercising live mode against different framework conventions. Each fixture is a small directory tree that the test harness copies into a temp git repo, then drives `live-inject.mjs`, `live-wrap.mjs`, `live-accept.mjs`, and `is-generated.mjs` against.
Representative project shapes for exercising live mode against different framework conventions. Each fixture is a small directory tree that the test harness copies into a temp git repo, then drives `live-inject.mjs`, `live-wrap.mjs`, `live-accept.mjs`, and `lib/is-generated.mjs` against.
Fixtures can also opt into a **runtime E2E** pass that actually installs dependencies, boots the framework dev server, and drives a Playwright browser to verify the live handshake. See the `runtime` block below.
+1 -1
View File
@@ -19,7 +19,7 @@ import {
readLiveServerInfo,
resolveDesignSidecarPath,
resolveLiveConfigPath,
} from '../skill/scripts/impeccable-paths.mjs';
} from '../skill/scripts/lib/impeccable-paths.mjs';
describe('impeccable project paths', () => {
let tmp;
+1 -1
View File
@@ -3,7 +3,7 @@ import assert from 'node:assert';
import fs from 'node:fs';
import path from 'node:path';
import os from 'node:os';
import { writeBuffer, readBuffer } from '../skill/scripts/live-manual-edits-buffer.mjs';
import { writeBuffer, readBuffer } from '../skill/scripts/live/manual-edits-buffer.mjs';
import { scrubManualEditsAgainstOriginalBlock } from '../skill/scripts/live-accept.mjs';
let tmpDir;
+1 -1
View File
@@ -5,7 +5,7 @@ import path from 'node:path';
import os from 'node:os';
import { execFileSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { writeBuffer, readBuffer } from '../skill/scripts/live-manual-edits-buffer.mjs';
import { writeBuffer, readBuffer } from '../skill/scripts/live/manual-edits-buffer.mjs';
import { buildManualEditEvidence } from '../skill/scripts/live-manual-edit-evidence.mjs';
import { commitManualEdits } from '../skill/scripts/live-commit-manual-edits.mjs';
import {
+1 -1
View File
@@ -4,7 +4,7 @@ import assert from 'node:assert/strict';
import {
completionAckForAcceptResult,
completionTypeForAcceptResult,
} from '../skill/scripts/live-completion.mjs';
} from '../skill/scripts/live/completion.mjs';
describe('live completion type classification', () => {
it('treats generated-file fallback accept as normal agent handoff, not error', () => {
+1 -1
View File
@@ -5,7 +5,7 @@ import path from 'node:path';
import os from 'node:os';
import { execFileSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { writeBuffer, readBuffer } from '../skill/scripts/live-manual-edits-buffer.mjs';
import { writeBuffer, readBuffer } from '../skill/scripts/live/manual-edits-buffer.mjs';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const REPO_ROOT = path.resolve(__dirname, '..');
+1 -1
View File
@@ -26,7 +26,7 @@ import { readFileSync, readdirSync } from 'node:fs';
import { join } from 'node:path';
import { execFile } from 'node:child_process';
import { promisify } from 'node:util';
import { completionTypeForAcceptResult } from '../../skill/scripts/live-completion.mjs';
import { completionTypeForAcceptResult } from '../../skill/scripts/live/completion.mjs';
const execFileP = promisify(execFile);
+1 -1
View File
@@ -5,7 +5,7 @@
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { validateEvent } from '../skill/scripts/live-event-validation.mjs';
import { validateEvent } from '../skill/scripts/live/event-validation.mjs';
const VALID_ID = 'a1b2c3d4';
+1 -1
View File
@@ -30,7 +30,7 @@ import {
resolveInsertSessionAnchor,
buildInsertPlaceholderSnapshot,
findInsertAnchorInDom,
} from '../skill/scripts/live-insert-ui.mjs';
} from '../skill/scripts/live/insert-ui.mjs';
describe('detectInsertAxisFromStyle', () => {
it('maps flex row and grid multi-column to row axis', () => {
+1 -1
View File
@@ -12,7 +12,7 @@ import {
countByPage,
truncateBuffer,
getBufferPath,
} from '../skill/scripts/live-manual-edits-buffer.mjs';
} from '../skill/scripts/live/manual-edits-buffer.mjs';
let tmpDir;
+1 -1
View File
@@ -9,7 +9,7 @@ import { mkdtempSync, readFileSync, rmSync } from 'node:fs';
import { join } from 'node:path';
import { spawn } from 'node:child_process';
import { tmpdir } from 'node:os';
import { getLiveServerPath } from '../skill/scripts/impeccable-paths.mjs';
import { getLiveServerPath } from '../skill/scripts/lib/impeccable-paths.mjs';
import { postReply } from '../skill/scripts/live-poll.mjs';
const REPO_ROOT = process.cwd();
+1 -1
View File
@@ -4,7 +4,7 @@ import { mkdtempSync, rmSync } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { execFileSync } from 'node:child_process';
import { createLiveSessionStore } from '../skill/scripts/live-session-store.mjs';
import { createLiveSessionStore } from '../skill/scripts/live/session-store.mjs';
const REPO_ROOT = process.cwd();
const STATUS_SCRIPT = join(REPO_ROOT, 'skill/scripts/live-status.mjs');
+2 -2
View File
@@ -14,7 +14,7 @@ import {
getLiveDir,
getLiveServerPath,
getLiveSessionsDir,
} from '../skill/scripts/impeccable-paths.mjs';
} from '../skill/scripts/lib/impeccable-paths.mjs';
const REPO_ROOT = process.cwd();
const SERVER_SCRIPT = join(REPO_ROOT, 'skill/scripts/live-server.mjs');
@@ -162,7 +162,7 @@ describe('live-server integration', () => {
// live-browser.js builds its action picker from window.__IMPECCABLE_VOCAB__
// rather than an inline copy, so the server must serialize the canonical
// vocabulary into /live.js (next to the token/port).
const { LIVE_COMMANDS } = await import('../skill/scripts/live-vocabulary.mjs');
const { LIVE_COMMANDS } = await import('../skill/scripts/live/vocabulary.mjs');
const body = await (await fetch(`http://localhost:${server.port}/live.js`)).text();
assert.match(body, /window\.__IMPECCABLE_VOCAB__\s*=/);
const injected = JSON.parse(body.match(/window\.__IMPECCABLE_VOCAB__\s*=\s*(\[.*?\]);/s)[1]);
+2 -2
View File
@@ -9,12 +9,12 @@ import { mkdirSync, mkdtempSync, rmSync, appendFileSync, readFileSync } from 'no
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { createLiveSessionStore } from '../skill/scripts/live-session-store.mjs';
import { createLiveSessionStore } from '../skill/scripts/live/session-store.mjs';
import {
getLegacyLiveSessionsDir,
getLiveAnnotationsDir,
getLiveSessionsDir,
} from '../skill/scripts/impeccable-paths.mjs';
} from '../skill/scripts/lib/impeccable-paths.mjs';
describe('live-session-store', () => {
let tmp;
+1 -1
View File
@@ -5,7 +5,7 @@ import path from 'node:path';
import os from 'node:os';
import { execFileSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { writeBuffer } from '../skill/scripts/live-manual-edits-buffer.mjs';
import { writeBuffer } from '../skill/scripts/live/manual-edits-buffer.mjs';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const REPO_ROOT = path.resolve(__dirname, '..');