@specship/specship-darwin-arm64 0.29.0 → 0.30.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/bin/specship +1 -1
- package/lib/dist/.claude-plugin/plugin.json +15 -3
- package/lib/dist/activation/cheatsheet.d.ts +10 -7
- package/lib/dist/activation/cheatsheet.d.ts.map +1 -1
- package/lib/dist/activation/cheatsheet.js +21 -5
- package/lib/dist/activation/cheatsheet.js.map +1 -1
- package/lib/dist/activation/hook-output.d.ts +75 -2
- package/lib/dist/activation/hook-output.d.ts.map +1 -1
- package/lib/dist/activation/hook-output.js +114 -3
- package/lib/dist/activation/hook-output.js.map +1 -1
- package/lib/dist/activation/search-intercept.d.ts +20 -7
- package/lib/dist/activation/search-intercept.d.ts.map +1 -1
- package/lib/dist/activation/search-intercept.js +27 -5
- package/lib/dist/activation/search-intercept.js.map +1 -1
- package/lib/dist/activation/steering.d.ts +7 -4
- package/lib/dist/activation/steering.d.ts.map +1 -1
- package/lib/dist/activation/steering.js +10 -8
- package/lib/dist/activation/steering.js.map +1 -1
- package/lib/dist/agents/detect.d.ts +32 -0
- package/lib/dist/agents/detect.d.ts.map +1 -0
- package/lib/dist/agents/detect.js +54 -0
- package/lib/dist/agents/detect.js.map +1 -0
- package/lib/dist/agents/recent-project.d.ts +18 -0
- package/lib/dist/agents/recent-project.d.ts.map +1 -0
- package/lib/dist/agents/recent-project.js +92 -0
- package/lib/dist/agents/recent-project.js.map +1 -0
- package/lib/dist/analytics/canonical-tools.d.ts +23 -0
- package/lib/dist/analytics/canonical-tools.d.ts.map +1 -0
- package/lib/dist/analytics/canonical-tools.js +36 -0
- package/lib/dist/analytics/canonical-tools.js.map +1 -0
- package/lib/dist/analytics/canonical-tools.json +16 -0
- package/lib/dist/analytics/specship-impact.d.ts +3 -2
- package/lib/dist/analytics/specship-impact.d.ts.map +1 -1
- package/lib/dist/analytics/specship-impact.js +6 -4
- package/lib/dist/analytics/specship-impact.js.map +1 -1
- package/lib/dist/bin/specship.js +215 -170
- package/lib/dist/bin/specship.js.map +1 -1
- package/lib/dist/bin/uninstall.js +2 -2
- package/lib/dist/bin/uninstall.js.map +1 -1
- package/lib/dist/claudemd/audit.d.ts +12 -3
- package/lib/dist/claudemd/audit.d.ts.map +1 -1
- package/lib/dist/claudemd/audit.js +65 -22
- package/lib/dist/claudemd/audit.js.map +1 -1
- package/lib/dist/commands/specship/spec.md +9 -0
- package/lib/dist/db/migrations.d.ts +1 -1
- package/lib/dist/db/migrations.d.ts.map +1 -1
- package/lib/dist/db/migrations.js +18 -4
- package/lib/dist/db/migrations.js.map +1 -1
- package/lib/dist/db/schema.sql +8 -0
- package/lib/dist/db/spec-queries.d.ts +13 -1
- package/lib/dist/db/spec-queries.d.ts.map +1 -1
- package/lib/dist/db/spec-queries.js +21 -0
- package/lib/dist/db/spec-queries.js.map +1 -1
- package/lib/dist/enforce/changed-files.d.ts +7 -0
- package/lib/dist/enforce/changed-files.d.ts.map +1 -1
- package/lib/dist/enforce/changed-files.js +17 -0
- package/lib/dist/enforce/changed-files.js.map +1 -1
- package/lib/dist/enforce/enforce.d.ts +35 -1
- package/lib/dist/enforce/enforce.d.ts.map +1 -1
- package/lib/dist/enforce/enforce.js +66 -2
- package/lib/dist/enforce/enforce.js.map +1 -1
- package/lib/dist/extraction/index.d.ts +50 -4
- package/lib/dist/extraction/index.d.ts.map +1 -1
- package/lib/dist/extraction/index.js +105 -13
- package/lib/dist/extraction/index.js.map +1 -1
- package/lib/dist/extraction/parse-warnings.d.ts +16 -0
- package/lib/dist/extraction/parse-warnings.d.ts.map +1 -0
- package/lib/dist/extraction/parse-warnings.js +30 -0
- package/lib/dist/extraction/parse-warnings.js.map +1 -0
- package/lib/dist/extraction/tree-sitter.d.ts +27 -0
- package/lib/dist/extraction/tree-sitter.d.ts.map +1 -1
- package/lib/dist/extraction/tree-sitter.js +168 -1
- package/lib/dist/extraction/tree-sitter.js.map +1 -1
- package/lib/dist/health/smoke-check.js +1 -1
- package/lib/dist/health/smoke-check.js.map +1 -1
- package/lib/dist/hooks/hooks.json +16 -1
- package/lib/dist/index.d.ts +63 -3
- package/lib/dist/index.d.ts.map +1 -1
- package/lib/dist/index.js +235 -9
- package/lib/dist/index.js.map +1 -1
- package/lib/dist/installer/agent-record.d.ts +80 -0
- package/lib/dist/installer/agent-record.d.ts.map +1 -0
- package/lib/dist/installer/agent-record.js +351 -0
- package/lib/dist/installer/agent-record.js.map +1 -0
- package/lib/dist/installer/auto-migrate.d.ts +56 -0
- package/lib/dist/installer/auto-migrate.d.ts.map +1 -0
- package/lib/dist/installer/auto-migrate.js +328 -0
- package/lib/dist/installer/auto-migrate.js.map +1 -0
- package/lib/dist/installer/index.d.ts +37 -8
- package/lib/dist/installer/index.d.ts.map +1 -1
- package/lib/dist/installer/index.js +156 -46
- package/lib/dist/installer/index.js.map +1 -1
- package/lib/dist/installer/install-defaults.d.ts +4 -3
- package/lib/dist/installer/install-defaults.d.ts.map +1 -1
- package/lib/dist/installer/install-defaults.js +6 -5
- package/lib/dist/installer/install-defaults.js.map +1 -1
- package/lib/dist/installer/{config-writer.d.ts → targets/claude-config-writer.d.ts} +1 -1
- package/lib/dist/installer/targets/claude-config-writer.d.ts.map +1 -0
- package/lib/dist/installer/{config-writer.js → targets/claude-config-writer.js} +7 -6
- package/lib/dist/installer/targets/claude-config-writer.js.map +1 -0
- package/lib/dist/installer/targets/claude-projects.d.ts +9 -0
- package/lib/dist/installer/targets/claude-projects.d.ts.map +1 -0
- package/lib/dist/installer/targets/claude-projects.js +151 -0
- package/lib/dist/installer/targets/claude-projects.js.map +1 -0
- package/lib/dist/installer/targets/claude.d.ts +28 -1
- package/lib/dist/installer/targets/claude.d.ts.map +1 -1
- package/lib/dist/installer/targets/claude.js +39 -20
- package/lib/dist/installer/targets/claude.js.map +1 -1
- package/lib/dist/installer/targets/feature-parity.d.ts +28 -0
- package/lib/dist/installer/targets/feature-parity.d.ts.map +1 -0
- package/lib/dist/installer/targets/feature-parity.js +32 -0
- package/lib/dist/installer/targets/feature-parity.js.map +1 -0
- package/lib/dist/installer/{gemini-commands.d.ts → targets/gemini-commands.d.ts} +7 -3
- package/lib/dist/installer/targets/gemini-commands.d.ts.map +1 -0
- package/lib/dist/installer/{gemini-commands.js → targets/gemini-commands.js} +35 -14
- package/lib/dist/installer/targets/gemini-commands.js.map +1 -0
- package/lib/dist/installer/targets/gemini-projects.d.ts +11 -0
- package/lib/dist/installer/targets/gemini-projects.d.ts.map +1 -0
- package/lib/dist/installer/targets/gemini-projects.js +84 -0
- package/lib/dist/installer/targets/gemini-projects.js.map +1 -0
- package/lib/dist/installer/targets/gemini.d.ts +94 -8
- package/lib/dist/installer/targets/gemini.d.ts.map +1 -1
- package/lib/dist/installer/targets/gemini.js +392 -33
- package/lib/dist/installer/targets/gemini.js.map +1 -1
- package/lib/dist/installer/targets/registry.d.ts +8 -1
- package/lib/dist/installer/targets/registry.d.ts.map +1 -1
- package/lib/dist/installer/targets/registry.js +14 -5
- package/lib/dist/installer/targets/registry.js.map +1 -1
- package/lib/dist/installer/targets/shared.d.ts +44 -1
- package/lib/dist/installer/targets/shared.d.ts.map +1 -1
- package/lib/dist/installer/targets/shared.js +130 -3
- package/lib/dist/installer/targets/shared.js.map +1 -1
- package/lib/dist/installer/targets/types.d.ts +23 -1
- package/lib/dist/installer/targets/types.d.ts.map +1 -1
- package/lib/dist/jira/auto-publish.d.ts +22 -2
- package/lib/dist/jira/auto-publish.d.ts.map +1 -1
- package/lib/dist/jira/auto-publish.js +54 -9
- package/lib/dist/jira/auto-publish.js.map +1 -1
- package/lib/dist/jira/board-first.d.ts +15 -2
- package/lib/dist/jira/board-first.d.ts.map +1 -1
- package/lib/dist/jira/board-first.js +16 -0
- package/lib/dist/jira/board-first.js.map +1 -1
- package/lib/dist/jira/ci-publish.d.ts +72 -0
- package/lib/dist/jira/ci-publish.d.ts.map +1 -0
- package/lib/dist/jira/ci-publish.js +162 -0
- package/lib/dist/jira/ci-publish.js.map +1 -0
- package/lib/dist/jira/publish.d.ts +23 -0
- package/lib/dist/jira/publish.d.ts.map +1 -1
- package/lib/dist/jira/publish.js +0 -0
- package/lib/dist/jira/publish.js.map +1 -1
- package/lib/dist/jira/regression-pack.d.ts.map +1 -1
- package/lib/dist/jira/regression-pack.js +7 -1
- package/lib/dist/jira/regression-pack.js.map +1 -1
- package/lib/dist/jira/repo-config.d.ts.map +1 -1
- package/lib/dist/jira/repo-config.js +8 -0
- package/lib/dist/jira/repo-config.js.map +1 -1
- package/lib/dist/jira/types.d.ts +8 -0
- package/lib/dist/jira/types.d.ts.map +1 -1
- package/lib/dist/jira/types.js.map +1 -1
- package/lib/dist/knowledge/enforce.d.ts.map +1 -1
- package/lib/dist/knowledge/enforce.js +6 -1
- package/lib/dist/knowledge/enforce.js.map +1 -1
- package/lib/dist/mcp/jira-tools.d.ts +5 -0
- package/lib/dist/mcp/jira-tools.d.ts.map +1 -1
- package/lib/dist/mcp/jira-tools.js +59 -4
- package/lib/dist/mcp/jira-tools.js.map +1 -1
- package/lib/dist/mcp/proxy.d.ts.map +1 -1
- package/lib/dist/mcp/proxy.js +2 -1
- package/lib/dist/mcp/proxy.js.map +1 -1
- package/lib/dist/mcp/server-instructions.d.ts +16 -10
- package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
- package/lib/dist/mcp/server-instructions.js +69 -20
- package/lib/dist/mcp/server-instructions.js.map +1 -1
- package/lib/dist/mcp/session.d.ts +11 -0
- package/lib/dist/mcp/session.d.ts.map +1 -1
- package/lib/dist/mcp/session.js +43 -1
- package/lib/dist/mcp/session.js.map +1 -1
- package/lib/dist/mcp/tools.d.ts.map +1 -1
- package/lib/dist/mcp/tools.js +8 -0
- package/lib/dist/mcp/tools.js.map +1 -1
- package/lib/dist/reflect/apply.d.ts +2 -2
- package/lib/dist/reflect/apply.d.ts.map +1 -1
- package/lib/dist/reflect/apply.js +6 -5
- package/lib/dist/reflect/apply.js.map +1 -1
- package/lib/dist/reflect/miner.d.ts.map +1 -1
- package/lib/dist/reflect/miner.js +28 -15
- package/lib/dist/reflect/miner.js.map +1 -1
- package/lib/dist/reflect/session-outcomes.d.ts.map +1 -1
- package/lib/dist/reflect/session-outcomes.js +8 -3
- package/lib/dist/reflect/session-outcomes.js.map +1 -1
- package/lib/dist/reflect/targets.d.ts.map +1 -1
- package/lib/dist/reflect/targets.js +25 -5
- package/lib/dist/reflect/targets.js.map +1 -1
- package/lib/dist/reflect/types.d.ts +7 -0
- package/lib/dist/reflect/types.d.ts.map +1 -1
- package/lib/dist/resolution/spec-link-resolver.d.ts +14 -2
- package/lib/dist/resolution/spec-link-resolver.d.ts.map +1 -1
- package/lib/dist/resolution/spec-link-resolver.js +13 -3
- package/lib/dist/resolution/spec-link-resolver.js.map +1 -1
- package/lib/dist/server/canonical-tools.js +50 -0
- package/lib/dist/server/cli.js +2 -2
- package/lib/dist/server/host-profiles.js +39 -0
- package/lib/dist/server/ingest/index.js +2 -1
- package/lib/dist/server/ingest/ingestor.js +195 -76
- package/lib/dist/server/ingest/project-paths.js +8 -2
- package/lib/dist/server/ingest/recorded-projects.js +43 -0
- package/lib/dist/server/ingest/specship-classify.js +7 -2
- package/lib/dist/server/ingest/transcripts/claude-jsonl.js +54 -0
- package/lib/dist/server/ingest/transcripts/claude.js +64 -0
- package/lib/dist/server/ingest/transcripts/gemini.js +469 -0
- package/lib/dist/server/ingest/transcripts/index.js +14 -0
- package/lib/dist/server/ingest/{parser.js → transcripts/shared.js} +3 -49
- package/lib/dist/server/ingest/transcripts/types.js +4 -0
- package/lib/dist/server/ingest/watcher.js +31 -30
- package/lib/dist/server/routes/claude.js +27 -10
- package/lib/dist/server/routes/graph.js +64 -3
- package/lib/dist/server/routes/mcp.js +57 -15
- package/lib/dist/server/routes/memory.js +54 -35
- package/lib/dist/server/routes/projects.js +78 -7
- package/lib/dist/server/routes/spec.js +125 -0
- package/lib/dist/server/server.js +8 -2
- package/lib/dist/skills/spec-author/SKILL.md +1 -1
- package/lib/dist/skills/spec-author/references/gap-questions.md +1 -1
- package/lib/dist/spec-lint/lint.d.ts +26 -1
- package/lib/dist/spec-lint/lint.d.ts.map +1 -1
- package/lib/dist/spec-lint/lint.js +96 -7
- package/lib/dist/spec-lint/lint.js.map +1 -1
- package/lib/dist/sync/worktree.d.ts +48 -0
- package/lib/dist/sync/worktree.d.ts.map +1 -1
- package/lib/dist/sync/worktree.js +109 -0
- package/lib/dist/sync/worktree.js.map +1 -1
- package/lib/dist/ui/assets/bricolage-latin-C23fTOVi.woff2 +0 -0
- package/lib/dist/ui/assets/bricolage-latin-ext-B82pxkPf.woff2 +0 -0
- package/lib/dist/ui/assets/index-54vorjyq.css +1 -0
- package/lib/dist/ui/assets/index-BZQonCVb.js +52 -0
- package/lib/dist/ui/assets/space-grotesk-latin-DPT1xrvW.woff2 +0 -0
- package/lib/dist/ui/assets/space-grotesk-latin-ext-wJGaI8U0.woff2 +0 -0
- package/lib/dist/ui/index.html +2 -2
- package/lib/dist/update/updater.d.ts +6 -0
- package/lib/dist/update/updater.d.ts.map +1 -1
- package/lib/dist/update/updater.js +13 -1
- package/lib/dist/update/updater.js.map +1 -1
- package/lib/dist/workflows/agents/claude.d.ts +9 -0
- package/lib/dist/workflows/agents/claude.d.ts.map +1 -1
- package/lib/dist/workflows/agents/claude.js +22 -3
- package/lib/dist/workflows/agents/claude.js.map +1 -1
- package/lib/dist/workflows/agents/gemini-version.d.ts +18 -0
- package/lib/dist/workflows/agents/gemini-version.d.ts.map +1 -0
- package/lib/dist/workflows/agents/gemini-version.js +81 -0
- package/lib/dist/workflows/agents/gemini-version.js.map +1 -0
- package/lib/dist/workflows/agents/gemini.d.ts +1 -1
- package/lib/dist/workflows/agents/gemini.d.ts.map +1 -1
- package/lib/dist/workflows/agents/gemini.js +12 -2
- package/lib/dist/workflows/agents/gemini.js.map +1 -1
- package/lib/dist/workflows/agents/index.d.ts +2 -0
- package/lib/dist/workflows/agents/index.d.ts.map +1 -1
- package/lib/dist/workflows/agents/index.js +5 -0
- package/lib/dist/workflows/agents/index.js.map +1 -1
- package/lib/dist/workflows/agents/types.d.ts +13 -0
- package/lib/dist/workflows/agents/types.d.ts.map +1 -1
- package/lib/dist/workflows/agents/types.js.map +1 -1
- package/lib/dist/workflows/condition-evaluator.d.ts +8 -0
- package/lib/dist/workflows/condition-evaluator.d.ts.map +1 -1
- package/lib/dist/workflows/condition-evaluator.js +7 -0
- package/lib/dist/workflows/condition-evaluator.js.map +1 -1
- package/lib/dist/workflows/defaults/claude-design-implement.yaml +11 -11
- package/lib/dist/workflows/defaults/spec-author.yaml +9 -9
- package/lib/dist/workflows/defaults/spec-fix.yaml +8 -8
- package/lib/dist/workflows/defaults/spec-implement.yaml +38 -23
- package/lib/dist/workflows/defaults/spec-relink.yaml +5 -5
- package/lib/dist/workflows/defaults/spec-verify.yaml +3 -3
- package/lib/dist/workflows/executor.d.ts +7 -0
- package/lib/dist/workflows/executor.d.ts.map +1 -1
- package/lib/dist/workflows/executor.js +22 -5
- package/lib/dist/workflows/executor.js.map +1 -1
- package/lib/node_modules/.package-lock.json +1 -1
- package/lib/package.json +3 -2
- package/package.json +1 -1
- package/lib/dist/installer/config-writer.d.ts.map +0 -1
- package/lib/dist/installer/config-writer.js.map +0 -1
- package/lib/dist/installer/gemini-commands.d.ts.map +0 -1
- package/lib/dist/installer/gemini-commands.js.map +0 -1
- package/lib/dist/ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/lib/dist/ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/lib/dist/ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/lib/dist/ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/lib/dist/ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/lib/dist/ui/assets/index-BzuUWUAE.js +0 -50
- package/lib/dist/ui/assets/index-ezwX2EfG.css +0 -1
|
@@ -55,9 +55,16 @@ exports.gitWorktreeRoot = gitWorktreeRoot;
|
|
|
55
55
|
exports.detectWorktreeIndexMismatch = detectWorktreeIndexMismatch;
|
|
56
56
|
exports.worktreeMismatchWarning = worktreeMismatchWarning;
|
|
57
57
|
exports.worktreeMismatchNotice = worktreeMismatchNotice;
|
|
58
|
+
exports.readGitHead = readGitHead;
|
|
59
|
+
exports.uncommittedTrackedFingerprint = uncommittedTrackedFingerprint;
|
|
60
|
+
exports.computeIndexFreshness = computeIndexFreshness;
|
|
61
|
+
exports.indexStaleNotice = indexStaleNotice;
|
|
62
|
+
exports.formatRevision = formatRevision;
|
|
63
|
+
exports.indexFreshnessJsonFields = indexFreshnessJsonFields;
|
|
58
64
|
const fs = __importStar(require("fs"));
|
|
59
65
|
const path = __importStar(require("path"));
|
|
60
66
|
const child_process_1 = require("child_process");
|
|
67
|
+
const crypto_1 = require("crypto");
|
|
61
68
|
/**
|
|
62
69
|
* Absolute, symlink-resolved toplevel of the git working tree that `dir`
|
|
63
70
|
* belongs to, or null when `dir` isn't inside a git repo (or git is missing).
|
|
@@ -125,6 +132,108 @@ function worktreeMismatchNotice(m) {
|
|
|
125
132
|
`and symbols changed only here are missing. Run "specship init -i" here for a ` +
|
|
126
133
|
`worktree-local index.`);
|
|
127
134
|
}
|
|
135
|
+
// =============================================================================
|
|
136
|
+
// Indexed revision + staleness (REQ-MULTIDEV-004)
|
|
137
|
+
// =============================================================================
|
|
138
|
+
/** Run git in `dir`; returns trimmed stdout, or null on any failure. Never throws. */
|
|
139
|
+
function git(dir, args) {
|
|
140
|
+
try {
|
|
141
|
+
return (0, child_process_1.execFileSync)('git', args, {
|
|
142
|
+
cwd: dir,
|
|
143
|
+
encoding: 'utf8',
|
|
144
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
145
|
+
windowsHide: true,
|
|
146
|
+
maxBuffer: 256 * 1024 * 1024,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/** Pathspec limiting git output to `dir`, excluding SpecShip's own `.specship/`. */
|
|
154
|
+
const NON_SPECSHIP_PATHSPEC = ['--', '.', ':(exclude).specship'];
|
|
155
|
+
/**
|
|
156
|
+
* The checkout's current HEAD: commit sha plus branch name (`null` on a
|
|
157
|
+
* detached HEAD). Returns null outside a git repo, when git is missing, or
|
|
158
|
+
* when the repo has no commit yet. Never throws.
|
|
159
|
+
*/
|
|
160
|
+
function readGitHead(dir) {
|
|
161
|
+
const commit = git(dir, ['rev-parse', '--verify', '-q', 'HEAD'])?.trim();
|
|
162
|
+
if (!commit)
|
|
163
|
+
return null;
|
|
164
|
+
// `symbolic-ref -q` exits non-zero with no output on a detached HEAD.
|
|
165
|
+
const branch = git(dir, ['symbolic-ref', '--short', '-q', 'HEAD'])?.trim() || null;
|
|
166
|
+
return { branch, commit };
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Fingerprint of the uncommitted tracked state under `dir` (outside
|
|
170
|
+
* `.specship/`): a hash over `git status --porcelain --untracked-files=no`
|
|
171
|
+
* plus `git diff HEAD`. Two calls return the same value exactly when the
|
|
172
|
+
* working tree's tracked changes are identical — so an index synced after an
|
|
173
|
+
* edit is fresh until the edits change again. Null when git can't answer.
|
|
174
|
+
*/
|
|
175
|
+
function uncommittedTrackedFingerprint(dir) {
|
|
176
|
+
const status = git(dir, ['status', '--porcelain', '--untracked-files=no', ...NON_SPECSHIP_PATHSPEC]);
|
|
177
|
+
if (status === null)
|
|
178
|
+
return null;
|
|
179
|
+
if (status.trim().length === 0)
|
|
180
|
+
return 'clean';
|
|
181
|
+
const diff = git(dir, ['diff', 'HEAD', '--no-ext-diff', '--binary', ...NON_SPECSHIP_PATHSPEC]);
|
|
182
|
+
if (diff === null)
|
|
183
|
+
return null;
|
|
184
|
+
return (0, crypto_1.createHash)('sha256').update(status).update('\0').update(diff).digest('hex');
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Pure staleness verdict. `worktreeChanged` is true when the checkout's
|
|
188
|
+
* uncommitted tracked changes differ from those present at index time.
|
|
189
|
+
*/
|
|
190
|
+
function computeIndexFreshness(recorded, head, worktreeChanged) {
|
|
191
|
+
const reasons = [];
|
|
192
|
+
if (recorded.commit !== head.commit)
|
|
193
|
+
reasons.push('commit-moved');
|
|
194
|
+
if (worktreeChanged)
|
|
195
|
+
reasons.push('uncommitted-changes');
|
|
196
|
+
return {
|
|
197
|
+
indexedBranch: recorded.branch,
|
|
198
|
+
indexedCommit: recorded.commit,
|
|
199
|
+
headBranch: head.branch,
|
|
200
|
+
headCommit: head.commit,
|
|
201
|
+
stale: reasons.length > 0,
|
|
202
|
+
reasons,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
/** One-line staleness notice naming `specship sync` as the fix. */
|
|
206
|
+
function indexStaleNotice(f) {
|
|
207
|
+
const short = (c) => c.slice(0, 7);
|
|
208
|
+
const parts = [];
|
|
209
|
+
if (f.reasons.includes('commit-moved')) {
|
|
210
|
+
parts.push(`indexed at ${short(f.indexedCommit)}, HEAD ${short(f.headCommit)}`);
|
|
211
|
+
}
|
|
212
|
+
if (f.reasons.includes('uncommitted-changes')) {
|
|
213
|
+
parts.push('uncommitted changes differ from when it was indexed');
|
|
214
|
+
}
|
|
215
|
+
return `Index may be stale (${parts.join('; ')}) — run \`specship sync\``;
|
|
216
|
+
}
|
|
217
|
+
/** `ref (branch)` / `ref (detached)` label for human output. */
|
|
218
|
+
function formatRevision(branch, commit) {
|
|
219
|
+
return `${commit.slice(0, 7)} (${branch ?? 'detached'})`;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* The `specship status --json` fields for a freshness verdict. Empty when
|
|
223
|
+
* freshness is null (no git / nothing recorded), so the keys are absent.
|
|
224
|
+
*/
|
|
225
|
+
function indexFreshnessJsonFields(f) {
|
|
226
|
+
if (!f)
|
|
227
|
+
return {};
|
|
228
|
+
return {
|
|
229
|
+
indexedBranch: f.indexedBranch,
|
|
230
|
+
indexedCommit: f.indexedCommit,
|
|
231
|
+
headBranch: f.headBranch,
|
|
232
|
+
headCommit: f.headCommit,
|
|
233
|
+
indexStale: f.stale,
|
|
234
|
+
staleReasons: f.reasons,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
128
237
|
/** Resolve symlinks where possible so tmp/realpath quirks don't break equality. */
|
|
129
238
|
function realpath(p) {
|
|
130
239
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worktree.js","sourceRoot":"","sources":["../../src/sync/worktree.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"worktree.js","sourceRoot":"","sources":["../../src/sync/worktree.ts"],"names":[],"mappings":"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"}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@font-face{font-family:Geist Mono Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/geist-mono-cyrillic-ext-wght-normal-I4S5GZfc.woff2) format("woff2-variations");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Geist Mono Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/geist-mono-cyrillic-wght-normal-BmXc_FBt.woff2) format("woff2-variations");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Geist Mono Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/geist-mono-symbols2-wght-normal-GZpp1pK2.woff2) format("woff2-variations");unicode-range:U+2000-2001,U+2004-2008,U+200A,U+23B8-23BD,U+2500-259F}@font-face{font-family:Geist Mono Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/geist-mono-vietnamese-wght-normal-D8KDMBhC.woff2) format("woff2-variations");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Geist Mono Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/geist-mono-latin-ext-wght-normal-DrnZ1wKl.woff2) format("woff2-variations");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Geist Mono Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/geist-mono-latin-wght-normal-B_7UjwxQ.woff2) format("woff2-variations");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root{--bmg-color-canvas: #0A0D10;--bmg-color-bg: #0A0D10;--bmg-color-surface: #0D1115;--bmg-color-surface-alt: #14191E;--bmg-color-surface-deep: #07090B;--bmg-color-surface-raised: #171E24;--bmg-color-sheet: #1F2730;--bmg-color-panel: #14191E;--bmg-color-surface3: #29333C;--bmg-color-popover: rgba(41,51,60,.98);--bmg-color-text: #F4F7F9;--bmg-color-text-strong: #F8FAFC;--bmg-color-text-muted: #C9D1D9;--bmg-color-text-dim: #AAB6C1;--bmg-color-text-faint: #929EAA;--bmg-color-text-disabled: #828E9A;--bmg-color-accent: #2EE59D;--bmg-color-accent-hover: #5CF0B5;--bmg-color-accent-pressed: #1FC683;--bmg-color-hero-end: #14B8A6;--bmg-color-text-off: #56616C;--bmg-color-info: #4CC3FF;--bmg-color-success: #2EE59D;--bmg-color-warning: #FFB547;--bmg-color-warning-hover: #FFC46B;--bmg-color-danger: #FF6B6E;--bmg-color-danger-hover: #FF8285;--bmg-color-violet: #A48BFF;--bmg-color-wash: #FFFFFF;--bmg-color-track: #2A333C;--bmg-color-line-faint: rgba(255,255,255,.05);--bmg-color-line-soft: rgba(255,255,255,.06);--bmg-color-border-quiet: rgba(255,255,255,.09);--bmg-color-border: rgba(255,255,255,.1);--bmg-color-border-strong: rgba(255,255,255,.12);--bmg-color-border-stronger: rgba(255,255,255,.14);--bmg-color-border-active: rgba(255,255,255,.18);--bmg-color-border-hover: rgba(255,255,255,.34);--bmg-color-fill-tile: rgba(255,255,255,.07);--bmg-color-fill-faint: rgba(255,255,255,.045);--bmg-color-fill-soft: rgba(255,255,255,.05);--bmg-color-fill: rgba(255,255,255,.06);--bmg-color-fill-strong: rgba(255,255,255,.08);--bmg-color-wallpaper-ink: rgba(255,255,255,.045);--bmg-color-overlay: rgba(4,6,8,.72);--bmg-color-scrim: rgba(3,4,5,.6);--bmg-color-inset: rgba(10,13,16,.4);--bmg-space-gutter: 20px;--bmg-space-gutter-wide: 26px;--bmg-space-gutter-tight: 24px;--bmg-space-xs: 4px;--bmg-space-sm: 8px;--bmg-space-md: 12px;--bmg-space-lg: 18px;--bmg-space-xl: 24px;--bmg-space-2xl: 32px;--bmg-radius-xs: 8px;--bmg-radius-sm: 10px;--bmg-radius-chip: 11px;--bmg-radius-md: 12px;--bmg-radius-lg: 14px;--bmg-radius-xl: 16px;--bmg-radius-2xl: 18px;--bmg-radius-3xl: 20px;--bmg-radius-sheet: 28px;--bmg-radius-screen: 42px;--bmg-radius-pill: 999px;--bmg-font-size-display: 52px;--bmg-font-size-hero: 44px;--bmg-font-size-h0: 30px;--bmg-font-size-h1: 27px;--bmg-font-size-h2: 23px;--bmg-font-size-h3: 19px;--bmg-font-size-h4: 17px;--bmg-font-size-xl: 16px;--bmg-font-size-cta: 16px;--bmg-font-size-lg: 15px;--bmg-font-size-body: 15px;--bmg-font-size-base: 14px;--bmg-font-size-body-sm: 14px;--bmg-font-size-label: 13px;--bmg-font-size-meta: 13px;--bmg-font-size-meta-sm: 12px;--bmg-font-size-micro: 12px;--bmg-font-size-tiny: 11px;--bmg-font-size-nano: 11px}:root,[data-theme=dark]{color-scheme:dark;--bg-canvas: var(--bmg-color-bg);--bg-canvas-2: var(--bmg-color-surface-deep);--bg-panel: var(--bmg-color-panel);--bg-panel-2: var(--bmg-color-surface-raised);--bg-elevated: var(--bmg-color-sheet);--bg-popover: var(--bmg-color-popover);--bg-hover: var(--bmg-color-fill-faint);--bg-active: var(--bmg-color-fill-tile);--fill-soft: var(--bmg-color-fill-soft);--fill: var(--bmg-color-fill);--fill-strong: var(--bmg-color-fill-strong);--overlay: var(--bmg-color-overlay);--scrim: var(--bmg-color-scrim);--inset: var(--bmg-color-inset);--border-subtle: var(--bmg-color-border-quiet);--border-strong: var(--bmg-color-border-strong);--border-active: var(--bmg-color-border-active);--border-hover: var(--bmg-color-border-hover);--border-focus: var(--bmg-color-accent);--text-primary: var(--bmg-color-text);--text-strong: var(--bmg-color-text-strong);--text-secondary: var(--bmg-color-text-dim);--text-muted: var(--bmg-color-text-faint);--text-faint: var(--bmg-color-text-off);--on-strong: var(--bmg-color-wash);--on-strong-muted: color-mix(in srgb, var(--bmg-color-wash) 80%, transparent);--on-accent: var(--bmg-color-canvas);--accent: var(--bmg-color-accent);--accent-hover: var(--bmg-color-accent-hover);--accent-strong: var(--bmg-color-accent-pressed);--accent-soft: color-mix(in srgb, var(--bmg-color-accent) 14%, transparent);--accent-line: color-mix(in srgb, var(--bmg-color-accent) 35%, transparent);--success: var(--bmg-color-success);--success-soft: color-mix(in srgb, var(--bmg-color-success) 13%, transparent);--warning: var(--bmg-color-warning);--warning-soft: color-mix(in srgb, var(--bmg-color-warning) 14%, transparent);--warning-line: color-mix(in srgb, var(--bmg-color-warning) 30%, transparent);--danger: var(--bmg-color-danger);--danger-soft: color-mix(in srgb, var(--bmg-color-danger) 14%, transparent);--danger-soft-strong: color-mix(in srgb, var(--bmg-color-danger) 22%, transparent);--danger-line: color-mix(in srgb, var(--bmg-color-danger) 32%, transparent);--info: var(--bmg-color-info);--info-soft: color-mix(in srgb, var(--bmg-color-info) 13%, transparent);--warn: var(--warning);--warn-soft: var(--warning-soft);--error: var(--danger);--error-soft: var(--danger-soft);--node-code: var(--bmg-color-violet);--node-spec: var(--bmg-color-info);--node-test: var(--bmg-color-success);--node-route: var(--bmg-color-hero-end);--node-code-soft: color-mix(in srgb, var(--node-code) 14%, transparent);--node-spec-soft: color-mix(in srgb, var(--node-spec) 14%, transparent);--node-test-soft: color-mix(in srgb, var(--node-test) 14%, transparent);--node-route-soft: color-mix(in srgb, var(--node-route) 14%, transparent);--node-text: var(--bmg-color-wash);--dot-grid: var(--bmg-color-wallpaper-ink);--edge-line: color-mix(in srgb, var(--bmg-color-text-faint) 32%, transparent);--edge-arrow: color-mix(in srgb, var(--bmg-color-text-faint) 50%, transparent);--cell-border: rgba(0,0,0,.26);--font-ui: "Space Grotesk", system-ui, -apple-system, sans-serif;--font-display: "Bricolage Grotesque", "Space Grotesk", system-ui, -apple-system, sans-serif;--font-mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;--font-mono-features: "zero", "liga" 0, "calt" 0;--fs-big: var(--bmg-font-size-h0);--fs-title: var(--bmg-font-size-h2);--fs-lg: var(--bmg-font-size-lg);--fs-base: var(--bmg-font-size-label);--fs-sm: var(--bmg-font-size-meta-sm);--fs-xs: var(--bmg-font-size-tiny);--space-xs: var(--bmg-space-xs);--space-sm: var(--bmg-space-sm);--space-md: var(--bmg-space-md);--space-lg: var(--bmg-space-lg);--space-xl: var(--bmg-space-xl);--space-2xl: var(--bmg-space-2xl);--space-gutter: var(--bmg-space-gutter);--r-sm: var(--bmg-radius-xs);--r-md: var(--bmg-radius-sm);--r-lg: var(--bmg-radius-md);--r-xl: var(--bmg-radius-xl);--r-pill: var(--bmg-radius-pill);--radius-card: var(--bmg-radius-3xl);--radius-control: var(--bmg-radius-lg);--radius-control-primary: var(--bmg-radius-xl);--radius-chip: var(--bmg-radius-xs);--radius-seg: var(--bmg-radius-lg);--radius-seg-btn: var(--bmg-radius-sm);--radius-switch: var(--bmg-radius-pill);--radius-empty-icon: var(--bmg-radius-lg);--control-h-md: 32px;--control-h-sm: 28px;--control-h-xs: 22px;--control-pad-x: var(--bmg-space-lg);--control-pad-x-sm: var(--bmg-space-md);--control-pad-x-xs: var(--bmg-space-sm);--control-gap: var(--bmg-space-sm);--control-border-w: 1px;--chip-pad-x: var(--bmg-space-sm);--chip-pad-y: var(--bmg-space-xs);--badge-pad-x: var(--bmg-space-sm);--badge-pad-y: 2px;--dot-size: 6px;--seg-h: 36px;--seg-inset: 2px;--switch-track-w: 44px;--switch-track-h: 26px;--switch-thumb: 20px;--switch-inset: calc((var(--switch-track-h) - var(--switch-thumb)) / 2);--empty-icon: 52px;--empty-min-h: 280px;--empty-max-w: 360px;--spinner-size: 12px;--spinner-w: 2px;--state-disabled-opacity: .4;--focus-ring: 2px solid var(--border-focus);--focus-ring-offset: 1px;--motion-fast: .1s ease;--motion-spin: .7s linear infinite;--shadow-pop: 0 12px 32px -8px rgba(0,0,0,.6), 0 2px 8px rgba(0,0,0,.4);--shadow-panel: 0 1px 0 rgba(255,255,255,.02) inset;--shadow-node: 0 2px 8px rgba(0,0,0,.4);--shadow-minimap: 0 4px 12px rgba(0,0,0,.4);--shadow-seg: 0 1px 2px rgba(0,0,0,.3);--glow-logo: drop-shadow(0 0 9px color-mix(in srgb, var(--bmg-color-info) 35%, transparent));--sidebar-w: 232px;--sidebar-w-collapsed: 56px;--status-h: 30px}[data-density=compact]{--fs-title: 19px;--status-h: 26px;--sidebar-w: 204px}[data-density=compact] .card-pad{padding:10px}*{box-sizing:border-box}html,body{margin:0;padding:0;height:100%;background:var(--bg-canvas);color:var(--text-primary);font-family:var(--font-ui);font-size:var(--fs-base);line-height:1.45;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;font-feature-settings:"cv01","cv03","ss03";overflow:hidden}#root{height:100%}::selection{background:var(--accent-soft)}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--fill-strong);border-radius:999px;border:2px solid transparent;background-clip:content-box}::-webkit-scrollbar-thumb:hover{background:var(--border-active);background-clip:content-box}h1,h2,h3,h4,.sp-title,[data-page-title],.display-num{font-family:var(--font-display)}.mono{font-family:var(--font-mono);font-feature-settings:var(--font-mono-features);font-variant-ligatures:none}code,pre,kbd,samp,.mono,.sp-code,.sp-kw,.sp-crit-id,.sp-label .ct,.sp-textarea,.sp-textarea::placeholder,.sp-crit-num,[style*=--font-mono],[font-family*=--font-mono]{font-feature-settings:var(--font-mono-features);font-variant-ligatures:none}.tnum{font-variant-numeric:tabular-nums}.btn{font-family:var(--font-ui);font-size:var(--fs-base);font-weight:500;border:var(--control-border-w) solid transparent;border-radius:var(--radius-control);height:var(--control-h-md);padding:0 var(--control-pad-x);display:inline-flex;align-items:center;justify-content:center;gap:var(--control-gap);cursor:pointer;white-space:nowrap;transition:background var(--motion-fast),border-color var(--motion-fast),color var(--motion-fast);user-select:none}.btn svg{width:14px;height:14px;flex-shrink:0}.btn-primary{background:var(--accent);color:var(--on-accent);border-color:var(--accent);border-radius:var(--radius-control-primary)}.btn-primary.is-hover,.btn-primary:hover:not(:disabled){background:var(--accent-hover);border-color:var(--accent-hover)}.btn-primary.is-active,.btn-primary:active:not(:disabled){background:var(--accent-strong);border-color:var(--accent-strong)}.btn-ghost{background:transparent;color:var(--text-secondary)}.btn-ghost.is-hover,.btn-ghost:hover:not(:disabled){background:var(--bg-hover);color:var(--text-primary)}.btn-ghost.is-active,.btn-ghost:active:not(:disabled){background:var(--bg-active);color:var(--text-primary)}.btn-outline{background:transparent;color:var(--text-primary);border-color:var(--border-strong)}.btn-outline.is-hover,.btn-outline:hover:not(:disabled){background:var(--bg-hover);border-color:var(--border-hover)}.btn-outline.is-active,.btn-outline:active:not(:disabled){background:var(--bg-active);border-color:var(--border-active)}.btn-secondary{background:var(--bg-elevated);color:var(--text-primary);border-color:var(--border-subtle)}.btn-secondary.is-hover,.btn-secondary:hover:not(:disabled){background:var(--bg-elevated);border-color:var(--border-strong)}.btn-secondary.is-active,.btn-secondary:active:not(:disabled){background:var(--bg-active)}.btn-destructive{background:var(--error-soft);color:var(--error);border-color:var(--danger-line)}.btn-destructive.is-hover,.btn-destructive:hover:not(:disabled){background:var(--danger-soft-strong)}.btn-destructive.is-active,.btn-destructive:active:not(:disabled){background:var(--danger-soft)}.btn-sm{height:var(--control-h-sm);padding:0 var(--control-pad-x-sm);font-size:var(--fs-sm)}.btn-xs{height:var(--control-h-xs);padding:0 var(--control-pad-x-xs);font-size:var(--fs-xs);border-radius:var(--r-sm)}.btn:disabled{opacity:var(--state-disabled-opacity);cursor:not-allowed}.btn.is-loading,.btn[aria-busy=true]{cursor:progress}.btn.is-loading:before,.btn[aria-busy=true]:before{content:"";width:var(--spinner-size);height:var(--spinner-size);border-radius:var(--r-pill);border:var(--spinner-w) solid currentColor;border-right-color:transparent;animation:spin var(--motion-spin);flex-shrink:0}.pill{display:inline-flex;align-items:center;gap:var(--space-xs);font-size:var(--fs-xs);font-weight:600;padding:var(--badge-pad-y) var(--badge-pad-x);border-radius:var(--r-pill);letter-spacing:.01em;white-space:nowrap;line-height:1.5;color:var(--text-secondary);background:var(--fill-soft)}.pill svg{width:11px;height:11px}.pill-dot{width:var(--dot-size);height:var(--dot-size);border-radius:var(--r-pill);background:currentColor}.chip{display:inline-flex;align-items:center;gap:var(--space-xs);padding:var(--chip-pad-y) var(--chip-pad-x);border:var(--control-border-w) solid var(--border-subtle);border-radius:var(--radius-chip);background:var(--bg-panel);color:var(--text-secondary);font-family:var(--font-ui);font-size:var(--fs-sm);font-weight:500;line-height:1.4;white-space:nowrap;cursor:pointer;transition:background var(--motion-fast),color var(--motion-fast),border-color var(--motion-fast)}.chip.sm{font-size:var(--fs-xs)}.chip-cap{text-transform:capitalize}.chip-count{font-size:var(--fs-xs);font-variant-numeric:tabular-nums;opacity:.75}.chip-dot{width:var(--dot-size);height:var(--dot-size);border-radius:var(--r-pill);background:var(--chip-color, var(--accent))}.chip.is-hover,.chip:hover:not(:disabled){background:var(--bg-hover);border-color:var(--border-strong);color:var(--text-primary)}.chip.is-active,.chip:active:not(:disabled){background:var(--bg-active)}.chip:disabled{opacity:var(--state-disabled-opacity);cursor:not-allowed}.chip.on,.chip[aria-pressed=true]{background:var(--chip-bg, color-mix(in srgb, var(--chip-color, var(--accent)) 22%, var(--bg-panel)));color:var(--chip-color, var(--accent));border-color:transparent}.card{background:var(--bg-panel);border:var(--control-border-w) solid var(--border-subtle);border-radius:var(--radius-card)}.card-pad{padding:var(--space-lg)}.card-btn{cursor:pointer;font-family:var(--font-ui);color:var(--text-primary);transition:background var(--motion-fast),border-color var(--motion-fast)}.card-btn.is-hover,.card-btn:hover:not(:disabled){background:var(--bg-panel-2);border-color:var(--border-strong)}.card-btn.is-active,.card-btn:active:not(:disabled){background:var(--bg-elevated)}.card-btn:disabled{opacity:var(--state-disabled-opacity);cursor:not-allowed}.stat-tile{text-align:left;padding:var(--space-md);display:flex;flex-direction:column;gap:var(--space-sm)}.stat-tile-label{letter-spacing:.04em}.stat-tile .display-num{font-size:var(--bmg-font-size-h2);font-weight:650;letter-spacing:-.02em;line-height:1}.stat-tile-note{font-size:var(--fs-xs);color:var(--text-muted)}.list-row{transition:background var(--motion-fast)}.list-row:hover{background:var(--bg-hover)}.list-row:active{background:var(--bg-active)}.list-row.selected,.list-row[aria-selected=true]{background:var(--accent-soft)}.seg{display:inline-flex;background:var(--bg-canvas);border:var(--control-border-w) solid var(--border-subtle);border-radius:var(--radius-seg);padding:var(--seg-inset);gap:var(--seg-inset)}.seg-btn{border:none;cursor:pointer;border-radius:var(--radius-seg-btn);height:var(--seg-h);padding:0 var(--control-pad-x-sm);font-size:var(--fs-sm);font-weight:500;font-family:var(--font-ui);background:transparent;color:var(--text-muted);transition:background var(--motion-fast),color var(--motion-fast),box-shadow var(--motion-fast)}.seg-btn.sm{height:var(--control-h-sm);padding:0 var(--control-pad-x-xs)}.seg-btn.is-hover:not(.active),.seg-btn:hover:not(:disabled):not(.active){background:var(--bg-hover);color:var(--text-secondary)}.seg-btn.is-active,.seg-btn:active:not(:disabled){background:var(--bg-active)}.seg-btn:disabled{opacity:var(--state-disabled-opacity);cursor:not-allowed}.seg-btn.active{background:var(--bg-elevated);color:var(--text-primary);box-shadow:var(--shadow-seg)}.switch{position:relative;flex-shrink:0;width:var(--switch-track-w);height:var(--switch-track-h);padding:0;border:var(--control-border-w) solid var(--border-strong);border-radius:var(--radius-switch);background:var(--bg-elevated);cursor:pointer;transition:background var(--motion-fast),border-color var(--motion-fast)}.switch-thumb{position:absolute;top:calc(var(--switch-inset) - var(--control-border-w));left:calc(var(--switch-inset) - var(--control-border-w));width:var(--switch-thumb);height:var(--switch-thumb);border-radius:var(--radius-switch);background:var(--on-strong);transition:transform var(--motion-fast)}.switch.is-hover,.switch:hover:not(:disabled){border-color:var(--border-hover)}.switch.is-active,.switch:active:not(:disabled){background:var(--bg-active)}.switch:disabled{opacity:var(--state-disabled-opacity);cursor:not-allowed}.switch[aria-busy=true]{cursor:progress}.switch[aria-checked=true]{background:var(--accent);border-color:var(--accent)}.switch[aria-checked=true] .switch-thumb{background:var(--on-accent);transform:translate(calc(var(--switch-track-w) - var(--switch-thumb) - 2 * var(--switch-inset)))}.empty{display:grid;place-items:center;height:100%;min-height:var(--empty-min-h);text-align:center;padding:var(--space-2xl)}.empty-inner{max-width:var(--empty-max-w)}.empty-icon{width:var(--empty-icon);height:var(--empty-icon);border-radius:var(--radius-empty-icon);background:var(--bg-panel);border:var(--control-border-w) solid var(--border-subtle);display:grid;place-items:center;color:var(--text-muted);margin:0 auto var(--space-lg)}.empty-title{font-family:var(--font-display);font-size:var(--fs-lg);font-weight:600;margin-bottom:var(--space-sm)}.empty-body{color:var(--text-secondary);line-height:1.55}.empty-action{margin-top:var(--space-lg)}.error-state .empty-icon{color:var(--danger);background:var(--danger-soft);border-color:var(--danger-line)}.error-state .empty-title{color:var(--danger)}.error-state-detail{color:var(--text-muted);font-size:var(--fs-sm);overflow-wrap:anywhere;margin-top:var(--space-xs)}.input{background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:var(--r-sm);color:var(--text-primary);font-family:var(--font-ui);font-size:var(--fs-base);padding:6px 10px;outline:none;transition:border-color var(--motion-fast),box-shadow var(--motion-fast)}.input:focus{border-color:var(--border-focus);box-shadow:0 0 0 3px var(--accent-soft)}.input::placeholder{color:var(--text-muted)}.eyebrow{font-size:var(--fs-xs);font-weight:600;text-transform:uppercase;letter-spacing:.07em;color:var(--text-muted)}:focus-visible{outline:var(--focus-ring);outline-offset:var(--focus-ring-offset)}.sp-prose{font-size:15px;line-height:1.62;color:var(--text-secondary);text-wrap:pretty}.sp-prose strong,.sp-strong{color:var(--text-primary);font-weight:600}.sp-code{font-family:var(--font-mono);font-size:.86em;font-feature-settings:var(--font-mono-features);font-variant-ligatures:none;background:var(--bg-canvas);color:var(--text-primary);padding:1px 6px;border-radius:5px;border:1px solid var(--border-subtle);white-space:nowrap}.sp-kw{font-family:var(--font-mono);font-size:.7em;font-weight:600;letter-spacing:.05em;padding:1px 6px;border-radius:4px;white-space:nowrap;position:relative;top:-1px}.sp-kw-must{color:var(--node-spec);background:var(--node-spec-soft)}.sp-kw-should{color:var(--warn);background:var(--warn-soft)}.sp-kw-may{color:var(--text-muted);background:var(--fill-soft)}.sp-statement{position:relative;padding:16px 18px 16px 20px;border-radius:var(--r-md);background:var(--bg-panel);border:1px solid var(--border-subtle);overflow:hidden}.sp-statement:before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--sp-accent, var(--node-spec))}.sp-crit{display:flex;gap:12px;align-items:flex-start;padding:12px 14px;border-top:1px solid var(--border-subtle);transition:background var(--motion-fast)}.sp-crit:first-child{border-top:none}.sp-crit:hover{background:var(--bg-hover)}.sp-crit-mark{width:20px;height:20px;border-radius:6px;flex-shrink:0;margin-top:1px;display:grid;place-items:center}.sp-crit-id{font-family:var(--font-mono);font-size:11px;font-weight:600;flex-shrink:0;color:var(--text-muted);margin-top:2px;width:22px}.sp-crit-text{font-size:13.5px;line-height:1.55;color:var(--text-secondary);flex:1;text-wrap:pretty}.sp-meta-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:2px;background:var(--border-subtle);border:1px solid var(--border-subtle);border-radius:var(--r-md);overflow:hidden}.sp-meta-cell{background:var(--bg-panel);padding:9px 12px}.sp-meta-k{font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted)}.sp-meta-v{font-size:13px;color:var(--text-primary);margin-top:3px}.sp-doc{max-width:700px}.sp-breadcrumb{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--text-muted);margin-bottom:20px}.sp-breadcrumb .sp-path{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sp-title{font-size:27px;font-weight:650;letter-spacing:-.025em;line-height:1.16;margin:0 0 16px;text-wrap:pretty}.sp-metaline{display:flex;align-items:center;gap:11px;flex-wrap:wrap;font-size:12.5px;color:var(--text-muted)}.sp-metaline .sep{width:3px;height:3px;border-radius:50%;background:var(--text-faint);flex-shrink:0}.sp-metaline .fact b{color:var(--text-secondary);font-weight:550}.sp-label{display:flex;align-items:center;gap:8px;margin-bottom:12px;font-size:11px;font-weight:600;letter-spacing:.07em;text-transform:uppercase;color:var(--text-muted)}.sp-label .ct{margin-left:auto;font-family:var(--font-mono);font-size:11px;letter-spacing:0;text-transform:none}.sp-sec{margin-bottom:30px}.sp-statement.lead{padding:20px 22px 20px 24px;background:var(--bg-canvas)}.sp-statement.lead .sp-prose{font-size:16.5px;line-height:1.7;color:var(--text-primary)}.sp-rationale{font-size:14px;line-height:1.72;color:var(--text-secondary);padding-left:16px;border-left:2px solid var(--border-strong);text-wrap:pretty}.sp-rationale .sp-code{font-size:.84em}.sp-crit-text{font-size:14px}.sp-edit-bar{position:sticky;top:0;z-index:6;display:flex;align-items:center;gap:12px;padding:11px 28px;background:color-mix(in srgb,var(--bg-panel) 88%,transparent);border-bottom:1px solid var(--border-subtle);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.sp-edit-bar:before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--accent)}.sp-fl{font-size:10px;text-transform:uppercase;letter-spacing:.07em;color:var(--text-muted);font-weight:600;display:block;margin-bottom:7px}.sp-input-lg{width:100%;font-size:19px;font-weight:600;letter-spacing:-.01em;padding:10px 14px;line-height:1.3}.sp-textarea{width:100%;resize:vertical;line-height:1.65;display:block;font-family:var(--font-mono);font-size:13px;min-height:110px;padding:13px 15px;tab-size:2}.sp-textarea::placeholder{font-family:var(--font-mono)}.sp-edit-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 22px;margin-bottom:4px}@media (max-width: 1100px){.sp-edit-grid{grid-template-columns:1fr}}.sp-select{appearance:none;-webkit-appearance:none;cursor:pointer;padding-right:28px;background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%238792a3" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>');background-repeat:no-repeat;background-position:right 9px center;background-size:13px}.sp-write-area{position:relative}.sp-kw-legend{display:flex;gap:6px;flex-wrap:wrap;align-items:center;margin-top:9px}.sp-kw-legend .label{font-size:11px;color:var(--text-muted)}.sp-crit-edit{display:flex;gap:10px;align-items:center;padding:9px 10px 9px 8px;border-top:1px solid var(--border-subtle)}.sp-crit-edit:first-child{border-top:none}.sp-crit-grip{color:var(--text-muted);cursor:grab;flex-shrink:0;display:grid;place-items:center;opacity:.5}.sp-crit-grip:hover{opacity:1}.sp-crit-num{font-family:var(--font-mono);font-size:11px;font-weight:600;color:var(--text-muted);width:22px;flex-shrink:0;text-align:center}.sp-icon-btn{width:28px;height:28px;border-radius:var(--r-sm);flex-shrink:0;display:grid;place-items:center;cursor:pointer;background:transparent;border:1px solid transparent;color:var(--text-muted);transition:background var(--motion-fast),color var(--motion-fast)}.sp-icon-btn:hover:not(:disabled){background:var(--error-soft);color:var(--error)}.sp-dirty-dot{width:7px;height:7px;border-radius:50%;background:var(--warn);box-shadow:0 0 0 3px var(--warn-soft)}.sp-status-auto{display:flex;align-items:center;gap:10px;padding:8px 12px;min-height:38px;box-sizing:border-box;background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:var(--r-md)}.row{display:flex;align-items:center}.col{display:flex;flex-direction:column}.gap-2{gap:2px}.gap-4{gap:4px}.gap-6{gap:6px}.gap-8{gap:8px}.gap-10{gap:10px}.gap-12{gap:12px}.gap-16{gap:16px}.grow{flex:1}.muted{color:var(--text-muted)}.secondary{color:var(--text-secondary)}.tabular{font-variant-numeric:tabular-nums}.scroll-y{overflow-y:auto;overflow-x:hidden}@keyframes pulsePill{0%{box-shadow:0 0 0 0 currentColor}to{box-shadow:0 0 0 8px transparent}}@keyframes slideInRight{0%{opacity:0;transform:translate(14px)}to{opacity:1;transform:translate(0)}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes runningDash{to{stroke-dashoffset:-16}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes skeleton{0%{opacity:.5}50%{opacity:.9}to{opacity:.5}}.skel{background:var(--bg-elevated);border-radius:5px;animation:skeleton 1.4s ease-in-out infinite}@media (prefers-reduced-motion: reduce){*{animation-duration:.001ms!important;transition-duration:.001ms!important}}.plan-reader{max-width:75ch;margin:0 auto;padding:var(--space-lg) var(--space-lg) var(--space-2xl);font-size:var(--fs-base);line-height:1.6}.plan-reader h2{font-family:var(--font-display);font-size:var(--fs-title);margin:var(--space-xl) 0 var(--space-sm)}.plan-reader h3{font-size:var(--fs-lg);margin:var(--space-lg) 0 var(--space-xs)}.plan-reader p{margin:0 0 var(--space-sm);white-space:pre-wrap}.plan-reader ul{margin:0 0 var(--space-md);padding-left:var(--space-lg)}.plan-reader li{margin:var(--space-xs) 0}.plan-reader a{color:inherit}@font-face{font-family:Bricolage Grotesque;font-style:normal;font-weight:200 800;font-stretch:100%;font-display:swap;src:url(/assets/bricolage-latin-ext-B82pxkPf.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C4,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Bricolage Grotesque;font-style:normal;font-weight:200 800;font-stretch:100%;font-display:swap;src:url(/assets/bricolage-latin-C23fTOVi.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Space Grotesk;font-style:normal;font-weight:300 700;font-stretch:100%;font-display:swap;src:url(/assets/space-grotesk-latin-ext-wJGaI8U0.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C4,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Space Grotesk;font-style:normal;font-weight:300 700;font-stretch:100%;font-display:swap;src:url(/assets/space-grotesk-latin-DPT1xrvW.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root{--font-ui: "Space Grotesk", system-ui, -apple-system, sans-serif;--font-display: "Bricolage Grotesque", "Space Grotesk", system-ui, -apple-system, sans-serif;--font-mono: "Geist Mono Variable", "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace}
|