@wrongstack/tools 0.284.1 → 0.286.0
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/README.md +19 -0
- package/dist/_concurrency.d.ts +16 -0
- package/dist/_concurrency.d.ts.map +1 -0
- package/dist/_danger-detect.d.ts +54 -0
- package/dist/_danger-detect.d.ts.map +1 -0
- package/dist/_edit-match.d.ts +86 -0
- package/dist/_edit-match.d.ts.map +1 -0
- package/dist/_env.d.ts +6 -0
- package/dist/_env.d.ts.map +1 -0
- package/dist/_fetch-guard.d.ts +31 -0
- package/dist/_fetch-guard.d.ts.map +1 -0
- package/dist/_output-spool.d.ts +38 -0
- package/dist/_output-spool.d.ts.map +1 -0
- package/dist/_redact-command.d.ts +6 -0
- package/dist/_redact-command.d.ts.map +1 -0
- package/dist/_regex.d.ts +39 -0
- package/dist/_regex.d.ts.map +1 -0
- package/dist/_session-shell.d.ts +73 -0
- package/dist/_session-shell.d.ts.map +1 -0
- package/dist/_shell-pick.d.ts +158 -0
- package/dist/_shell-pick.d.ts.map +1 -0
- package/dist/_spawn-stream.d.ts +32 -0
- package/dist/_spawn-stream.d.ts.map +1 -0
- package/dist/_syntax-check.d.ts +16 -0
- package/dist/_syntax-check.d.ts.map +1 -0
- package/dist/_util.d.ts +68 -0
- package/dist/_util.d.ts.map +1 -0
- package/dist/_win32-resolve.d.ts +42 -0
- package/dist/_win32-resolve.d.ts.map +1 -0
- package/dist/audit.d.ts +4 -5
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +2743 -28
- package/dist/audit.js.map +7 -1
- package/dist/bash-kill-guard.d.ts +62 -0
- package/dist/bash-kill-guard.d.ts.map +1 -0
- package/dist/bash.d.ts +4 -5
- package/dist/bash.d.ts.map +1 -0
- package/dist/bash.js +59 -30
- package/dist/bash.js.map +7 -1
- package/dist/batch-tool-use.d.ts +4 -5
- package/dist/batch-tool-use.d.ts.map +1 -0
- package/dist/batch-tool-use.js +3 -3
- package/dist/batch-tool-use.js.map +7 -1
- package/dist/browser/artifacts.d.ts +13 -0
- package/dist/browser/artifacts.d.ts.map +1 -0
- package/dist/browser/index.d.ts +7 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +1264 -0
- package/dist/browser/index.js.map +7 -0
- package/dist/browser/manager.d.ts +57 -0
- package/dist/browser/manager.d.ts.map +1 -0
- package/dist/browser/network-guard-proxy.d.ts +23 -0
- package/dist/browser/network-guard-proxy.d.ts.map +1 -0
- package/dist/browser/security.d.ts +29 -0
- package/dist/browser/security.d.ts.map +1 -0
- package/dist/browser/tools.d.ts +62 -0
- package/dist/browser/tools.d.ts.map +1 -0
- package/dist/browser/types.d.ts +60 -0
- package/dist/browser/types.d.ts.map +1 -0
- package/dist/builtin.d.ts +11 -12
- package/dist/builtin.d.ts.map +1 -0
- package/dist/builtin.js +8099 -2178
- package/dist/builtin.js.map +7 -1
- package/dist/circuit-breaker.d.ts +4 -5
- package/dist/circuit-breaker.d.ts.map +1 -0
- package/dist/circuit-breaker.js +3 -3
- package/dist/circuit-breaker.js.map +7 -1
- package/dist/codebase-index/background-indexer.d.ts +116 -0
- package/dist/codebase-index/background-indexer.d.ts.map +1 -0
- package/dist/codebase-index/bm25.d.ts +40 -0
- package/dist/codebase-index/bm25.d.ts.map +1 -0
- package/dist/codebase-index/circuit-breaker.d.ts +94 -0
- package/dist/codebase-index/circuit-breaker.d.ts.map +1 -0
- package/dist/codebase-index/codebase-index-tool.d.ts +17 -0
- package/dist/codebase-index/codebase-index-tool.d.ts.map +1 -0
- package/dist/codebase-index/codebase-search-tool.d.ts +43 -0
- package/dist/codebase-index/codebase-search-tool.d.ts.map +1 -0
- package/dist/codebase-index/codebase-stats-tool.d.ts +23 -0
- package/dist/codebase-index/codebase-stats-tool.d.ts.map +1 -0
- package/dist/codebase-index/gitignore.d.ts +22 -0
- package/dist/codebase-index/gitignore.d.ts.map +1 -0
- package/dist/codebase-index/go-parser.d.ts +16 -0
- package/dist/codebase-index/go-parser.d.ts.map +1 -0
- package/dist/codebase-index/index-service.d.ts +25 -0
- package/dist/codebase-index/index-service.d.ts.map +1 -0
- package/dist/codebase-index/index.d.ts +23 -271
- package/dist/codebase-index/index.d.ts.map +1 -0
- package/dist/codebase-index/index.js +136 -68
- package/dist/codebase-index/index.js.map +7 -1
- package/dist/codebase-index/indexer.d.ts +28 -0
- package/dist/codebase-index/indexer.d.ts.map +1 -0
- package/dist/codebase-index/json-parser.d.ts +8 -0
- package/dist/codebase-index/json-parser.d.ts.map +1 -0
- package/dist/codebase-index/lsp-kind.d.ts +53 -0
- package/dist/codebase-index/lsp-kind.d.ts.map +1 -0
- package/dist/codebase-index/py-parser.d.ts +16 -0
- package/dist/codebase-index/py-parser.d.ts.map +1 -0
- package/dist/codebase-index/refs-extractor.d.ts +25 -0
- package/dist/codebase-index/refs-extractor.d.ts.map +1 -0
- package/dist/codebase-index/rs-parser.d.ts +8 -0
- package/dist/codebase-index/rs-parser.d.ts.map +1 -0
- package/dist/codebase-index/schema.d.ts +82 -0
- package/dist/codebase-index/schema.d.ts.map +1 -0
- package/dist/codebase-index/ts-parser.d.ts +30 -0
- package/dist/codebase-index/ts-parser.d.ts.map +1 -0
- package/dist/codebase-index/worker-protocol.d.ts +77 -0
- package/dist/codebase-index/worker-protocol.d.ts.map +1 -0
- package/dist/codebase-index/worker.d.ts +16 -2
- package/dist/codebase-index/worker.d.ts.map +1 -0
- package/dist/codebase-index/worker.js +103 -65
- package/dist/codebase-index/worker.js.map +7 -1
- package/dist/codebase-index/writer.d.ts +189 -0
- package/dist/codebase-index/writer.d.ts.map +1 -0
- package/dist/codebase-index/yaml-parser.d.ts +8 -0
- package/dist/codebase-index/yaml-parser.d.ts.map +1 -0
- package/dist/design.d.ts +38 -0
- package/dist/design.d.ts.map +1 -0
- package/dist/design.js +270 -0
- package/dist/design.js.map +7 -0
- package/dist/diff.d.ts +4 -5
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +14 -12
- package/dist/diff.js.map +7 -1
- package/dist/document.d.ts +4 -5
- package/dist/document.d.ts.map +1 -0
- package/dist/document.js +8 -7
- package/dist/document.js.map +7 -1
- package/dist/e2e.d.ts +56 -0
- package/dist/e2e.d.ts.map +1 -0
- package/dist/edit.d.ts +5 -36
- package/dist/edit.d.ts.map +1 -0
- package/dist/edit.js +28 -16
- package/dist/edit.js.map +7 -1
- package/dist/exec.d.ts +67 -2
- package/dist/exec.d.ts.map +1 -0
- package/dist/exec.js +51 -26
- package/dist/exec.js.map +7 -1
- package/dist/fetch.d.ts +4 -32
- package/dist/fetch.d.ts.map +1 -0
- package/dist/fetch.js +89 -77
- package/dist/fetch.js.map +7 -1
- package/dist/format.d.ts +4 -5
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +2415 -28
- package/dist/format.js.map +7 -1
- package/dist/git.d.ts +4 -5
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +10 -9
- package/dist/git.js.map +7 -1
- package/dist/glob.d.ts +4 -5
- package/dist/glob.d.ts.map +1 -0
- package/dist/glob.js +15 -12
- package/dist/glob.js.map +7 -1
- package/dist/grep.d.ts +4 -5
- package/dist/grep.d.ts.map +1 -0
- package/dist/grep.js +13 -10
- package/dist/grep.js.map +7 -1
- package/dist/index.d.ts +21 -724
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8955 -2866
- package/dist/index.js.map +7 -1
- package/dist/install.d.ts +4 -5
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +2680 -31
- package/dist/install.js.map +7 -1
- package/dist/json.d.ts +4 -5
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +13 -11
- package/dist/json.js.map +7 -1
- package/dist/kanban.d.ts +107 -0
- package/dist/kanban.d.ts.map +1 -0
- package/dist/kanban.js +845 -0
- package/dist/kanban.js.map +7 -0
- package/dist/languages/detect.d.ts +3 -0
- package/dist/languages/detect.d.ts.map +1 -0
- package/dist/languages/diagnostics.d.ts +15 -0
- package/dist/languages/diagnostics.d.ts.map +1 -0
- package/dist/languages/execute-tool.d.ts +34 -0
- package/dist/languages/execute-tool.d.ts.map +1 -0
- package/dist/languages/execute.d.ts +18 -0
- package/dist/languages/execute.d.ts.map +1 -0
- package/dist/languages/index.d.ts +12 -0
- package/dist/languages/index.d.ts.map +1 -0
- package/dist/languages/index.js +4457 -0
- package/dist/languages/index.js.map +7 -0
- package/dist/languages/legacy-bridge.d.ts +29 -0
- package/dist/languages/legacy-bridge.d.ts.map +1 -0
- package/dist/languages/package-tool.d.ts +29 -0
- package/dist/languages/package-tool.d.ts.map +1 -0
- package/dist/languages/plan.d.ts +4 -0
- package/dist/languages/plan.d.ts.map +1 -0
- package/dist/languages/profile-helpers.d.ts +14 -0
- package/dist/languages/profile-helpers.d.ts.map +1 -0
- package/dist/languages/profiles/additional.d.ts +3 -0
- package/dist/languages/profiles/additional.d.ts.map +1 -0
- package/dist/languages/profiles/primary.d.ts +3 -0
- package/dist/languages/profiles/primary.d.ts.map +1 -0
- package/dist/languages/registry.d.ts +11 -0
- package/dist/languages/registry.d.ts.map +1 -0
- package/dist/languages/tool.d.ts +32 -0
- package/dist/languages/tool.d.ts.map +1 -0
- package/dist/languages/types.d.ts +207 -0
- package/dist/languages/types.d.ts.map +1 -0
- package/dist/lint.d.ts +4 -5
- package/dist/lint.d.ts.map +1 -0
- package/dist/lint.js +2415 -27
- package/dist/lint.js.map +7 -1
- package/dist/logs.d.ts +4 -5
- package/dist/logs.d.ts.map +1 -0
- package/dist/logs.js +16 -10
- package/dist/logs.js.map +7 -1
- package/dist/memory.d.ts +7 -8
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +7 -5
- package/dist/memory.js.map +7 -1
- package/dist/mode.d.ts +4 -5
- package/dist/mode.d.ts.map +1 -0
- package/dist/mode.js +3 -3
- package/dist/mode.js.map +7 -1
- package/dist/next-steps.d.ts +5 -6
- package/dist/next-steps.d.ts.map +1 -0
- package/dist/next-steps.js +5 -4
- package/dist/next-steps.js.map +7 -1
- package/dist/outdated.d.ts +4 -5
- package/dist/outdated.d.ts.map +1 -0
- package/dist/outdated.js +4777 -68
- package/dist/outdated.js.map +7 -1
- package/dist/pack.d.ts +3 -6
- package/dist/pack.d.ts.map +1 -0
- package/dist/pack.js +8134 -2204
- package/dist/pack.js.map +7 -1
- package/dist/patch.d.ts +4 -5
- package/dist/patch.d.ts.map +1 -0
- package/dist/patch.js +18 -16
- package/dist/patch.js.map +7 -1
- package/dist/plan.d.ts +55 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +280 -0
- package/dist/plan.js.map +7 -0
- package/dist/process-guardian.d.ts +100 -0
- package/dist/process-guardian.d.ts.map +1 -0
- package/dist/process-registry-persistent.d.ts +121 -0
- package/dist/process-registry-persistent.d.ts.map +1 -0
- package/dist/process-registry.d.ts +13 -17
- package/dist/process-registry.d.ts.map +1 -0
- package/dist/process-registry.js +15 -9
- package/dist/process-registry.js.map +7 -1
- package/dist/ps-slash.d.ts +106 -0
- package/dist/ps-slash.d.ts.map +1 -0
- package/dist/ps-slash.js +1291 -0
- package/dist/ps-slash.js.map +7 -0
- package/dist/read.d.ts +4 -5
- package/dist/read.d.ts.map +1 -0
- package/dist/read.js +13 -11
- package/dist/read.js.map +7 -1
- package/dist/replace.d.ts +4 -5
- package/dist/replace.d.ts.map +1 -0
- package/dist/replace.js +26 -13
- package/dist/replace.js.map +7 -1
- package/dist/scaffold.d.ts +4 -5
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +16 -14
- package/dist/scaffold.js.map +7 -1
- package/dist/search.d.ts +5 -6
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +32 -27
- package/dist/search.js.map +7 -1
- package/dist/set-working-dir.d.ts +18 -0
- package/dist/set-working-dir.d.ts.map +1 -0
- package/dist/shim/node-sqlite.d.ts +3 -0
- package/dist/shim/node-sqlite.d.ts.map +1 -0
- package/dist/skill.d.ts +45 -0
- package/dist/skill.d.ts.map +1 -0
- package/dist/skill.js +175 -0
- package/dist/skill.js.map +7 -0
- package/dist/spawn-background.d.ts +80 -0
- package/dist/spawn-background.d.ts.map +1 -0
- package/dist/task.d.ts +35 -0
- package/dist/task.d.ts.map +1 -0
- package/dist/task.js +380 -0
- package/dist/task.js.map +7 -0
- package/dist/test.d.ts +4 -5
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +2419 -27
- package/dist/test.js.map +7 -1
- package/dist/todo.d.ts +4 -5
- package/dist/todo.d.ts.map +1 -0
- package/dist/todo.js +5 -5
- package/dist/todo.js.map +7 -1
- package/dist/tool-diff.d.ts +16 -17
- package/dist/tool-diff.d.ts.map +1 -0
- package/dist/tool-diff.js +11 -3
- package/dist/tool-diff.js.map +7 -1
- package/dist/tool-help.d.ts +4 -5
- package/dist/tool-help.d.ts.map +1 -0
- package/dist/tool-help.js +3 -3
- package/dist/tool-help.js.map +7 -1
- package/dist/tool-icon-map.d.ts +46 -0
- package/dist/tool-icon-map.d.ts.map +1 -0
- package/dist/tool-icons.d.ts +5 -6
- package/dist/tool-icons.d.ts.map +1 -0
- package/dist/tool-icons.js +16 -4
- package/dist/tool-icons.js.map +7 -1
- package/dist/tool-search.d.ts +4 -5
- package/dist/tool-search.d.ts.map +1 -0
- package/dist/tool-search.js +3 -3
- package/dist/tool-search.js.map +7 -1
- package/dist/tool-summary.d.ts +4 -5
- package/dist/tool-summary.d.ts.map +1 -0
- package/dist/tool-summary.js +5 -3
- package/dist/tool-summary.js.map +7 -1
- package/dist/tool-use.d.ts +4 -5
- package/dist/tool-use.d.ts.map +1 -0
- package/dist/tool-use.js +3 -3
- package/dist/tool-use.js.map +7 -1
- package/dist/tree.d.ts +4 -5
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +11 -9
- package/dist/tree.js.map +7 -1
- package/dist/typecheck.d.ts +4 -5
- package/dist/typecheck.d.ts.map +1 -0
- package/dist/typecheck.js +2416 -28
- package/dist/typecheck.js.map +7 -1
- package/dist/write.d.ts +4 -5
- package/dist/write.d.ts.map +1 -0
- package/dist/write.js +21 -16
- package/dist/write.js.map +7 -1
- package/package.json +39 -6
- package/dist/background-indexer-BeDBxfSh.d.ts +0 -371
- package/dist/exec-2OKoT6tk.d.ts +0 -121
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import type { FileMeta, IndexStats, Ref, SearchResult, Symbol as IndexSymbol, SymbolKind, SymbolLang } from './schema.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the per-project index directory. By default it lives under the
|
|
4
|
+
* global project dir (`~/.wrongstack/projects/<hash>/codebase-index`),
|
|
5
|
+
* matching every other piece of per-project state. Callers may pass an
|
|
6
|
+
* explicit `override` (used by tests and any wiring that already resolved the
|
|
7
|
+
* path) to avoid touching the real home directory.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveIndexDir(projectRoot: string, override?: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Optional index-directory override carried on the run context's `meta` bag.
|
|
12
|
+
* Production leaves it unset (the index resolves to the global per-project
|
|
13
|
+
* dir); tests and bespoke wiring set `meta.codebaseIndexDir` to redirect it.
|
|
14
|
+
*/
|
|
15
|
+
export declare function codebaseIndexDirOverride(ctx: {
|
|
16
|
+
meta?: Record<string, unknown>;
|
|
17
|
+
}): string | undefined;
|
|
18
|
+
export declare class IndexStore {
|
|
19
|
+
private db;
|
|
20
|
+
/** Absolute path to this project's index directory. */
|
|
21
|
+
private readonly indexDir;
|
|
22
|
+
/**
|
|
23
|
+
* True when the SQLite build provides FTS5 (Node's bundled SQLite does).
|
|
24
|
+
* When false, ranked search falls back to the LIKE + in-process BM25 path.
|
|
25
|
+
*/
|
|
26
|
+
private ftsAvailable;
|
|
27
|
+
/**
|
|
28
|
+
* Cache of prepared statements keyed by their SQL text. `DatabaseSync`
|
|
29
|
+
* compiles SQL on every `.prepare()` call; for the fixed-SQL methods
|
|
30
|
+
* (upsertFile, getFileMeta, deleteFile, insertRefs, …) that runs thousands
|
|
31
|
+
* of times during a full reindex. `StatementSync` objects are reusable
|
|
32
|
+
* across calls on the same connection, so we compile each distinct SQL once
|
|
33
|
+
* and reuse it. Cleared in {@link close} when the connection is torn down.
|
|
34
|
+
*/
|
|
35
|
+
private readonly stmtCache;
|
|
36
|
+
/** Prepare-once helper: compile `sql` on first use, reuse thereafter. */
|
|
37
|
+
private stmt;
|
|
38
|
+
/**
|
|
39
|
+
* Execute a SQLite write operation with automatic retry on lock conflicts.
|
|
40
|
+
*
|
|
41
|
+
* When another wstack process is holding the write lock the statement first
|
|
42
|
+
* waits up to `busy_timeout` ms, then throws SQLITE_BUSY. This wrapper catches
|
|
43
|
+
* that error and retries (up to MAX_LOCK_RETRIES) with exponential backoff,
|
|
44
|
+
* giving the competing writer time to finish and release the lock.
|
|
45
|
+
*
|
|
46
|
+
* @param fn The write operation to execute. Can return a value which is
|
|
47
|
+
* returned to the caller on success.
|
|
48
|
+
* @throws {@link LockError} when all retries are exhausted on a lock conflict
|
|
49
|
+
* (non-lock errors always propagate on the first attempt).
|
|
50
|
+
*/
|
|
51
|
+
runWithRetry<T>(fn: () => T): T;
|
|
52
|
+
constructor(projectRoot: string, opts?: {
|
|
53
|
+
indexDir?: string | undefined;
|
|
54
|
+
});
|
|
55
|
+
private initSchema;
|
|
56
|
+
/**
|
|
57
|
+
* Insert symbols, assigning IDs atomically inside `BEGIN IMMEDIATE` /
|
|
58
|
+
* `COMMIT`. The ID allocation (`SELECT MAX(id)`) and all `INSERT`s share
|
|
59
|
+
* the same transaction, preventing UNIQUE constraint violations when two
|
|
60
|
+
* processes index concurrently (each would see a different `MAX(id)` and
|
|
61
|
+
* neither can insert with the other's IDs).
|
|
62
|
+
*
|
|
63
|
+
* @returns The symbols array with `id` fields populated so the caller can
|
|
64
|
+
* use them for refs without re-reading from the DB.
|
|
65
|
+
*/
|
|
66
|
+
insertSymbols(symbols: IndexSymbol[]): IndexSymbol[];
|
|
67
|
+
deleteSymbolsForFile(file: string): void;
|
|
68
|
+
/**
|
|
69
|
+
* Remove every trace of a file (refs, symbols, FTS rows, file meta). Used
|
|
70
|
+
* when a source file disappears between index runs — previously this only
|
|
71
|
+
* dropped the `files` row, leaving its symbols orphaned but still searchable.
|
|
72
|
+
*/
|
|
73
|
+
deleteFile(file: string): void;
|
|
74
|
+
upsertFile(meta: FileMeta): void;
|
|
75
|
+
getFileMeta(file: string): FileMeta | null;
|
|
76
|
+
getAllFileMetas(): FileMeta[];
|
|
77
|
+
search(query: string, filter?: {
|
|
78
|
+
kind?: SymbolKind | undefined;
|
|
79
|
+
lang?: SymbolLang | undefined;
|
|
80
|
+
file?: string | undefined;
|
|
81
|
+
lspKind?: number | undefined;
|
|
82
|
+
}): SearchResult[];
|
|
83
|
+
/**
|
|
84
|
+
* Ranked search — the one-stop query the codebase-search tool and plug-lsp
|
|
85
|
+
* use. With FTS5 this is a single indexed `MATCH` ranked by SQLite's native
|
|
86
|
+
* `bm25()` with a built-in `snippet()`; without FTS5 it falls back to the
|
|
87
|
+
* legacy LIKE scan + in-process BM25 (identical semantics, slower).
|
|
88
|
+
*
|
|
89
|
+
* Tokens are matched as prefixes (`"tok"*`), mirroring the old
|
|
90
|
+
* `LIKE '%tok%'` recall for the common symbol-search shapes ("user" finds
|
|
91
|
+
* "users", camelCase-split text makes "complex" find "complexOperation").
|
|
92
|
+
*/
|
|
93
|
+
searchRanked(query: string, filter: {
|
|
94
|
+
kind?: SymbolKind | undefined;
|
|
95
|
+
lang?: SymbolLang | undefined;
|
|
96
|
+
file?: string | undefined;
|
|
97
|
+
lspKind?: number | undefined;
|
|
98
|
+
} | undefined, limit: number): {
|
|
99
|
+
results: SearchResult[];
|
|
100
|
+
total: number;
|
|
101
|
+
};
|
|
102
|
+
/** Legacy ranked path: LIKE candidates + in-process BM25 + JS snippets. */
|
|
103
|
+
private searchRankedFallback;
|
|
104
|
+
getAllIndexable(): Array<{
|
|
105
|
+
id: number;
|
|
106
|
+
text: string;
|
|
107
|
+
}>;
|
|
108
|
+
/**
|
|
109
|
+
* Largest symbol id currently in the table (0 when empty). New ids must be
|
|
110
|
+
* allocated from this, NOT from `COUNT(*)`: incremental reindexes delete a
|
|
111
|
+
* changed file's rows, so the row count drops below the max id and a
|
|
112
|
+
* count-based id would collide with a surviving row (UNIQUE constraint on
|
|
113
|
+
* `symbols.id`). Ids may have gaps — that is fine.
|
|
114
|
+
*/
|
|
115
|
+
getMaxSymbolId(): number;
|
|
116
|
+
getStats(): IndexStats;
|
|
117
|
+
setLastIndexed(ts: number): void;
|
|
118
|
+
clearAll(): void;
|
|
119
|
+
/**
|
|
120
|
+
* Insert cross-references for a given source symbol id.
|
|
121
|
+
* Replaces any existing refs from the same source (idempotent on re-index).
|
|
122
|
+
*/
|
|
123
|
+
insertRefs(fromId: number, refs: Ref[]): void;
|
|
124
|
+
/**
|
|
125
|
+
* Bulk-insert refs for many source symbols in a single transaction.
|
|
126
|
+
*
|
|
127
|
+
* Unlike {@link insertRefs} this does NOT delete per source id — the caller
|
|
128
|
+
* (the indexer) has already cleared stale refs for the file via
|
|
129
|
+
* {@link deleteRefsForFile}, so the per-source DELETE would be redundant work
|
|
130
|
+
* repeated once per symbol. One transaction for the whole file instead of one
|
|
131
|
+
* per symbol turns an O(symbols) transaction count into O(1).
|
|
132
|
+
*
|
|
133
|
+
* Each ref's own {@link Ref.fromId} is used; pass an empty array to no-op.
|
|
134
|
+
*/
|
|
135
|
+
insertRefsBatch(refs: Ref[]): void;
|
|
136
|
+
/**
|
|
137
|
+
* Commit a batch of file-level symbol/refs/upserts in a single transaction.
|
|
138
|
+
*
|
|
139
|
+
* Used by the indexer to amortize SQLite commit overhead across many files.
|
|
140
|
+
* Before this, the indexer issued one transaction per file (BEGIN IMMEDIATE
|
|
141
|
+
* for symbols, plus per-file deletes and an upsertFile call), so a 20-file
|
|
142
|
+
* parallel batch cost ~5+ transactions × 20 files = 100+ commits. With
|
|
143
|
+
* this entry point we do exactly one BEGIN/COMMIT per parallel batch.
|
|
144
|
+
*
|
|
145
|
+
* Each entry must already be a fully-parsed FileSymbols (symbols + refs).
|
|
146
|
+
* The caller is responsible for the per-file prefix accounting
|
|
147
|
+
* (refsByLine → flat list with `fromId` populated). `deleteForFiles` lets
|
|
148
|
+
* the caller clear stale symbols/refs for any files being re-indexed before
|
|
149
|
+
* the inserts run (required to keep refs → symbols FK invariants).
|
|
150
|
+
*
|
|
151
|
+
* Returns the symbols back with their assigned `id` (same shape as
|
|
152
|
+
* {@link insertSymbols}) so callers can build final per-file results.
|
|
153
|
+
*/
|
|
154
|
+
commitBatch(entries: Array<{
|
|
155
|
+
file: string;
|
|
156
|
+
lang: SymbolLang;
|
|
157
|
+
symbols: IndexSymbol[];
|
|
158
|
+
refs: Ref[];
|
|
159
|
+
mtimeMs: number;
|
|
160
|
+
symbolCount: number;
|
|
161
|
+
}>, options?: {
|
|
162
|
+
deleteForFiles?: string[] | undefined;
|
|
163
|
+
}): IndexSymbol[];
|
|
164
|
+
/**
|
|
165
|
+
* Delete all refs whose source symbols are in a given file.
|
|
166
|
+
* Used when re-indexing a file to clear stale refs.
|
|
167
|
+
*/
|
|
168
|
+
deleteRefsForFile(file: string): void;
|
|
169
|
+
/**
|
|
170
|
+
* Resolve `to_name` → `to_id` for all refs that have a name but no id.
|
|
171
|
+
* Call this after all symbols have been inserted to fill in cross-references.
|
|
172
|
+
*
|
|
173
|
+
* Single statement: the `to_name IN (SELECT name FROM symbols)` guard restricts
|
|
174
|
+
* the UPDATE to refs that will actually resolve, so `.changes` counts only refs
|
|
175
|
+
* that found a target — matching the previous per-row loop's return value.
|
|
176
|
+
*/
|
|
177
|
+
resolveRefs(): number;
|
|
178
|
+
/**
|
|
179
|
+
* Find all references TO a given symbol (who calls / uses this symbol?).
|
|
180
|
+
*/
|
|
181
|
+
findRefsTo(symbolId: number): Ref[];
|
|
182
|
+
/**
|
|
183
|
+
* Find all references FROM a given symbol (what does this symbol call/use?).
|
|
184
|
+
*/
|
|
185
|
+
findRefsFrom(symbolId: number): Ref[];
|
|
186
|
+
private sizeBytes;
|
|
187
|
+
close(): void;
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../src/codebase-index/writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FileSymbols, SymbolLang } from './schema.js';
|
|
2
|
+
export declare function parseSymbols(opts: {
|
|
3
|
+
file: string;
|
|
4
|
+
content: string;
|
|
5
|
+
lang: SymbolLang;
|
|
6
|
+
}): FileSymbols;
|
|
7
|
+
export { detectLang } from './ts-parser.js';
|
|
8
|
+
//# sourceMappingURL=yaml-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml-parser.d.ts","sourceRoot":"","sources":["../../src/codebase-index/yaml-parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAyB,UAAU,EAAE,MAAM,aAAa,CAAC;AAGlF,wBAAgB,YAAY,CAAC,IAAI,EAAE;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,UAAU,CAAC;CAClB,GAAG,WAAW,CASd;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/design.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Tool } from '@wrongstack/core';
|
|
2
|
+
type Overrides = Record<string, string>;
|
|
3
|
+
interface DesignInput {
|
|
4
|
+
action?: 'list' | 'use' | 'foundations' | 'set' | 'materialize' | 'verify' | undefined;
|
|
5
|
+
kit?: string | undefined;
|
|
6
|
+
stack?: string | undefined;
|
|
7
|
+
/** action "set" / "use": token overrides, e.g. { primary: "oklch(...)", "dark.bg": "#111" }. */
|
|
8
|
+
set?: Overrides | undefined;
|
|
9
|
+
/** action "materialize": output path (project-relative); defaults per stack. */
|
|
10
|
+
out?: string | undefined;
|
|
11
|
+
/** action "materialize": overwrite an existing file. */
|
|
12
|
+
force?: boolean | undefined;
|
|
13
|
+
/** action "verify": explicit files to scan (project-relative). Defaults to a UI-file walk. */
|
|
14
|
+
files?: string[] | undefined;
|
|
15
|
+
}
|
|
16
|
+
interface DesignOutput {
|
|
17
|
+
action: string;
|
|
18
|
+
kit?: string | undefined;
|
|
19
|
+
stack?: string | undefined;
|
|
20
|
+
output: string;
|
|
21
|
+
/** action "materialize": where the theme file was (or would be) written. */
|
|
22
|
+
path?: string | undefined;
|
|
23
|
+
/** action "verify": adherence score 0..1 and violation count. */
|
|
24
|
+
score?: number | undefined;
|
|
25
|
+
violations?: number | undefined;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Design Studio tool — progressive disclosure + token enforcement.
|
|
29
|
+
*
|
|
30
|
+
* `list`/`use`/`foundations` browse and pin kits. `set` records structured color
|
|
31
|
+
* overrides (these win over kit tokens). `materialize` writes the active kit's
|
|
32
|
+
* (override-applied) tokens to a real, stack-appropriate theme file so the
|
|
33
|
+
* palette becomes the codebase's source of truth — not just a prompt hint.
|
|
34
|
+
* `verify` scans UI files for off-palette drift.
|
|
35
|
+
*/
|
|
36
|
+
export declare const designTool: Tool<DesignInput, DesignOutput>;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=design.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design.d.ts","sourceRoot":"","sources":["../src/design.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAe,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAc1D,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AA+BxC,UAAU,WAAW;IACnB,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,aAAa,GAAG,KAAK,GAAG,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;IACvF,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,gGAAgG;IAChG,GAAG,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAC5B,gFAAgF;IAChF,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,wDAAwD;IACxD,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,8FAA8F;IAC9F,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CAC9B;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAYD;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,EAAE,IAAI,CAAC,WAAW,EAAE,YAAY,CA8QtD,CAAC"}
|
package/dist/design.js
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
// src/design.ts
|
|
2
|
+
import * as fs from "node:fs/promises";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import {
|
|
5
|
+
applyTokenOverrides,
|
|
6
|
+
getDesignKitLoader,
|
|
7
|
+
isDesignStack,
|
|
8
|
+
loadActiveKit,
|
|
9
|
+
materializeTokens,
|
|
10
|
+
recordKitChoice,
|
|
11
|
+
recordOverrides,
|
|
12
|
+
runDesignVerify,
|
|
13
|
+
setActiveKit,
|
|
14
|
+
setDesignOverrides
|
|
15
|
+
} from "@wrongstack/core";
|
|
16
|
+
async function resolveReal(p) {
|
|
17
|
+
const resolved = path.resolve(p);
|
|
18
|
+
let probe = resolved;
|
|
19
|
+
const missing = [];
|
|
20
|
+
for (; ; ) {
|
|
21
|
+
try {
|
|
22
|
+
return path.resolve(await fs.realpath(probe), ...missing);
|
|
23
|
+
} catch (err) {
|
|
24
|
+
if (err.code === "ENOENT") {
|
|
25
|
+
const parent = path.dirname(probe);
|
|
26
|
+
if (parent === probe) return resolved;
|
|
27
|
+
missing.unshift(path.basename(probe));
|
|
28
|
+
probe = parent;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
return resolved;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function normalizeOverrides(set) {
|
|
36
|
+
const out = {};
|
|
37
|
+
if (set && typeof set === "object") {
|
|
38
|
+
for (const [k, v] of Object.entries(set)) {
|
|
39
|
+
if (typeof v === "string") out[k] = v;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
var designTool = {
|
|
45
|
+
name: "design",
|
|
46
|
+
category: "Design",
|
|
47
|
+
description: 'Browse, load, customize, and enforce curated frontend/mobile UI design kits. Use BEFORE writing UI code to commit to one coherent, modern, responsive, dark/light, accessible design. Actions: "list" (menu), "use" (load+pin a kit for a stack), "foundations" (baseline), "set" (override kit colors/tokens), "materialize" (write the tokens to a real theme file \u2014 CSS @theme/OKLCH or native), "verify" (scan UI files for off-palette colors).',
|
|
48
|
+
usageHint: 'Flow: `design {action:"use", kit:"minimal-clarity", stack:"web"}` \u2192 optionally `design {action:"set", set:{primary:"oklch(62% 0.2 25)"}}` \u2192 `design {action:"materialize"}` to write tokens to disk \u2192 implement against them \u2192 `design {action:"verify"}`.',
|
|
49
|
+
permission: "confirm",
|
|
50
|
+
mutating: true,
|
|
51
|
+
capabilities: ["fs.write"],
|
|
52
|
+
timeoutMs: 15e3,
|
|
53
|
+
inputSchema: {
|
|
54
|
+
type: "object",
|
|
55
|
+
properties: {
|
|
56
|
+
action: {
|
|
57
|
+
type: "string",
|
|
58
|
+
enum: ["list", "use", "foundations", "set", "materialize", "verify"],
|
|
59
|
+
description: "list = menu; use = load+pin a kit; foundations = baseline; set = override colors/tokens; materialize = write tokens to a theme file; verify = scan UI for off-palette colors. Default: list."
|
|
60
|
+
},
|
|
61
|
+
kit: {
|
|
62
|
+
type: "string",
|
|
63
|
+
description: 'Kit id (required for "use"), e.g. "minimal-clarity", "neo-brutalist".'
|
|
64
|
+
},
|
|
65
|
+
stack: {
|
|
66
|
+
type: "string",
|
|
67
|
+
enum: ["web", "react-native", "flutter", "swiftui", "compose"],
|
|
68
|
+
description: "Target stack \u2014 narrows guidance + materialize format. Default: web."
|
|
69
|
+
},
|
|
70
|
+
set: {
|
|
71
|
+
type: "object",
|
|
72
|
+
description: 'Token overrides for "set"/"use": { "primary": "oklch(\u2026)", "dark.bg": "#111" }. Bare key = both themes; "light."/"dark." prefix = that theme only. Empty value clears an override.',
|
|
73
|
+
additionalProperties: { type: "string" }
|
|
74
|
+
},
|
|
75
|
+
out: {
|
|
76
|
+
type: "string",
|
|
77
|
+
description: "Materialize output path (project-relative). Defaults to a per-stack convention."
|
|
78
|
+
},
|
|
79
|
+
force: {
|
|
80
|
+
type: "boolean",
|
|
81
|
+
description: "Materialize: overwrite an existing file (default false \u2014 refuses to clobber)."
|
|
82
|
+
},
|
|
83
|
+
files: {
|
|
84
|
+
type: "array",
|
|
85
|
+
items: { type: "string" },
|
|
86
|
+
description: "Verify: explicit project-relative files to scan. Default: a bounded UI-file walk."
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
required: []
|
|
90
|
+
},
|
|
91
|
+
async execute(input, ctx) {
|
|
92
|
+
const loader = getDesignKitLoader(ctx.projectRoot);
|
|
93
|
+
const action = input.action ?? "list";
|
|
94
|
+
const stack = input.stack && isDesignStack(input.stack) ? input.stack : void 0;
|
|
95
|
+
if (action === "foundations") {
|
|
96
|
+
const text = await loader.foundationsText(stack);
|
|
97
|
+
return { action, stack, output: text || "No foundations document is installed." };
|
|
98
|
+
}
|
|
99
|
+
if (action === "use") {
|
|
100
|
+
const kitId = input.kit?.trim();
|
|
101
|
+
if (!kitId) {
|
|
102
|
+
const menu2 = await loader.menuText();
|
|
103
|
+
return { action, output: `No kit id provided.
|
|
104
|
+
|
|
105
|
+
${menu2}` };
|
|
106
|
+
}
|
|
107
|
+
const manifest = await loader.find(kitId);
|
|
108
|
+
if (!manifest) {
|
|
109
|
+
const menu2 = await loader.menuText();
|
|
110
|
+
return { action, kit: kitId, output: `Kit "${kitId}" not found.
|
|
111
|
+
|
|
112
|
+
${menu2}` };
|
|
113
|
+
}
|
|
114
|
+
const resolvedStack = stack ?? manifest.stacks[0] ?? "web";
|
|
115
|
+
const body = await loader.readBody(manifest.id, resolvedStack);
|
|
116
|
+
const rawTokens = await loader.readTokens(manifest.id);
|
|
117
|
+
const persisted = await loadActiveKit(ctx.projectRoot);
|
|
118
|
+
const keepOverrides = persisted?.kit === manifest.id ? persisted.overrides ?? {} : {};
|
|
119
|
+
const overrides = { ...keepOverrides, ...normalizeOverrides(input.set) };
|
|
120
|
+
const tokens = rawTokens ? applyTokenOverrides(rawTokens, overrides) : rawTokens;
|
|
121
|
+
setActiveKit(ctx, manifest.id, resolvedStack, overrides);
|
|
122
|
+
await recordKitChoice(
|
|
123
|
+
ctx.projectRoot,
|
|
124
|
+
manifest.id,
|
|
125
|
+
resolvedStack,
|
|
126
|
+
"design-tool",
|
|
127
|
+
(/* @__PURE__ */ new Date()).toISOString(),
|
|
128
|
+
Object.keys(overrides).length ? overrides : void 0
|
|
129
|
+
);
|
|
130
|
+
const ovLine = Object.keys(overrides).length ? `
|
|
131
|
+
Active color overrides: ${Object.entries(overrides).map(([k, v]) => `${k}=${v}`).join(", ")}
|
|
132
|
+
` : "";
|
|
133
|
+
const header = `# Active design kit: ${manifest.name} (${manifest.id}) \u2014 stack: ${resolvedStack}
|
|
134
|
+
${manifest.aesthetic}
|
|
135
|
+
${ovLine}
|
|
136
|
+
Implement the UI faithfully to this spec. Keep light/dark, responsive, and WCAG AA.
|
|
137
|
+
`;
|
|
138
|
+
const tokenBlock = tokens ? `
|
|
139
|
+
## Token snapshot (overrides applied)
|
|
140
|
+
\`\`\`json
|
|
141
|
+
${JSON.stringify(tokens, null, 2)}
|
|
142
|
+
\`\`\`
|
|
143
|
+
Tip: run \`design {action:"materialize"}\` to write these tokens to a real theme file.
|
|
144
|
+
` : "";
|
|
145
|
+
return {
|
|
146
|
+
action,
|
|
147
|
+
kit: manifest.id,
|
|
148
|
+
stack: resolvedStack,
|
|
149
|
+
output: `${header}${tokenBlock}
|
|
150
|
+
${body}`
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
if (action === "set") {
|
|
154
|
+
const patch = normalizeOverrides(input.set);
|
|
155
|
+
if (Object.keys(patch).length === 0) {
|
|
156
|
+
return { action, output: 'No overrides given. Pass set:{ "primary": "oklch(\u2026)" }.' };
|
|
157
|
+
}
|
|
158
|
+
const merged = await recordOverrides(ctx.projectRoot, patch, (/* @__PURE__ */ new Date()).toISOString());
|
|
159
|
+
if (!merged) {
|
|
160
|
+
return {
|
|
161
|
+
action,
|
|
162
|
+
output: 'No active kit. Pick one first: `design {action:"use", kit:"<id>"}`.'
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
setDesignOverrides(ctx, merged);
|
|
166
|
+
return {
|
|
167
|
+
action,
|
|
168
|
+
output: `Overrides updated. Active overrides: ${Object.entries(merged).map(([k, v]) => `${k}=${v}`).join(", ")}
|
|
169
|
+
These win over kit tokens. Run \`design {action:"materialize"}\` to write them to a theme file.`
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
if (action === "materialize") {
|
|
173
|
+
const active = await loadActiveKit(ctx.projectRoot);
|
|
174
|
+
if (!active) {
|
|
175
|
+
return {
|
|
176
|
+
action,
|
|
177
|
+
output: 'No active kit. Pick one first: `design {action:"use", kit:"<id>"}`.'
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
const resolvedStack = stack ?? (active.stack && isDesignStack(active.stack) ? active.stack : "web");
|
|
181
|
+
const rawTokens = await loader.readTokens(active.kit);
|
|
182
|
+
if (!rawTokens) {
|
|
183
|
+
return { action, kit: active.kit, output: `Kit "${active.kit}" has no tokens.json.` };
|
|
184
|
+
}
|
|
185
|
+
const tokens = applyTokenOverrides(rawTokens, active.overrides);
|
|
186
|
+
const result = materializeTokens({
|
|
187
|
+
tokens,
|
|
188
|
+
stack: resolvedStack,
|
|
189
|
+
kitId: active.kit,
|
|
190
|
+
outPath: input.out
|
|
191
|
+
});
|
|
192
|
+
const root = await resolveReal(ctx.projectRoot);
|
|
193
|
+
const absResolved = path.isAbsolute(result.path) ? path.resolve(result.path) : path.resolve(path.join(ctx.projectRoot, result.path));
|
|
194
|
+
const absParent = await resolveReal(path.dirname(absResolved));
|
|
195
|
+
const abs = path.join(absParent, path.basename(absResolved));
|
|
196
|
+
const rel = path.relative(root, abs);
|
|
197
|
+
if (rel.startsWith("..") || path.isAbsolute(rel)) {
|
|
198
|
+
throw new Error(
|
|
199
|
+
`design: materialize path "${result.path}" would escape the project root`
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
let exists = false;
|
|
203
|
+
try {
|
|
204
|
+
await fs.access(abs);
|
|
205
|
+
exists = true;
|
|
206
|
+
} catch {
|
|
207
|
+
}
|
|
208
|
+
if (exists && !input.force) {
|
|
209
|
+
return {
|
|
210
|
+
action,
|
|
211
|
+
kit: active.kit,
|
|
212
|
+
stack: resolvedStack,
|
|
213
|
+
path: result.path,
|
|
214
|
+
output: `${result.path} already exists. Re-run with force:true to overwrite, or write this ${result.format} yourself:
|
|
215
|
+
|
|
216
|
+
\`\`\`
|
|
217
|
+
${result.content}
|
|
218
|
+
\`\`\``
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
await fs.mkdir(path.dirname(abs), { recursive: true });
|
|
222
|
+
await fs.writeFile(abs, result.content);
|
|
223
|
+
return {
|
|
224
|
+
action,
|
|
225
|
+
kit: active.kit,
|
|
226
|
+
stack: resolvedStack,
|
|
227
|
+
path: result.path,
|
|
228
|
+
output: `Wrote ${result.format} to ${result.path}. Import these tokens in your UI so the kit palette is the source of truth. ${exists ? "(overwrote existing file)" : ""}`
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
if (action === "verify") {
|
|
232
|
+
const active = await loadActiveKit(ctx.projectRoot);
|
|
233
|
+
if (!active) {
|
|
234
|
+
return {
|
|
235
|
+
action,
|
|
236
|
+
output: 'No active kit to verify against. Pick one: `design {action:"use", kit:"<id>"}`.'
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
const rawTokens = await loader.readTokens(active.kit);
|
|
240
|
+
if (!rawTokens) {
|
|
241
|
+
return { action, kit: active.kit, output: `Kit "${active.kit}" has no tokens.json.` };
|
|
242
|
+
}
|
|
243
|
+
const tokens = applyTokenOverrides(rawTokens, active.overrides);
|
|
244
|
+
const report = await runDesignVerify(ctx.projectRoot, tokens, input.files);
|
|
245
|
+
const pct = Math.round(report.score * 100);
|
|
246
|
+
const top = report.violations.slice(0, 25).map((v) => ` ${v.file}:${v.line} \u2014 ${v.reason}: ${v.snippet}`).join("\n");
|
|
247
|
+
const summary = `Adherence: ${pct}% on-palette across ${report.filesScanned} file(s). ${report.violations.length} violation(s).` + (report.violations.length ? `
|
|
248
|
+
${top}${report.violations.length > 25 ? `
|
|
249
|
+
\u2026and ${report.violations.length - 25} more` : ""}
|
|
250
|
+
|
|
251
|
+
Replace off-palette colors with kit tokens (or the materialized CSS vars / token utilities).` : "\nNo off-palette colors found \u2014 UI adheres to the kit palette.");
|
|
252
|
+
return {
|
|
253
|
+
action,
|
|
254
|
+
kit: active.kit,
|
|
255
|
+
output: summary,
|
|
256
|
+
score: report.score,
|
|
257
|
+
violations: report.violations.length
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
const menu = await loader.menuText();
|
|
261
|
+
return {
|
|
262
|
+
action: "list",
|
|
263
|
+
output: (menu || "No design kits are installed.") + '\n\nLoad one with `design {action:"use", kit:"<id>", stack:"<stack>"}`.'
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
export {
|
|
268
|
+
designTool
|
|
269
|
+
};
|
|
270
|
+
//# sourceMappingURL=design.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/design.ts"],
|
|
4
|
+
"sourcesContent": ["import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { DesignStack, Tool } from '@wrongstack/core';\nimport {\n applyTokenOverrides,\n getDesignKitLoader,\n isDesignStack,\n loadActiveKit,\n materializeTokens,\n recordKitChoice,\n recordOverrides,\n runDesignVerify,\n setActiveKit,\n setDesignOverrides,\n} from '@wrongstack/core';\n\ntype Overrides = Record<string, string>;\n\n/**\n * Canonicalize `p` through `fs.realpath` so symlinks / bind mounts don't\n * hide out-of-root writes. Falls back to `path.resolve(p)` when the path\n * (or any of its parents) doesn't exist yet \u2014 callers frequently pass a\n * destination that the tool is about to write.\n */\nasync function resolveReal(p: string): Promise<string> {\n const resolved = path.resolve(p);\n let probe = resolved;\n const missing: string[] = [];\n for (;;) {\n try {\n return path.resolve(await fs.realpath(probe), ...missing);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n const parent = path.dirname(probe);\n if (parent === probe) return resolved; // reached fs root\n missing.unshift(path.basename(probe));\n probe = parent;\n continue;\n }\n // Any other error (EACCES, EBUSY, \u2026) \u2014 fall back to the lexical\n // resolve rather than throwing, so the caller can still surface a\n // meaningful error from the path.relative check below.\n return resolved;\n }\n }\n}\n\ninterface DesignInput {\n action?: 'list' | 'use' | 'foundations' | 'set' | 'materialize' | 'verify' | undefined;\n kit?: string | undefined;\n stack?: string | undefined;\n /** action \"set\" / \"use\": token overrides, e.g. { primary: \"oklch(...)\", \"dark.bg\": \"#111\" }. */\n set?: Overrides | undefined;\n /** action \"materialize\": output path (project-relative); defaults per stack. */\n out?: string | undefined;\n /** action \"materialize\": overwrite an existing file. */\n force?: boolean | undefined;\n /** action \"verify\": explicit files to scan (project-relative). Defaults to a UI-file walk. */\n files?: string[] | undefined;\n}\n\ninterface DesignOutput {\n action: string;\n kit?: string | undefined;\n stack?: string | undefined;\n output: string;\n /** action \"materialize\": where the theme file was (or would be) written. */\n path?: string | undefined;\n /** action \"verify\": adherence score 0..1 and violation count. */\n score?: number | undefined;\n violations?: number | undefined;\n}\n\nfunction normalizeOverrides(set: unknown): Overrides {\n const out: Overrides = {};\n if (set && typeof set === 'object') {\n for (const [k, v] of Object.entries(set as Record<string, unknown>)) {\n if (typeof v === 'string') out[k] = v;\n }\n }\n return out;\n}\n\n/**\n * Design Studio tool \u2014 progressive disclosure + token enforcement.\n *\n * `list`/`use`/`foundations` browse and pin kits. `set` records structured color\n * overrides (these win over kit tokens). `materialize` writes the active kit's\n * (override-applied) tokens to a real, stack-appropriate theme file so the\n * palette becomes the codebase's source of truth \u2014 not just a prompt hint.\n * `verify` scans UI files for off-palette drift.\n */\nexport const designTool: Tool<DesignInput, DesignOutput> = {\n name: 'design',\n category: 'Design',\n description:\n 'Browse, load, customize, and enforce curated frontend/mobile UI design kits. Use BEFORE writing ' +\n 'UI code to commit to one coherent, modern, responsive, dark/light, accessible design. Actions: ' +\n '\"list\" (menu), \"use\" (load+pin a kit for a stack), \"foundations\" (baseline), \"set\" (override kit ' +\n 'colors/tokens), \"materialize\" (write the tokens to a real theme file \u2014 CSS @theme/OKLCH or native), ' +\n '\"verify\" (scan UI files for off-palette colors).',\n usageHint:\n 'Flow: `design {action:\"use\", kit:\"minimal-clarity\", stack:\"web\"}` \u2192 optionally ' +\n '`design {action:\"set\", set:{primary:\"oklch(62% 0.2 25)\"}}` \u2192 `design {action:\"materialize\"}` ' +\n 'to write tokens to disk \u2192 implement against them \u2192 `design {action:\"verify\"}`.',\n permission: 'confirm',\n mutating: true,\n capabilities: ['fs.write'],\n timeoutMs: 15_000,\n inputSchema: {\n type: 'object',\n properties: {\n action: {\n type: 'string',\n enum: ['list', 'use', 'foundations', 'set', 'materialize', 'verify'],\n description:\n 'list = menu; use = load+pin a kit; foundations = baseline; set = override colors/tokens; ' +\n 'materialize = write tokens to a theme file; verify = scan UI for off-palette colors. Default: list.',\n },\n kit: {\n type: 'string',\n description: 'Kit id (required for \"use\"), e.g. \"minimal-clarity\", \"neo-brutalist\".',\n },\n stack: {\n type: 'string',\n enum: ['web', 'react-native', 'flutter', 'swiftui', 'compose'],\n description: 'Target stack \u2014 narrows guidance + materialize format. Default: web.',\n },\n set: {\n type: 'object',\n description:\n 'Token overrides for \"set\"/\"use\": { \"primary\": \"oklch(\u2026)\", \"dark.bg\": \"#111\" }. Bare key = ' +\n 'both themes; \"light.\"/\"dark.\" prefix = that theme only. Empty value clears an override.',\n additionalProperties: { type: 'string' },\n },\n out: {\n type: 'string',\n description: 'Materialize output path (project-relative). Defaults to a per-stack convention.',\n },\n force: {\n type: 'boolean',\n description: 'Materialize: overwrite an existing file (default false \u2014 refuses to clobber).',\n },\n files: {\n type: 'array',\n items: { type: 'string' },\n description: 'Verify: explicit project-relative files to scan. Default: a bounded UI-file walk.',\n },\n },\n required: [],\n },\n async execute(input, ctx): Promise<DesignOutput> {\n const loader = getDesignKitLoader(ctx.projectRoot);\n const action = input.action ?? 'list';\n const stack: DesignStack | undefined =\n input.stack && isDesignStack(input.stack) ? input.stack : undefined;\n\n if (action === 'foundations') {\n const text = await loader.foundationsText(stack);\n return { action, stack, output: text || 'No foundations document is installed.' };\n }\n\n if (action === 'use') {\n const kitId = input.kit?.trim();\n if (!kitId) {\n const menu = await loader.menuText();\n return { action, output: `No kit id provided.\\n\\n${menu}` };\n }\n const manifest = await loader.find(kitId);\n if (!manifest) {\n const menu = await loader.menuText();\n return { action, kit: kitId, output: `Kit \"${kitId}\" not found.\\n\\n${menu}` };\n }\n const resolvedStack = stack ?? manifest.stacks[0] ?? 'web';\n const body = await loader.readBody(manifest.id, resolvedStack);\n const rawTokens = await loader.readTokens(manifest.id);\n // Preserve any persisted overrides; merge in any passed with `use`.\n const persisted = await loadActiveKit(ctx.projectRoot);\n const keepOverrides =\n persisted?.kit === manifest.id ? (persisted.overrides ?? {}) : {};\n const overrides: Overrides = { ...keepOverrides, ...normalizeOverrides(input.set) };\n const tokens = rawTokens ? applyTokenOverrides(rawTokens, overrides) : rawTokens;\n\n setActiveKit(ctx, manifest.id, resolvedStack, overrides);\n await recordKitChoice(\n ctx.projectRoot,\n manifest.id,\n resolvedStack,\n 'design-tool',\n new Date().toISOString(),\n Object.keys(overrides).length ? overrides : undefined,\n );\n\n const ovLine = Object.keys(overrides).length\n ? `\\nActive color overrides: ${Object.entries(overrides)\n .map(([k, v]) => `${k}=${v}`)\n .join(', ')}\\n`\n : '';\n const header =\n `# Active design kit: ${manifest.name} (${manifest.id}) \u2014 stack: ${resolvedStack}\\n` +\n `${manifest.aesthetic}\\n${ovLine}\\n` +\n 'Implement the UI faithfully to this spec. Keep light/dark, responsive, and WCAG AA.\\n';\n const tokenBlock = tokens\n ? `\\n## Token snapshot (overrides applied)\\n\\`\\`\\`json\\n${JSON.stringify(tokens, null, 2)}\\n\\`\\`\\`\\n` +\n 'Tip: run `design {action:\"materialize\"}` to write these tokens to a real theme file.\\n'\n : '';\n return {\n action,\n kit: manifest.id,\n stack: resolvedStack,\n output: `${header}${tokenBlock}\\n${body}`,\n };\n }\n\n if (action === 'set') {\n const patch = normalizeOverrides(input.set);\n if (Object.keys(patch).length === 0) {\n return { action, output: 'No overrides given. Pass set:{ \"primary\": \"oklch(\u2026)\" }.' };\n }\n const merged = await recordOverrides(ctx.projectRoot, patch, new Date().toISOString());\n if (!merged) {\n return {\n action,\n output: 'No active kit. Pick one first: `design {action:\"use\", kit:\"<id>\"}`.',\n };\n }\n setDesignOverrides(ctx, merged);\n return {\n action,\n output:\n `Overrides updated. Active overrides: ${Object.entries(merged)\n .map(([k, v]) => `${k}=${v}`)\n .join(', ')}\\n` +\n 'These win over kit tokens. Run `design {action:\"materialize\"}` to write them to a theme file.',\n };\n }\n\n if (action === 'materialize') {\n const active = await loadActiveKit(ctx.projectRoot);\n if (!active) {\n return {\n action,\n output: 'No active kit. Pick one first: `design {action:\"use\", kit:\"<id>\"}`.',\n };\n }\n const resolvedStack: DesignStack =\n stack ?? (active.stack && isDesignStack(active.stack) ? active.stack : 'web');\n const rawTokens = await loader.readTokens(active.kit);\n if (!rawTokens) {\n return { action, kit: active.kit, output: `Kit \"${active.kit}\" has no tokens.json.` };\n }\n const tokens = applyTokenOverrides(rawTokens, active.overrides);\n const result = materializeTokens({\n tokens,\n stack: resolvedStack,\n kitId: active.kit,\n outPath: input.out,\n });\n // Containment: result.path derives from caller-supplied input.out and\n // may be either relative (joined under projectRoot) or absolute\n // (used as-is). Pin the write inside the project root, mirroring the\n // scaffold tool.\n //\n // #249 (design.ts escape check): resolve both sides through fs.realpath\n // before the relative check, so symlinks / bind mounts (e.g. /tmp on\n // CI runners is often a symlink to /private/tmp) can't smuggle an\n // out-of-root path past the prefix-startsWith-`..` guard. The\n // destination file does not exist yet, so realpath the parent\n // directory and re-join the basename.\n //\n // Note: on Windows, path.join(absoluteA, absoluteB) concatenates\n // literally (path.join('C:\\\\A\\\\B', 'C:\\\\A\\\\C.css') === 'C:\\\\A\\\\B\\\\C:\\\\A\\\\C.css')\n // rather than collapsing absoluteB onto the drive root. Treating\n // absolute result.path as absolute (not as a join-input) keeps the\n // behavior consistent across platforms and is what the test asserts.\n const root = await resolveReal(ctx.projectRoot);\n const absResolved = path.isAbsolute(result.path)\n ? path.resolve(result.path)\n : path.resolve(path.join(ctx.projectRoot, result.path));\n const absParent = await resolveReal(path.dirname(absResolved));\n const abs = path.join(absParent, path.basename(absResolved));\n const rel = path.relative(root, abs);\n if (rel.startsWith('..') || path.isAbsolute(rel)) {\n throw new Error(\n `design: materialize path \"${result.path}\" would escape the project root`,\n );\n }\n let exists = false;\n try {\n await fs.access(abs);\n exists = true;\n } catch {\n // does not exist \u2014 safe to write\n }\n if (exists && !input.force) {\n return {\n action,\n kit: active.kit,\n stack: resolvedStack,\n path: result.path,\n output:\n `${result.path} already exists. Re-run with force:true to overwrite, or write this ` +\n `${result.format} yourself:\\n\\n\\`\\`\\`\\n${result.content}\\n\\`\\`\\``,\n };\n }\n await fs.mkdir(path.dirname(abs), { recursive: true });\n await fs.writeFile(abs, result.content);\n return {\n action,\n kit: active.kit,\n stack: resolvedStack,\n path: result.path,\n output:\n `Wrote ${result.format} to ${result.path}. Import these tokens in your UI so the kit ` +\n `palette is the source of truth. ${exists ? '(overwrote existing file)' : ''}`,\n };\n }\n\n if (action === 'verify') {\n const active = await loadActiveKit(ctx.projectRoot);\n if (!active) {\n return {\n action,\n output: 'No active kit to verify against. Pick one: `design {action:\"use\", kit:\"<id>\"}`.',\n };\n }\n const rawTokens = await loader.readTokens(active.kit);\n if (!rawTokens) {\n return { action, kit: active.kit, output: `Kit \"${active.kit}\" has no tokens.json.` };\n }\n const tokens = applyTokenOverrides(rawTokens, active.overrides);\n const report = await runDesignVerify(ctx.projectRoot, tokens, input.files);\n const pct = Math.round(report.score * 100);\n const top = report.violations\n .slice(0, 25)\n .map((v) => ` ${v.file}:${v.line} \u2014 ${v.reason}: ${v.snippet}`)\n .join('\\n');\n const summary =\n `Adherence: ${pct}% on-palette across ${report.filesScanned} file(s). ` +\n `${report.violations.length} violation(s).` +\n (report.violations.length\n ? `\\n${top}${report.violations.length > 25 ? `\\n \u2026and ${report.violations.length - 25} more` : ''}` +\n `\\n\\nReplace off-palette colors with kit tokens (or the materialized CSS vars / token utilities).`\n : '\\nNo off-palette colors found \u2014 UI adheres to the kit palette.');\n return {\n action,\n kit: active.kit,\n output: summary,\n score: report.score,\n violations: report.violations.length,\n };\n }\n\n // Default: list\n const menu = await loader.menuText();\n return {\n action: 'list',\n output:\n (menu || 'No design kits are installed.') +\n '\\n\\nLoad one with `design {action:\"use\", kit:\"<id>\", stack:\"<stack>\"}`.',\n };\n },\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["menu"]
|
|
7
|
+
}
|
package/dist/diff.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Tool } from '@wrongstack/core';
|
|
2
|
-
|
|
1
|
+
import type { Tool } from '@wrongstack/core';
|
|
3
2
|
interface DiffInput {
|
|
4
3
|
path?: string | undefined;
|
|
5
4
|
files?: string | string[] | undefined;
|
|
@@ -15,6 +14,6 @@ interface DiffOutput {
|
|
|
15
14
|
truncated: boolean;
|
|
16
15
|
mode: string;
|
|
17
16
|
}
|
|
18
|
-
declare const diffTool: Tool<DiffInput, DiffOutput>;
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
export declare const diffTool: Tool<DiffInput, DiffOutput>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAG7C,UAAU,SAAS;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;IACtC,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvB,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,IAAI,CAAC,EAAE,SAAS,GAAG,cAAc,GAAG,MAAM,GAAG,SAAS,CAAC;IACvD,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,UAAU,CA8DhD,CAAC"}
|
package/dist/diff.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { spawn } from 'node:child_process';
|
|
2
|
-
import { statSync } from 'node:fs';
|
|
3
|
-
import * as fs from 'node:fs/promises';
|
|
4
|
-
import * as path from 'node:path';
|
|
5
|
-
import * as Core from '@wrongstack/core';
|
|
6
|
-
import { buildChildEnv } from '@wrongstack/core';
|
|
7
|
-
|
|
8
1
|
// src/diff.ts
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import { statSync } from "node:fs";
|
|
4
|
+
import * as fs from "node:fs/promises";
|
|
5
|
+
import * as path2 from "node:path";
|
|
6
|
+
import { buildChildEnv } from "@wrongstack/core";
|
|
7
|
+
|
|
8
|
+
// src/_util.ts
|
|
9
|
+
import * as path from "node:path";
|
|
10
|
+
import * as Core from "@wrongstack/core";
|
|
9
11
|
function resolvePath(input, ctx) {
|
|
10
12
|
return path.isAbsolute(input) ? path.normalize(input) : path.resolve(ctx.workingDir ?? ctx.cwd, input);
|
|
11
13
|
}
|
|
@@ -111,11 +113,11 @@ function findGitDir(cwd) {
|
|
|
111
113
|
let dir = cwd;
|
|
112
114
|
for (let i = 0; i < 20; i++) {
|
|
113
115
|
try {
|
|
114
|
-
const stat2 = statSync(
|
|
116
|
+
const stat2 = statSync(path2.join(dir, ".git"));
|
|
115
117
|
if (stat2.isDirectory()) return dir;
|
|
116
118
|
} catch {
|
|
117
119
|
}
|
|
118
|
-
const parent =
|
|
120
|
+
const parent = path2.dirname(dir);
|
|
119
121
|
if (parent === dir) break;
|
|
120
122
|
dir = parent;
|
|
121
123
|
}
|
|
@@ -175,7 +177,7 @@ function formatWithLineNumbers(file, lines) {
|
|
|
175
177
|
return `--- ${file} (line-numbered dump, not a unified diff) ---
|
|
176
178
|
${numbered}`;
|
|
177
179
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
+
export {
|
|
181
|
+
diffTool
|
|
182
|
+
};
|
|
180
183
|
//# sourceMappingURL=diff.js.map
|
|
181
|
-
//# sourceMappingURL=diff.js.map
|