@erclx/canon 5.28.0 → 5.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/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/review-ui/references/post.md +7 -5
- package/docs/agents/canvas.md +8 -0
- package/docs/agents/pr-evidence.md +7 -7
- package/package.json +1 -1
- package/src/canvas/client/app.tsx +105 -4
- package/src/canvas/client/inspector.tsx +13 -4
- package/src/canvas/client/keys.ts +23 -6
- package/src/canvas/client/main.tsx +9 -0
- package/src/canvas/client/pages-panel.tsx +5 -1
- package/src/canvas/client/panel-handle.tsx +90 -0
- package/src/canvas/client/shell.css +86 -2
- package/src/canvas/client/state.ts +159 -6
- package/src/canvas/client/surface.tsx +37 -1
- package/src/canvas/client/tools.tsx +91 -2
- package/src/canvas/content.ts +65 -0
- package/src/canvas/edit.ts +195 -23
- package/src/canvas/history.ts +116 -0
- package/src/canvas/server.ts +126 -13
- package/src/{exec.ts → cli/exec.ts} +1 -1
- package/src/{help.ts → cli/help.ts} +1 -1
- package/src/cli.ts +1 -1
- package/src/commands/audits.ts +9 -1
- package/src/commands/autoship.ts +1 -1
- package/src/commands/canvas.ts +1 -1
- package/src/commands/capture.ts +1 -1
- package/src/commands/census.ts +1 -1
- package/src/commands/claude.ts +2 -2
- package/src/commands/comments.ts +1 -1
- package/src/commands/context.ts +1 -1
- package/src/commands/demo.ts +9 -1
- package/src/commands/deps.ts +1 -1
- package/src/commands/design.ts +9 -1
- package/src/commands/docs.ts +1 -1
- package/src/commands/driver.ts +9 -1
- package/src/commands/feedback.ts +1 -1
- package/src/commands/gate.ts +1 -1
- package/src/commands/gov.ts +1 -1
- package/src/commands/indexes.ts +1 -1
- package/src/commands/init.ts +10 -2
- package/src/commands/intake.ts +1 -1
- package/src/commands/inventory.ts +9 -1
- package/src/commands/labels.ts +1 -1
- package/src/commands/markdown.ts +1 -1
- package/src/commands/migrate.ts +1 -1
- package/src/commands/pr.ts +141 -2
- package/src/commands/records.ts +1 -1
- package/src/commands/repo.ts +1 -1
- package/src/commands/sandbox.ts +1 -1
- package/src/commands/secrets.ts +9 -1
- package/src/commands/sessions.ts +1 -1
- package/src/commands/slides.ts +1 -1
- package/src/commands/standards.ts +1 -1
- package/src/commands/sync.ts +2 -2
- package/src/commands/targets.ts +1 -1
- package/src/commands/tasks.ts +1 -1
- package/src/commands/teach.ts +1 -1
- package/src/commands/tooling.ts +1 -1
- package/src/commands/transcripts.ts +1 -1
- package/src/commands/upgrade.ts +1 -1
- package/src/commands/wiki.ts +1 -1
- package/src/commands/worktrees.ts +1 -1
- package/src/design/brand-favicon.ts +18 -0
- package/src/gate/measures.ts +1 -1
- package/src/init/run.ts +1 -1
- package/src/migrate/rename.ts +1 -1
- package/src/pr/evidence.ts +41 -7
- package/src/roots/project.ts +1 -1
- package/src/sandbox/headless/run.ts +1 -1
- package/src/sandbox/provision.ts +1 -1
- package/src/sandbox/scenario.ts +1 -1
- package/src/serve/report.ts +1 -1
- package/src/sync/engine.ts +1 -1
- package/src/sync/git.ts +1 -1
- package/src/sync/workflow.ts +1 -1
- package/src/targets/validate.ts +1 -1
- package/src/teach/nav.ts +5 -12
- package/src/tooling/inject.ts +1 -1
- package/src/tooling/verify-stack.ts +1 -1
- /package/src/{cli-run.ts → cli/run.ts} +0 -0
- /package/src/{ui.ts → cli/ui.ts} +0 -0
package/src/commands/claude.ts
CHANGED
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
writeSettings,
|
|
71
71
|
} from '@/claude/settings'
|
|
72
72
|
import { copyPreservingMode } from '@/sync/copy'
|
|
73
|
-
import { execScript } from '@/exec'
|
|
73
|
+
import { execScript } from '@/cli/exec'
|
|
74
74
|
import { checkoutMismatchWarning, PROJECT_ROOT } from '@/roots/project'
|
|
75
75
|
import { recordDir } from '@/roots/record'
|
|
76
76
|
import { SURFACE_ENTRIES, surfaceDir } from '@/roots/surface'
|
|
@@ -90,7 +90,7 @@ import {
|
|
|
90
90
|
pipeOutput,
|
|
91
91
|
plural,
|
|
92
92
|
select,
|
|
93
|
-
} from '@/ui'
|
|
93
|
+
} from '@/cli/ui'
|
|
94
94
|
import { describeSkew, readSkew, type SkewReport } from '@/version/skew'
|
|
95
95
|
|
|
96
96
|
interface SeedsListOptions {
|
package/src/commands/comments.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from '@/comments/scan'
|
|
10
10
|
import { type TrendPoint, trend } from '@/comments/trend'
|
|
11
11
|
import { loadVocabulary, type Vocabulary } from '@/comments/vocabulary'
|
|
12
|
-
import { intro, logInfo, logStep, logWarn, outro, pipeOutput } from '@/ui'
|
|
12
|
+
import { intro, logInfo, logStep, logWarn, outro, pipeOutput } from '@/cli/ui'
|
|
13
13
|
|
|
14
14
|
interface ScanCommandOptions {
|
|
15
15
|
readonly json?: boolean
|
package/src/commands/context.ts
CHANGED
package/src/commands/demo.ts
CHANGED
|
@@ -12,7 +12,15 @@ import {
|
|
|
12
12
|
} from '@/demo/container'
|
|
13
13
|
import { DEFAULT_CURSORS } from '@/demo/cursors'
|
|
14
14
|
import { loadCursorTheme } from '@/demo/theme'
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
intro,
|
|
17
|
+
logError,
|
|
18
|
+
logInfo,
|
|
19
|
+
logStep,
|
|
20
|
+
logWarn,
|
|
21
|
+
outro,
|
|
22
|
+
plural,
|
|
23
|
+
} from '@/cli/ui'
|
|
16
24
|
|
|
17
25
|
const DEFAULT_OUT = 'demos'
|
|
18
26
|
|
package/src/commands/deps.ts
CHANGED
package/src/commands/design.ts
CHANGED
|
@@ -16,7 +16,15 @@ import { creationRel, SCRATCH } from '@/roots/record'
|
|
|
16
16
|
import { surfaceDir } from '@/roots/surface'
|
|
17
17
|
import { recordStamp, runDomainSync } from '@/sync/engine'
|
|
18
18
|
import { isDirectory, resolveTarget } from '@/targets/validate'
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
intro,
|
|
21
|
+
logAdd,
|
|
22
|
+
logError,
|
|
23
|
+
logInfo,
|
|
24
|
+
logWarn,
|
|
25
|
+
outro,
|
|
26
|
+
palette,
|
|
27
|
+
} from '@/cli/ui'
|
|
20
28
|
|
|
21
29
|
export function register(program: Command): void {
|
|
22
30
|
const design = program
|
package/src/commands/docs.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Command } from 'commander'
|
|
|
2
2
|
import { type DocEntry, listDocs } from '@/docs/list'
|
|
3
3
|
import { listTopics, readTopic, resolveTopic } from '@/docs/read'
|
|
4
4
|
import { checkoutMismatchWarning, PROJECT_ROOT } from '@/roots/project'
|
|
5
|
-
import { intro, logError, logInfo, logStep, logWarn, outro } from '@/ui'
|
|
5
|
+
import { intro, logError, logInfo, logStep, logWarn, outro } from '@/cli/ui'
|
|
6
6
|
|
|
7
7
|
export function register(program: Command): void {
|
|
8
8
|
const docs = program
|
package/src/commands/driver.ts
CHANGED
|
@@ -6,7 +6,15 @@ import type { DriverRefusal } from '@/driver/drive'
|
|
|
6
6
|
import { describeViewport } from '@/driver/probes/viewport'
|
|
7
7
|
import { PROBE_NAMES, readDriverPlan } from '@/driver/steps'
|
|
8
8
|
import type { PlanRefusal } from '@/driver/steps'
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
intro,
|
|
11
|
+
logError,
|
|
12
|
+
logInfo,
|
|
13
|
+
logStep,
|
|
14
|
+
logWarn,
|
|
15
|
+
outro,
|
|
16
|
+
plural,
|
|
17
|
+
} from '@/cli/ui'
|
|
10
18
|
|
|
11
19
|
/**
|
|
12
20
|
* Holds wiring only. Every browser reference sits behind `loadDriver`, because
|
package/src/commands/feedback.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { checkoutMismatchWarning, PROJECT_ROOT } from '@/roots/project'
|
|
|
12
12
|
import { creationRel } from '@/roots/record'
|
|
13
13
|
import { createGithubIssue } from '@/feedback/github'
|
|
14
14
|
import { issueFailureMessage } from '@/feedback/github-format'
|
|
15
|
-
import { frameError, frameSuccess, logWarn, palette } from '@/ui'
|
|
15
|
+
import { frameError, frameSuccess, logWarn, palette } from '@/cli/ui'
|
|
16
16
|
|
|
17
17
|
function readStdin(): Promise<string> {
|
|
18
18
|
return new Promise((resolveStream, rejectStream) => {
|
package/src/commands/gate.ts
CHANGED
package/src/commands/gov.ts
CHANGED
package/src/commands/indexes.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { buildIndexCatalog } from '@/indexes/list'
|
|
|
6
6
|
import { exitCodeFor, type RegenResult, regenOne } from '@/indexes/regen'
|
|
7
7
|
import { gitEnv } from '@/git/env'
|
|
8
8
|
import { findIndexedAncestor, isIgnored, listIndexes } from '@/indexes/walk'
|
|
9
|
-
import { intro, logAdd, logInfo, logStep, logWarn, outro } from '@/ui'
|
|
9
|
+
import { intro, logAdd, logInfo, logStep, logWarn, outro } from '@/cli/ui'
|
|
10
10
|
|
|
11
11
|
interface RegenCommandOptions {
|
|
12
12
|
readonly dryRun?: boolean
|
package/src/commands/init.ts
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import type { Command } from 'commander'
|
|
2
|
-
import { cliPath, cliRun } from '@/cli
|
|
2
|
+
import { cliPath, cliRun } from '@/cli/run'
|
|
3
3
|
import { PROJECT_ROOT } from '@/roots/project'
|
|
4
4
|
import { applyInitOptions, flagsProvided } from '@/init/flags'
|
|
5
5
|
import { type InitFlags, parseSkip, planInit } from '@/init/plan'
|
|
6
6
|
import { runDomains } from '@/init/run'
|
|
7
7
|
import { buildSteps } from '@/init/steps'
|
|
8
8
|
import { resolveTarget } from '@/targets/validate'
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
intro,
|
|
11
|
+
logInfo,
|
|
12
|
+
logStep,
|
|
13
|
+
logWarn,
|
|
14
|
+
outro,
|
|
15
|
+
palette,
|
|
16
|
+
select,
|
|
17
|
+
} from '@/cli/ui'
|
|
10
18
|
|
|
11
19
|
interface InitOptions {
|
|
12
20
|
/** Always present: the option falls back to `DEFAULT_STACK`. */
|
package/src/commands/intake.ts
CHANGED
|
@@ -9,7 +9,15 @@ import {
|
|
|
9
9
|
import { abbreviate, groupByTreatment } from '@/inventory/group'
|
|
10
10
|
import { findSubject, SUBJECTS } from '@/inventory/subjects'
|
|
11
11
|
import type { WalkRefusal } from '@/inventory/walk'
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
intro,
|
|
14
|
+
logError,
|
|
15
|
+
logInfo,
|
|
16
|
+
logStep,
|
|
17
|
+
logWarn,
|
|
18
|
+
outro,
|
|
19
|
+
plural,
|
|
20
|
+
} from '@/cli/ui'
|
|
13
21
|
|
|
14
22
|
/**
|
|
15
23
|
* Holds wiring only. Every browser reference sits behind `loadWalker`, because
|
package/src/commands/labels.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { checkTitleFormat, type TitleFormatIssue } from '@/labels/format'
|
|
|
6
6
|
import { MAP_REL } from '@/labels/map'
|
|
7
7
|
import { scanPhaseLabels } from '@/labels/phase'
|
|
8
8
|
import { scanTitleSpelling } from '@/labels/spelling'
|
|
9
|
-
import { intro, logInfo, logStep, logWarn, outro, plural } from '@/ui'
|
|
9
|
+
import { intro, logInfo, logStep, logWarn, outro, plural } from '@/cli/ui'
|
|
10
10
|
|
|
11
11
|
interface AuditOptions {
|
|
12
12
|
readonly base?: string
|
package/src/commands/markdown.ts
CHANGED
package/src/commands/migrate.ts
CHANGED
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
} from '@/migrate/scratch-evidence'
|
|
47
47
|
import { checkoutMismatchWarning, PROJECT_ROOT } from '@/roots/project'
|
|
48
48
|
import { readStamp, stampedHashes } from '@/sync/stamp'
|
|
49
|
-
import { logError, logInfo, logStep, logWarn, plural } from '@/ui'
|
|
49
|
+
import { logError, logInfo, logStep, logWarn, plural } from '@/cli/ui'
|
|
50
50
|
|
|
51
51
|
interface SweepOptions {
|
|
52
52
|
readonly json?: boolean
|
package/src/commands/pr.ts
CHANGED
|
@@ -32,10 +32,14 @@ import {
|
|
|
32
32
|
findEvidenceHead,
|
|
33
33
|
findEvidenceLocal,
|
|
34
34
|
findEvidencePreview,
|
|
35
|
+
type EvidenceItem,
|
|
36
|
+
type EvidenceReading,
|
|
35
37
|
groupEvidence,
|
|
36
38
|
hasMarkedEvidenceComment,
|
|
39
|
+
PNG_HEADER_BYTES,
|
|
37
40
|
readChecklistBoxes,
|
|
38
41
|
readOwed,
|
|
42
|
+
readPngWidth,
|
|
39
43
|
renderEvidenceBody,
|
|
40
44
|
settleChecklist,
|
|
41
45
|
} from '@/pr/evidence'
|
|
@@ -87,7 +91,7 @@ import {
|
|
|
87
91
|
selectBranchPull,
|
|
88
92
|
} from '@/pr/rest'
|
|
89
93
|
import { resolveReviewScope } from '@/pr/review-scope'
|
|
90
|
-
import { intro, logInfo, logStep, logWarn, outro, plural } from '@/ui'
|
|
94
|
+
import { intro, logInfo, logStep, logWarn, outro, plural } from '@/cli/ui'
|
|
91
95
|
|
|
92
96
|
const GH_TIMEOUT_MS = 30_000
|
|
93
97
|
|
|
@@ -1746,6 +1750,134 @@ async function readPullMergeBase(
|
|
|
1746
1750
|
return sha === null || sha.trim() === '' ? undefined : sha.trim()
|
|
1747
1751
|
}
|
|
1748
1752
|
|
|
1753
|
+
/** How many width reads run at once, since each downloads a whole image. */
|
|
1754
|
+
const WIDTH_READ_CONCURRENCY = 4
|
|
1755
|
+
|
|
1756
|
+
type WidthRead =
|
|
1757
|
+
| { readonly kind: 'read'; readonly width?: number }
|
|
1758
|
+
| { readonly kind: 'failed' }
|
|
1759
|
+
|
|
1760
|
+
/**
|
|
1761
|
+
* The pixel width of a PNG at `sha`, read over the contents API like every
|
|
1762
|
+
* other evidence read. The endpoint ignores a `Range` header, so the whole
|
|
1763
|
+
* file arrives and only its first bytes are read. A format other than PNG
|
|
1764
|
+
* reads without a width, and a refused or timed-out call reads as failed, so
|
|
1765
|
+
* the caller can keep the ceiling width and still report the cause.
|
|
1766
|
+
*/
|
|
1767
|
+
async function readImageWidth(
|
|
1768
|
+
cwd: string,
|
|
1769
|
+
path: string,
|
|
1770
|
+
sha: string,
|
|
1771
|
+
): Promise<WidthRead> {
|
|
1772
|
+
if (!/\.png$/i.test(path)) return { kind: 'read' }
|
|
1773
|
+
try {
|
|
1774
|
+
const result = await execa(
|
|
1775
|
+
'gh',
|
|
1776
|
+
[
|
|
1777
|
+
'api',
|
|
1778
|
+
'-H',
|
|
1779
|
+
'Accept: application/vnd.github.raw',
|
|
1780
|
+
`repos/{owner}/{repo}/contents/${path.split('/').map(encodeURIComponent).join('/')}?ref=${sha}`,
|
|
1781
|
+
],
|
|
1782
|
+
{
|
|
1783
|
+
cwd,
|
|
1784
|
+
timeout: GH_TIMEOUT_MS,
|
|
1785
|
+
env: gitEnv(),
|
|
1786
|
+
extendEnv: false,
|
|
1787
|
+
encoding: 'buffer',
|
|
1788
|
+
},
|
|
1789
|
+
)
|
|
1790
|
+
const width = readPngWidth(result.stdout.subarray(0, PNG_HEADER_BYTES))
|
|
1791
|
+
return width === undefined ? { kind: 'read' } : { kind: 'read', width }
|
|
1792
|
+
} catch {
|
|
1793
|
+
return { kind: 'failed' }
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
/** Runs `task` over `inputs` with at most `limit` in flight, keeping input order. */
|
|
1798
|
+
async function mapPool<T, R>(
|
|
1799
|
+
inputs: readonly T[],
|
|
1800
|
+
limit: number,
|
|
1801
|
+
task: (input: T) => Promise<R>,
|
|
1802
|
+
): Promise<R[]> {
|
|
1803
|
+
const results: R[] = new Array(inputs.length)
|
|
1804
|
+
let next = 0
|
|
1805
|
+
const lane = async (): Promise<void> => {
|
|
1806
|
+
while (next < inputs.length) {
|
|
1807
|
+
const index = next++
|
|
1808
|
+
results[index] = await task(inputs[index] as T)
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
await Promise.all(
|
|
1812
|
+
Array.from({ length: Math.min(limit, inputs.length) }, lane),
|
|
1813
|
+
)
|
|
1814
|
+
return results
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
interface SizedEvidence {
|
|
1818
|
+
readonly reading: EvidenceReading
|
|
1819
|
+
/** Each image whose width read failed, as `head:<path>` or `base:<path>`, which rendered at the ceiling. */
|
|
1820
|
+
readonly unread: readonly string[]
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
/** Each item with the pixel width of its head image and, when it has one, its base image. */
|
|
1824
|
+
async function withImageWidths(
|
|
1825
|
+
cwd: string,
|
|
1826
|
+
reading: EvidenceReading,
|
|
1827
|
+
base: string | undefined,
|
|
1828
|
+
head: string,
|
|
1829
|
+
): Promise<SizedEvidence> {
|
|
1830
|
+
if (reading.kind === 'refused') return { reading, unread: [] }
|
|
1831
|
+
const jobs = reading.states.flatMap((entry, stateIndex) =>
|
|
1832
|
+
entry.items.flatMap((item, itemIndex) => [
|
|
1833
|
+
{
|
|
1834
|
+
stateIndex,
|
|
1835
|
+
itemIndex,
|
|
1836
|
+
side: 'head' as const,
|
|
1837
|
+
path: item.path,
|
|
1838
|
+
sha: head,
|
|
1839
|
+
},
|
|
1840
|
+
...(item.added || base === undefined
|
|
1841
|
+
? []
|
|
1842
|
+
: [
|
|
1843
|
+
{
|
|
1844
|
+
stateIndex,
|
|
1845
|
+
itemIndex,
|
|
1846
|
+
side: 'base' as const,
|
|
1847
|
+
path: item.path,
|
|
1848
|
+
sha: base,
|
|
1849
|
+
},
|
|
1850
|
+
]),
|
|
1851
|
+
]),
|
|
1852
|
+
)
|
|
1853
|
+
const reads = await mapPool(jobs, WIDTH_READ_CONCURRENCY, (job) =>
|
|
1854
|
+
readImageWidth(cwd, job.path, job.sha),
|
|
1855
|
+
)
|
|
1856
|
+
const unread: string[] = []
|
|
1857
|
+
const states = reading.states.map((entry, stateIndex) => ({
|
|
1858
|
+
...entry,
|
|
1859
|
+
items: entry.items.map((item, itemIndex): EvidenceItem => {
|
|
1860
|
+
const widths: { width?: number; baseWidth?: number } = {}
|
|
1861
|
+
jobs.forEach((job, index) => {
|
|
1862
|
+
const read = reads[index]
|
|
1863
|
+
if (
|
|
1864
|
+
job.stateIndex !== stateIndex ||
|
|
1865
|
+
job.itemIndex !== itemIndex ||
|
|
1866
|
+
read === undefined
|
|
1867
|
+
) {
|
|
1868
|
+
return
|
|
1869
|
+
}
|
|
1870
|
+
if (read.kind === 'failed') unread.push(`${job.side}:${job.path}`)
|
|
1871
|
+
else if (read.width !== undefined) {
|
|
1872
|
+
widths[job.side === 'head' ? 'width' : 'baseWidth'] = read.width
|
|
1873
|
+
}
|
|
1874
|
+
})
|
|
1875
|
+
return { ...item, ...widths }
|
|
1876
|
+
}),
|
|
1877
|
+
}))
|
|
1878
|
+
return { reading: { kind: 'read', states }, unread }
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1749
1881
|
async function runEvidence(
|
|
1750
1882
|
number: string | undefined,
|
|
1751
1883
|
opts: EvidenceOptions,
|
|
@@ -1954,7 +2086,8 @@ async function runEvidence(
|
|
|
1954
2086
|
unsettled === undefined
|
|
1955
2087
|
? undefined
|
|
1956
2088
|
: settleChecklist(unsettled, identity.head, findEvidenceHead(comments))
|
|
1957
|
-
const
|
|
2089
|
+
const sized = await withImageWidths(root, grouped, base, identity.head)
|
|
2090
|
+
const states = sized.reading.kind === 'read' ? sized.reading.states : []
|
|
1958
2091
|
const body = renderEvidenceBody(
|
|
1959
2092
|
states,
|
|
1960
2093
|
repo,
|
|
@@ -1993,6 +2126,11 @@ async function runEvidence(
|
|
|
1993
2126
|
logInfo(
|
|
1994
2127
|
`${plural(caseCount, 'case')} across ${plural(states.length, 'state')}`,
|
|
1995
2128
|
)
|
|
2129
|
+
if (sized.unread.length > 0) {
|
|
2130
|
+
logWarn(
|
|
2131
|
+
`width unread for ${plural(sized.unread.length, 'image')}, rendered at 1000: ${sized.unread.join(', ')}`,
|
|
2132
|
+
)
|
|
2133
|
+
}
|
|
1996
2134
|
if (preview !== undefined) logInfo(`preview ${preview}`)
|
|
1997
2135
|
if (local !== undefined) logInfo(`local preview ${local}`)
|
|
1998
2136
|
if (checklist !== undefined) {
|
|
@@ -2015,6 +2153,7 @@ async function runEvidence(
|
|
|
2015
2153
|
head: identity.head,
|
|
2016
2154
|
body,
|
|
2017
2155
|
states,
|
|
2156
|
+
...(sized.unread.length > 0 && { widthUnread: sized.unread }),
|
|
2018
2157
|
...(commentId !== undefined && { commentId }),
|
|
2019
2158
|
...carried,
|
|
2020
2159
|
})}\n`,
|
package/src/commands/records.ts
CHANGED
package/src/commands/repo.ts
CHANGED
package/src/commands/sandbox.ts
CHANGED
package/src/commands/secrets.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { resolve } from 'node:path'
|
|
2
2
|
import type { Command } from 'commander'
|
|
3
3
|
import { type ScanRefusal, scanShippedTree } from '@/secrets/scan'
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
intro,
|
|
6
|
+
logError,
|
|
7
|
+
logInfo,
|
|
8
|
+
logStep,
|
|
9
|
+
logWarn,
|
|
10
|
+
outro,
|
|
11
|
+
plural,
|
|
12
|
+
} from '@/cli/ui'
|
|
5
13
|
|
|
6
14
|
interface ScanCommandOptions {
|
|
7
15
|
readonly json?: boolean
|
package/src/commands/sessions.ts
CHANGED
package/src/commands/slides.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { INSTALL_BROWSER } from '@/browser/engine'
|
|
|
4
4
|
import { creationRel, SCRATCH } from '@/roots/record'
|
|
5
5
|
import { listDecks, resolveDeck, SLIDES_FOLDER } from '@/slides/decks'
|
|
6
6
|
import { openDeck } from '@/slides/open'
|
|
7
|
-
import { intro, outro, palette } from '@/ui'
|
|
7
|
+
import { intro, outro, palette } from '@/cli/ui'
|
|
8
8
|
|
|
9
9
|
const SLIDES_AT = creationRel(process.cwd(), SLIDES_FOLDER)
|
|
10
10
|
|
package/src/commands/sync.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs'
|
|
2
2
|
import { join } from 'node:path'
|
|
3
3
|
import type { Command } from 'commander'
|
|
4
|
-
import { cliPath, cliRun } from '@/cli
|
|
4
|
+
import { cliPath, cliRun } from '@/cli/run'
|
|
5
5
|
import { PROJECT_ROOT } from '@/roots/project'
|
|
6
6
|
import {
|
|
7
7
|
buildCheckReport,
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
logWarn,
|
|
31
31
|
outro,
|
|
32
32
|
palette,
|
|
33
|
-
} from '@/ui'
|
|
33
|
+
} from '@/cli/ui'
|
|
34
34
|
import { describeSkew } from '@/version/skew'
|
|
35
35
|
|
|
36
36
|
const SYNC_ARGS: Record<SyncDomain, readonly string[]> = {
|
package/src/commands/targets.ts
CHANGED
package/src/commands/tasks.ts
CHANGED
package/src/commands/teach.ts
CHANGED
package/src/commands/tooling.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { resolve } from 'node:path'
|
|
|
2
2
|
import type { Command } from 'commander'
|
|
3
3
|
import { recordDir } from '@/roots/record'
|
|
4
4
|
import { ensureYtDlp, fetchOne } from '@/transcripts/fetch'
|
|
5
|
-
import { palette } from '@/ui'
|
|
5
|
+
import { palette } from '@/cli/ui'
|
|
6
6
|
import { mainWorktreeRoot } from '@/git/worktree'
|
|
7
7
|
|
|
8
8
|
interface TranscriptOptions {
|
package/src/commands/upgrade.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
logWarn,
|
|
10
10
|
outro,
|
|
11
11
|
select,
|
|
12
|
-
} from '@/ui'
|
|
12
|
+
} from '@/cli/ui'
|
|
13
13
|
import { compareVersions, parseVersion } from '@/version/compare'
|
|
14
14
|
import { readInstalled, UNKNOWN_LABEL } from '@/version/installed'
|
|
15
15
|
import { detectManager, installCommand, type Manager } from '@/version/manager'
|
package/src/commands/wiki.ts
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { FAVICON_COLORS, renderFavicon } from '@/design/favicon'
|
|
4
|
+
import { PROJECT_ROOT } from '@/roots/project'
|
|
5
|
+
|
|
6
|
+
const BRAND_MARK = 'assets/brand/mark.svg'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The brand icon, built from the mark and the favicon's own pair, the same two
|
|
10
|
+
* inputs `web/public/favicon.svg` is generated from. Every surface that shows
|
|
11
|
+
* the icon reads it here rather than keeping a copy that drifts from the mark.
|
|
12
|
+
* It sits apart from `favicon.ts` because the card build imports that module
|
|
13
|
+
* through an `@` alias pointed at `web/src`, so it must import nothing.
|
|
14
|
+
*/
|
|
15
|
+
export function brandFavicon(): string {
|
|
16
|
+
const mark = readFileSync(join(PROJECT_ROOT, BRAND_MARK), 'utf8')
|
|
17
|
+
return renderFavicon(mark, FAVICON_COLORS)
|
|
18
|
+
}
|
package/src/gate/measures.ts
CHANGED
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
} from '@/shipped/references'
|
|
40
40
|
import { surfaceDir } from '@/roots/surface'
|
|
41
41
|
import { seedRoots } from '@/tooling/seeds'
|
|
42
|
-
import { plural } from '@/ui'
|
|
42
|
+
import { plural } from '@/cli/ui'
|
|
43
43
|
import {
|
|
44
44
|
README_PARAPHRASE_MARKER,
|
|
45
45
|
readmeCitationsIn,
|
package/src/init/run.ts
CHANGED
package/src/migrate/rename.ts
CHANGED
|
@@ -211,7 +211,7 @@ export const AITK_RULES: RenameRules = defineRenameRules({
|
|
|
211
211
|
'src/sync/stamp.test.ts',
|
|
212
212
|
'src/targets/registry.test.ts',
|
|
213
213
|
'src/targets/sweep.test.ts',
|
|
214
|
-
'src/ui.test.ts',
|
|
214
|
+
'src/cli/ui.test.ts',
|
|
215
215
|
],
|
|
216
216
|
articleFixups: [{ pattern: AITK_ARTICLE, replacement: '$1$2$3' }],
|
|
217
217
|
})
|