@erclx/aitk 1.2.0 → 1.4.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/docs/agents/commands.md +2 -1
- package/docs/agents/index.md +1 -1
- package/docs/agents/output-shape.md +13 -0
- package/docs/agents/records.md +32 -4
- package/docs/ai-workflow.md +3 -1
- package/docs/visual-design-workflow.md +2 -0
- package/package.json +1 -1
- package/src/cli.ts +6 -5
- package/src/commands/claude.ts +4 -4
- package/src/commands/design.ts +2 -6
- package/src/commands/feedback.ts +2 -4
- package/src/commands/gov.ts +3 -3
- package/src/commands/init.ts +3 -5
- package/src/commands/records.ts +145 -7
- package/src/commands/slides.ts +4 -6
- package/src/commands/snippets.ts +2 -3
- package/src/commands/standards.ts +2 -4
- package/src/commands/sync.ts +3 -4
- package/src/commands/tooling.ts +2 -3
- package/src/commands/transcripts.ts +2 -6
- package/src/commands/wiki.ts +2 -3
- package/src/design/parse.ts +42 -5
- package/src/design/render.ts +106 -27
- package/src/records/size.ts +260 -0
- package/src/sync/engine.ts +3 -4
- package/src/sync/workflow.ts +2 -3
- package/src/ui.ts +66 -6
- package/standards/design.md +10 -0
package/src/ui.ts
CHANGED
|
@@ -1,11 +1,60 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
export interface Palette {
|
|
2
|
+
readonly GREEN: string
|
|
3
|
+
readonly RED: string
|
|
4
|
+
readonly YELLOW: string
|
|
5
|
+
readonly WHITE: string
|
|
6
|
+
readonly GREY: string
|
|
7
|
+
readonly NC: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const COLOR: Palette = {
|
|
11
|
+
GREEN: '\x1b[0;32m',
|
|
12
|
+
RED: '\x1b[0;31m',
|
|
13
|
+
YELLOW: '\x1b[0;33m',
|
|
14
|
+
WHITE: '\x1b[1;37m',
|
|
15
|
+
GREY: '\x1b[0;90m',
|
|
16
|
+
NC: '\x1b[0m',
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The blank palette keeps every frame character and drops only the escapes, so
|
|
21
|
+
* a captured run still reads as one block.
|
|
22
|
+
*/
|
|
23
|
+
const PLAIN: Palette = {
|
|
24
|
+
GREEN: '',
|
|
25
|
+
RED: '',
|
|
26
|
+
YELLOW: '',
|
|
27
|
+
WHITE: '',
|
|
28
|
+
GREY: '',
|
|
29
|
+
NC: '',
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* `NO_COLOR` follows the published convention, where any non-empty value turns
|
|
34
|
+
* color off whatever the value says.
|
|
35
|
+
*/
|
|
36
|
+
export function supportsColor(stream: { isTTY?: boolean }): boolean {
|
|
37
|
+
const optOut = process.env.NO_COLOR
|
|
38
|
+
if (optOut !== undefined && optOut !== '') return false
|
|
39
|
+
return stream.isTTY === true
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The question is asked per stream rather than once for the process. The framed
|
|
44
|
+
* output goes to stderr and a structured record to stdout, so a run piping only
|
|
45
|
+
* its data keeps a terminal on stderr and keeps its color there. This is a
|
|
46
|
+
* third question again from `isNonInteractive`, which answers whether a caller
|
|
47
|
+
* can be prompted rather than whether a destination renders escapes.
|
|
48
|
+
*
|
|
49
|
+
* Read at write time rather than at import, so nothing freezes an answer taken
|
|
50
|
+
* before the caller's environment was in place.
|
|
51
|
+
*/
|
|
52
|
+
export function palette(stream: { isTTY?: boolean }): Palette {
|
|
53
|
+
return supportsColor(stream) ? COLOR : PLAIN
|
|
54
|
+
}
|
|
7
55
|
|
|
8
56
|
export function intro(title: string): void {
|
|
57
|
+
const { GREY, NC, WHITE } = palette(process.stderr)
|
|
9
58
|
process.stderr.write(`${GREY}┌${NC}\n${GREY}│${NC} ${WHITE}${title}${NC}\n`)
|
|
10
59
|
}
|
|
11
60
|
|
|
@@ -15,18 +64,22 @@ export function intro(title: string): void {
|
|
|
15
64
|
* leaving stdout clean for JSON and lists.
|
|
16
65
|
*/
|
|
17
66
|
export function logInfo(message: string): void {
|
|
67
|
+
const { GREEN, GREY, NC } = palette(process.stderr)
|
|
18
68
|
process.stderr.write(`${GREY}│${NC} ${GREEN}✓${NC} ${message}\n`)
|
|
19
69
|
}
|
|
20
70
|
|
|
21
71
|
export function logWarn(message: string): void {
|
|
72
|
+
const { GREY, NC, YELLOW } = palette(process.stderr)
|
|
22
73
|
process.stderr.write(`${GREY}│${NC} ${YELLOW}!${NC} ${message}\n`)
|
|
23
74
|
}
|
|
24
75
|
|
|
25
76
|
export function logAdd(message: string): void {
|
|
77
|
+
const { GREEN, GREY, NC } = palette(process.stderr)
|
|
26
78
|
process.stderr.write(`${GREY}│${NC} ${GREEN}+${NC} ${message}\n`)
|
|
27
79
|
}
|
|
28
80
|
|
|
29
81
|
export function logRemove(message: string): void {
|
|
82
|
+
const { GREY, NC, RED } = palette(process.stderr)
|
|
30
83
|
process.stderr.write(`${GREY}│${NC} ${RED}-${NC} ${message}\n`)
|
|
31
84
|
}
|
|
32
85
|
|
|
@@ -36,14 +89,17 @@ export function logRemove(message: string): void {
|
|
|
36
89
|
* exit code rather than terminating mid-write.
|
|
37
90
|
*/
|
|
38
91
|
export function logError(message: string): void {
|
|
92
|
+
const { GREY, NC, RED } = palette(process.stderr)
|
|
39
93
|
process.stderr.write(`${GREY}│${NC} ${RED}✗${NC} ${message}\n`)
|
|
40
94
|
}
|
|
41
95
|
|
|
42
96
|
export function logStep(message: string): void {
|
|
97
|
+
const { GREY, NC, WHITE } = palette(process.stderr)
|
|
43
98
|
process.stderr.write(`${GREY}│${NC}\n${GREY}├${NC} ${WHITE}${message}${NC}\n`)
|
|
44
99
|
}
|
|
45
100
|
|
|
46
101
|
export function outro(): void {
|
|
102
|
+
const { GREY, NC } = palette(process.stderr)
|
|
47
103
|
process.stderr.write(`${GREY}└${NC}\n`)
|
|
48
104
|
}
|
|
49
105
|
|
|
@@ -53,6 +109,7 @@ export function outro(): void {
|
|
|
53
109
|
* such as a pull request body or the output of a git mutation.
|
|
54
110
|
*/
|
|
55
111
|
export function pipeOutput(text: string): void {
|
|
112
|
+
const { GREY, NC } = palette(process.stderr)
|
|
56
113
|
const lines = text.replace(/\n$/, '').split('\n')
|
|
57
114
|
process.stderr.write(
|
|
58
115
|
`${lines.map((line) => `${GREY}│${NC} ${line}`).join('\n')}\n`,
|
|
@@ -65,12 +122,14 @@ export function plural(count: number, noun: string): string {
|
|
|
65
122
|
}
|
|
66
123
|
|
|
67
124
|
export function frameError(message: string): void {
|
|
125
|
+
const { GREY, NC, RED } = palette(process.stderr)
|
|
68
126
|
process.stderr.write(
|
|
69
127
|
`${GREY}┌${NC}\n${GREY}│${NC} ${RED}✗${NC} ${message}\n${GREY}└${NC}\n`,
|
|
70
128
|
)
|
|
71
129
|
}
|
|
72
130
|
|
|
73
131
|
export function frameSuccess(command: string, target: string): void {
|
|
132
|
+
const { GREEN, GREY, NC, WHITE } = palette(process.stderr)
|
|
74
133
|
process.stderr.write(
|
|
75
134
|
`${GREY}┌${NC}\n${GREY}│${NC} ${WHITE}${command}${NC}\n${GREY}│${NC}\n${GREY}│${NC} ${GREEN}✓${NC} ${target}\n${GREY}└${NC}\n`,
|
|
76
135
|
)
|
|
@@ -92,6 +151,7 @@ export async function select<Value>(opts: {
|
|
|
92
151
|
nonInteractiveDefault?: boolean
|
|
93
152
|
}): Promise<Value> {
|
|
94
153
|
const { message, options } = opts
|
|
154
|
+
const { GREEN, GREY, NC, RED, WHITE } = palette(process.stderr)
|
|
95
155
|
const count = options.length
|
|
96
156
|
let cursor = 0
|
|
97
157
|
|
package/standards/design.md
CHANGED
|
@@ -34,6 +34,16 @@ Does not govern:
|
|
|
34
34
|
- Plain English over technical notation. If a section could be removed and the developer would still build correctly from wireframes and code alone, remove it.
|
|
35
35
|
- Keep table headers and role names intact so the render tooling can parse the token tables.
|
|
36
36
|
|
|
37
|
+
## The uncertainty tag
|
|
38
|
+
|
|
39
|
+
A cell no source anchors ends in ` ? verify`, written inside the cell rather than as a trailing column, since a trailing marker breaks the table parse. A cell wrapping itself in a code span carries the tag inside the span, as in `` `#ffffff ? verify` ``. Both spellings parse.
|
|
40
|
+
|
|
41
|
+
The renderer splits the tag off the value, so a swatch and a font sample are built from the value alone and the marker shows beside it. The preview also reports how many cells are anchored against how many are tagged, which is the reading a reviewer takes the record's overall confidence from.
|
|
42
|
+
|
|
43
|
+
Which columns that ratio reads is fixed by the table rather than by the record. The first column of each table names its row, and `Multiplier` and `When used` restate what the row already carries, so none of them is something a source could anchor and none is counted. That leaves `Intent` and `Value` in Color, `Family`, `Weight`, `Size`, and `Line height` in Typography, `Value` in Spacing, and `Radius` and `Width` in Borders. A cell tagged outside that set counts anyway, so a marker the preview draws is never missing from the ratio beside it.
|
|
44
|
+
|
|
45
|
+
A prose section takes its uncertainty inline instead, in a sentence saying what is proposed and what has yet to confirm it. A tag appended to a paragraph renders verbatim.
|
|
46
|
+
|
|
37
47
|
## Sections
|
|
38
48
|
|
|
39
49
|
Use `## Personality`, `## Color`, `## Typography`, `## Spacing`, `## Borders`, `## Motion`, and `## Iconography`. The token tables carry fixed headers the renderer reads.
|