pi-anchor 0.3.0 → 0.5.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 +38 -174
- package/README_zh.md +36 -184
- package/assets/hero-en.svg +48 -47
- package/assets/hero-zh.svg +48 -47
- package/bin/anchor.js +68 -70
- package/dist/chunk-VXEQDTK4.js +1310 -0
- package/dist/extension-Cq1NH1jT.d.cts +205 -0
- package/dist/extension-Cq1NH1jT.d.ts +205 -0
- package/dist/extension.cjs +617 -1354
- package/dist/extension.d.cts +2 -20
- package/dist/extension.d.ts +2 -20
- package/dist/extension.js +6 -536
- package/dist/index.cjs +452 -1152
- package/dist/index.d.cts +22 -250
- package/dist/index.d.ts +22 -250
- package/dist/index.js +21 -103
- package/package.json +2 -2
- package/src/extension.ts +265 -376
- package/src/index.ts +1 -6
- package/src/pi-types.d.ts +5 -1
- package/src/store.ts +385 -427
- package/src/tui.ts +166 -307
- package/src/types.ts +35 -63
- package/dist/chunk-Q7IILJFA.js +0 -1563
- package/dist/store-t2_TDhJn.d.cts +0 -210
- package/dist/store-t2_TDhJn.d.ts +0 -210
- package/src/context_injector.ts +0 -166
- package/src/decay.ts +0 -125
- package/src/matcher.ts +0 -202
- package/src/observer.ts +0 -141
- package/src/protocol.ts +0 -95
- package/src/settlement.ts +0 -140
package/assets/hero-en.svg
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 410" width="840" height="410">
|
|
2
2
|
<defs>
|
|
3
3
|
<filter id="shadow" x="-5%" y="-5%" width="110%" height="115%" filterUnits="userSpaceOnUse">
|
|
4
4
|
<feDropShadow dx="0" dy="12" stdDeviation="16" flood-color="#000000" flood-opacity="0.45" />
|
|
@@ -10,78 +10,79 @@
|
|
|
10
10
|
</defs>
|
|
11
11
|
|
|
12
12
|
<g filter="url(#shadow)">
|
|
13
|
-
<rect x="20" y="15" width="800" height="
|
|
13
|
+
<rect x="20" y="15" width="800" height="370" rx="12" fill="#1e2326" stroke="#343f44" stroke-width="1.2" />
|
|
14
14
|
<path d="M 20,27 A 12,12 0 0,1 32,15 L 808,15 A 12,12 0 0,1 820,27 L 820,52 L 20,52 Z" fill="url(#headerGrad)" stroke="#343f44" stroke-width="1" />
|
|
15
15
|
<line x1="20" y1="52" x2="820" y2="52" stroke="#2d353b" stroke-width="1" />
|
|
16
16
|
<circle cx="42" cy="33.5" r="5.5" fill="#e67e80" />
|
|
17
17
|
<circle cx="60" cy="33.5" r="5.5" fill="#dbbc7f" />
|
|
18
18
|
<circle cx="78" cy="33.5" r="5.5" fill="#a7c080" />
|
|
19
19
|
<text x="420" y="38" text-anchor="middle" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" font-size="12" font-weight="500" fill="#859289">
|
|
20
|
-
⌖ anchor (v0.
|
|
20
|
+
⌖ anchor (v0.5.0) · Below-Editor Sticky Strip · Progress Bar · Session Teleport
|
|
21
21
|
</text>
|
|
22
22
|
</g>
|
|
23
23
|
|
|
24
24
|
<g font-family="'JetBrains Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace" font-size="13" xml:space="preserve">
|
|
25
25
|
<text x="45" y="84">
|
|
26
|
-
<tspan fill="#
|
|
27
|
-
<tspan fill="#7fbbb3"> ❯ </tspan>
|
|
28
|
-
<tspan fill="#d3c6aa" font-weight="bold">anchor</tspan>
|
|
26
|
+
<tspan fill="#7fbbb3" font-weight="bold">⌖ Notes (3):</tspan>
|
|
29
27
|
</text>
|
|
30
28
|
|
|
31
29
|
<text x="45" y="116">
|
|
32
|
-
<tspan fill="#7fbbb3" font-weight="bold">⌖ Anchors </tspan>
|
|
33
|
-
<tspan fill="#859289">(3 active, 1 quiet · 0 repo clutter · 0 idle tokens):</tspan>
|
|
34
|
-
</text>
|
|
35
|
-
|
|
36
|
-
<text x="45" y="152">
|
|
37
30
|
<tspan fill="#859289"> 01 </tspan>
|
|
38
|
-
<tspan fill="#
|
|
39
|
-
<tspan fill="#d3c6aa">
|
|
40
|
-
<tspan fill="#7fbbb3">
|
|
41
|
-
<tspan fill="#
|
|
42
|
-
<tspan fill="#7a8478">Today 10:02</tspan>
|
|
31
|
+
<tspan fill="#a7c080" font-weight="bold">[■■□□ 2/4] </tspan>
|
|
32
|
+
<tspan fill="#d3c6aa">Refactor auth flow </tspan>
|
|
33
|
+
<tspan fill="#7fbbb3">app · auth.ts ↪ </tspan>
|
|
34
|
+
<tspan fill="#7a8478">25m ago</tspan>
|
|
43
35
|
</text>
|
|
44
36
|
|
|
45
|
-
<text x="45" y="
|
|
37
|
+
<text x="45" y="144">
|
|
46
38
|
<tspan fill="#859289"> 02 </tspan>
|
|
47
|
-
<tspan fill="#
|
|
48
|
-
<tspan fill="#
|
|
49
|
-
<tspan fill="#
|
|
50
|
-
<tspan fill="#dbbc7f">Tomorrow </tspan>
|
|
51
|
-
<tspan fill="#7a8478">Yesterday 21:34</tspan>
|
|
39
|
+
<tspan fill="#d3c6aa">Double-check rate limit fallback on timeout </tspan>
|
|
40
|
+
<tspan fill="#7fbbb3">app · gateway.ts ↪ </tspan>
|
|
41
|
+
<tspan fill="#7a8478">3h ago</tspan>
|
|
52
42
|
</text>
|
|
53
43
|
|
|
54
|
-
<text x="45" y="
|
|
44
|
+
<text x="45" y="172">
|
|
55
45
|
<tspan fill="#859289"> 03 </tspan>
|
|
56
|
-
<tspan fill="#
|
|
57
|
-
<tspan fill="#
|
|
58
|
-
<tspan fill="#
|
|
59
|
-
<tspan fill="#a7c080">In 2d </tspan>
|
|
60
|
-
<tspan fill="#7a8478">Today 10:02</tspan>
|
|
46
|
+
<tspan fill="#859289">Read external architecture notes first </tspan>
|
|
47
|
+
<tspan fill="#7a8478">College/优化 · notes.md </tspan>
|
|
48
|
+
<tspan fill="#56635f">8d ago · quiet</tspan>
|
|
61
49
|
</text>
|
|
62
50
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<tspan fill="#
|
|
67
|
-
<tspan fill="#
|
|
68
|
-
<tspan fill="#7a8478">Quiet (0 tok) </tspan>
|
|
69
|
-
<tspan fill="#56635f">09-28 14:20</tspan>
|
|
51
|
+
<!-- Simulated Pi Input Box + Below-Editor Persistent Sticky Strip -->
|
|
52
|
+
<rect x="45" y="204" width="750" height="44" rx="6" fill="#232a2e" stroke="#4f5b58" stroke-width="1.2" />
|
|
53
|
+
<text x="62" y="231">
|
|
54
|
+
<tspan fill="#a7c080" font-weight="bold">❯ </tspan>
|
|
55
|
+
<tspan fill="#d3c6aa">pin: Refactor auth flow: 1. Extract interface 2. HttpOnly cookie 3. Unit tests</tspan>
|
|
70
56
|
</text>
|
|
71
57
|
|
|
72
|
-
|
|
73
|
-
<
|
|
74
|
-
<text x="62" y="
|
|
58
|
+
<!-- Below-Editor Sticky Strip -->
|
|
59
|
+
<rect x="45" y="256" width="750" height="36" rx="6" fill="#292b28" stroke="#a7c080" stroke-width="1" stroke-dasharray="4,3" />
|
|
60
|
+
<text x="62" y="279">
|
|
61
|
+
<tspan fill="#a7c080" font-weight="bold">⌖ </tspan>
|
|
62
|
+
<tspan fill="#859289">#1 </tspan>
|
|
63
|
+
<tspan fill="#dbbc7f" font-weight="bold">[■■□□ 2/4] </tspan>
|
|
64
|
+
<tspan fill="#d3c6aa">Refactor auth flow </tspan>
|
|
65
|
+
<tspan fill="#7fbbb3">▸ HttpOnly cookie </tspan>
|
|
66
|
+
<tspan fill="#859289">(app · auth.ts ↪)</tspan>
|
|
67
|
+
</text>
|
|
75
68
|
|
|
76
|
-
<text x="45" y="
|
|
77
|
-
<tspan>
|
|
78
|
-
<tspan fill="#
|
|
79
|
-
<tspan
|
|
80
|
-
<tspan fill="#7fbbb3"
|
|
81
|
-
<tspan>
|
|
82
|
-
<tspan fill="#7fbbb3"
|
|
83
|
-
<tspan>
|
|
84
|
-
|
|
69
|
+
<text x="45" y="324" fill="#859289">
|
|
70
|
+
<tspan> • </tspan>
|
|
71
|
+
<tspan fill="#d3c6aa" font-weight="bold">0ms Instant Stick</tspan>
|
|
72
|
+
<tspan>: Type </tspan>
|
|
73
|
+
<tspan fill="#7fbbb3">`pin: <note>`</tspan>
|
|
74
|
+
<tspan> (or </tspan>
|
|
75
|
+
<tspan fill="#7fbbb3">`/pin`</tspan>
|
|
76
|
+
<tspan>) — docked below editor, never collides with aboveEditor HUDs.</tspan>
|
|
77
|
+
</text>
|
|
78
|
+
<text x="45" y="348" fill="#859289">
|
|
79
|
+
<tspan> • </tspan>
|
|
80
|
+
<tspan fill="#d3c6aa" font-weight="bold">Session Teleport (↪)</tspan>
|
|
81
|
+
<tspan>: Select any note in </tspan>
|
|
82
|
+
<tspan fill="#7fbbb3">`/anchor`</tspan>
|
|
83
|
+
<tspan> or run </tspan>
|
|
84
|
+
<tspan fill="#7fbbb3">`/anchor jump 1`</tspan>
|
|
85
|
+
<tspan> to resume its conversation.</tspan>
|
|
85
86
|
</text>
|
|
86
87
|
</g>
|
|
87
88
|
</svg>
|
package/assets/hero-zh.svg
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 410" width="840" height="410">
|
|
2
2
|
<defs>
|
|
3
3
|
<filter id="shadow" x="-5%" y="-5%" width="110%" height="115%" filterUnits="userSpaceOnUse">
|
|
4
4
|
<feDropShadow dx="0" dy="12" stdDeviation="16" flood-color="#000000" flood-opacity="0.45" />
|
|
@@ -10,78 +10,79 @@
|
|
|
10
10
|
</defs>
|
|
11
11
|
|
|
12
12
|
<g filter="url(#shadow)">
|
|
13
|
-
<rect x="20" y="15" width="800" height="
|
|
13
|
+
<rect x="20" y="15" width="800" height="370" rx="12" fill="#1e2326" stroke="#343f44" stroke-width="1.2" />
|
|
14
14
|
<path d="M 20,27 A 12,12 0 0,1 32,15 L 808,15 A 12,12 0 0,1 820,27 L 820,52 L 20,52 Z" fill="url(#headerGrad)" stroke="#343f44" stroke-width="1" />
|
|
15
15
|
<line x1="20" y1="52" x2="820" y2="52" stroke="#2d353b" stroke-width="1" />
|
|
16
16
|
<circle cx="42" cy="33.5" r="5.5" fill="#e67e80" />
|
|
17
17
|
<circle cx="60" cy="33.5" r="5.5" fill="#dbbc7f" />
|
|
18
18
|
<circle cx="78" cy="33.5" r="5.5" fill="#a7c080" />
|
|
19
19
|
<text x="420" y="38" text-anchor="middle" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" font-size="12" font-weight="500" fill="#859289">
|
|
20
|
-
⌖ anchor (v0.
|
|
20
|
+
⌖ anchor (v0.5.0) · 输入框下方常驻便签条 · 迷你进度条 · 原对话一键穿越
|
|
21
21
|
</text>
|
|
22
22
|
</g>
|
|
23
23
|
|
|
24
24
|
<g font-family="'JetBrains Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace" font-size="13" xml:space="preserve">
|
|
25
25
|
<text x="45" y="84">
|
|
26
|
-
<tspan fill="#
|
|
27
|
-
<tspan fill="#7fbbb3"> ❯ </tspan>
|
|
28
|
-
<tspan fill="#d3c6aa" font-weight="bold">anchor</tspan>
|
|
26
|
+
<tspan fill="#7fbbb3" font-weight="bold">⌖ Notes (3):</tspan>
|
|
29
27
|
</text>
|
|
30
28
|
|
|
31
29
|
<text x="45" y="116">
|
|
32
|
-
<tspan fill="#7fbbb3" font-weight="bold">⌖ Anchors </tspan>
|
|
33
|
-
<tspan fill="#859289">(3 active, 1 quiet · 0 仓库污染 · 0 闲置 Token):</tspan>
|
|
34
|
-
</text>
|
|
35
|
-
|
|
36
|
-
<text x="45" y="152">
|
|
37
30
|
<tspan fill="#859289"> 01 </tspan>
|
|
38
|
-
<tspan fill="#
|
|
39
|
-
<tspan fill="#d3c6aa"
|
|
40
|
-
<tspan fill="#7fbbb3">
|
|
41
|
-
<tspan fill="#
|
|
42
|
-
<tspan fill="#7a8478">Today 10:02</tspan>
|
|
31
|
+
<tspan fill="#a7c080" font-weight="bold">[■■□□ 2/4] </tspan>
|
|
32
|
+
<tspan fill="#d3c6aa">重构登录鉴权流 </tspan>
|
|
33
|
+
<tspan fill="#7fbbb3">app · auth.ts ↪ </tspan>
|
|
34
|
+
<tspan fill="#7a8478">25m ago</tspan>
|
|
43
35
|
</text>
|
|
44
36
|
|
|
45
|
-
<text x="45" y="
|
|
37
|
+
<text x="45" y="144">
|
|
46
38
|
<tspan fill="#859289"> 02 </tspan>
|
|
47
|
-
<tspan fill="#
|
|
48
|
-
<tspan fill="#
|
|
49
|
-
<tspan fill="#
|
|
50
|
-
<tspan fill="#dbbc7f">Tomorrow </tspan>
|
|
51
|
-
<tspan fill="#7a8478">Yesterday 21:34</tspan>
|
|
39
|
+
<tspan fill="#d3c6aa">检查网关超时后的降级重试边界 </tspan>
|
|
40
|
+
<tspan fill="#7fbbb3">app · gateway.ts ↪ </tspan>
|
|
41
|
+
<tspan fill="#7a8478">3h ago</tspan>
|
|
52
42
|
</text>
|
|
53
43
|
|
|
54
|
-
<text x="45" y="
|
|
44
|
+
<text x="45" y="172">
|
|
55
45
|
<tspan fill="#859289"> 03 </tspan>
|
|
56
|
-
<tspan fill="#
|
|
57
|
-
<tspan fill="#
|
|
58
|
-
<tspan fill="#
|
|
59
|
-
<tspan fill="#a7c080">In 2d </tspan>
|
|
60
|
-
<tspan fill="#7a8478">Today 10:02</tspan>
|
|
46
|
+
<tspan fill="#859289">College 重构前置查阅外部架构参考库 </tspan>
|
|
47
|
+
<tspan fill="#7a8478">College/优化 · notes.md </tspan>
|
|
48
|
+
<tspan fill="#56635f">8d ago · quiet</tspan>
|
|
61
49
|
</text>
|
|
62
50
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<tspan fill="#
|
|
67
|
-
<tspan fill="#
|
|
68
|
-
<tspan fill="#7a8478">Quiet (0 tok) </tspan>
|
|
69
|
-
<tspan fill="#56635f">09-28 14:20</tspan>
|
|
51
|
+
<!-- Simulated Pi Input Box + Below-Editor Persistent Sticky Strip -->
|
|
52
|
+
<rect x="45" y="204" width="750" height="44" rx="6" fill="#232a2e" stroke="#4f5b58" stroke-width="1.2" />
|
|
53
|
+
<text x="62" y="231">
|
|
54
|
+
<tspan fill="#a7c080" font-weight="bold">❯ </tspan>
|
|
55
|
+
<tspan fill="#d3c6aa">便签: 重构登录鉴权流: 1. 抽出接口 2. 替换Cookie 3. 补单测 4. 压测</tspan>
|
|
70
56
|
</text>
|
|
71
57
|
|
|
72
|
-
|
|
73
|
-
<
|
|
74
|
-
<text x="62" y="
|
|
58
|
+
<!-- Below-Editor Sticky Strip -->
|
|
59
|
+
<rect x="45" y="256" width="750" height="36" rx="6" fill="#292b28" stroke="#a7c080" stroke-width="1" stroke-dasharray="4,3" />
|
|
60
|
+
<text x="62" y="279">
|
|
61
|
+
<tspan fill="#a7c080" font-weight="bold">⌖ </tspan>
|
|
62
|
+
<tspan fill="#859289">#1 </tspan>
|
|
63
|
+
<tspan fill="#dbbc7f" font-weight="bold">[■■□□ 2/4] </tspan>
|
|
64
|
+
<tspan fill="#d3c6aa">重构登录鉴权流 </tspan>
|
|
65
|
+
<tspan fill="#7fbbb3">▸ 补单测 </tspan>
|
|
66
|
+
<tspan fill="#859289">(app · auth.ts ↪)</tspan>
|
|
67
|
+
</text>
|
|
75
68
|
|
|
76
|
-
<text x="45" y="
|
|
77
|
-
<tspan>
|
|
78
|
-
<tspan fill="#
|
|
79
|
-
<tspan
|
|
80
|
-
<tspan fill="#7fbbb3"
|
|
81
|
-
<tspan>
|
|
82
|
-
<tspan fill="#7fbbb3"
|
|
83
|
-
<tspan>
|
|
84
|
-
<tspan fill="#7fbbb3"
|
|
69
|
+
<text x="45" y="324" fill="#859289">
|
|
70
|
+
<tspan> • </tspan>
|
|
71
|
+
<tspan fill="#d3c6aa" font-weight="bold">输入框下方常驻 1 行便签条</tspan>
|
|
72
|
+
<tspan>:采用 </tspan>
|
|
73
|
+
<tspan fill="#7fbbb3">belowEditor</tspan>
|
|
74
|
+
<tspan> 挂载,与上方 </tspan>
|
|
75
|
+
<tspan fill="#7fbbb3">pi-lingual</tspan>
|
|
76
|
+
<tspan> 零冲突;敲 </tspan>
|
|
77
|
+
<tspan fill="#7fbbb3">便签: ...</tspan>
|
|
78
|
+
<tspan> 0ms 瞬贴。</tspan>
|
|
79
|
+
</text>
|
|
80
|
+
<text x="45" y="348" fill="#859289">
|
|
81
|
+
<tspan> • </tspan>
|
|
82
|
+
<tspan fill="#d3c6aa" font-weight="bold">原对话一键穿越 (↪)</tspan>
|
|
83
|
+
<tspan>:自动记录贴便签时的 Session,在 </tspan>
|
|
84
|
+
<tspan fill="#7fbbb3">/anchor</tspan>
|
|
85
|
+
<tspan> 中点击即可直接切回当时的对话上下文。</tspan>
|
|
85
86
|
</text>
|
|
86
87
|
</g>
|
|
87
88
|
</svg>
|
package/bin/anchor.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Anchor CLI
|
|
5
|
-
* Production-ready executable with dual-timeline & 4-quadrant cognitive grouping
|
|
4
|
+
* Anchor CLI — Minimalist terminal sticky notes for AI coding
|
|
6
5
|
*/
|
|
7
6
|
|
|
8
7
|
import {
|
|
9
8
|
AnchorStore,
|
|
10
9
|
formatOrigin,
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
formatProgressBar,
|
|
11
|
+
formatRelativeAge,
|
|
13
12
|
sortAnchorsForDisplay,
|
|
14
13
|
padToWidth
|
|
15
14
|
} from '../dist/index.js';
|
|
@@ -17,55 +16,71 @@ import {
|
|
|
17
16
|
const store = new AnchorStore();
|
|
18
17
|
const args = process.argv.slice(2);
|
|
19
18
|
|
|
20
|
-
// 1. View
|
|
19
|
+
// 1. View sticky notes: `anchor` or `anchor list`
|
|
21
20
|
if (args.length === 0 || args[0] === 'list' || args[0] === 'ls') {
|
|
22
|
-
const
|
|
21
|
+
const allNotes = store
|
|
23
22
|
.list({ cwd: process.cwd(), all: true })
|
|
24
23
|
.filter(a => a.status === 'active' || a.status === 'sleeping');
|
|
25
24
|
|
|
26
|
-
if (
|
|
27
|
-
console.log('\n⌖ No
|
|
25
|
+
if (allNotes.length === 0) {
|
|
26
|
+
console.log('\n⌖ No sticky notes. Run `anchor "<note>"` to stick one.\n');
|
|
28
27
|
process.exit(0);
|
|
29
28
|
}
|
|
30
29
|
|
|
31
|
-
const sorted = sortAnchorsForDisplay(
|
|
32
|
-
|
|
33
|
-
const quietCount = sorted.length - activeCount;
|
|
34
|
-
const headerSuffix = quietCount > 0 ? `${activeCount} active, ${quietCount} quiet` : `${activeCount} active`;
|
|
35
|
-
|
|
36
|
-
console.log(`\n⌖ Anchors (${headerSuffix}):\n`);
|
|
30
|
+
const sorted = sortAnchorsForDisplay(allNotes, process.cwd());
|
|
31
|
+
console.log(`\n⌖ Notes (${sorted.length}):\n`);
|
|
37
32
|
|
|
38
33
|
sorted.forEach((a, idx) => {
|
|
39
34
|
const num = String(idx + 1).padStart(2, '0');
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const created = formatCreationTime(a.createdAt);
|
|
46
|
-
|
|
47
|
-
const titleWithFiles = (a.files && a.files.length > 0)
|
|
48
|
-
? `${a.title} [${a.files.slice(0, 1).join(', ')}]`
|
|
49
|
-
: a.title;
|
|
35
|
+
const bar = a.progress ? `${formatProgressBar(a.progress)} ` : '';
|
|
36
|
+
const origin = formatOrigin(a) + (a.sessionFile ? ' ↪' : '');
|
|
37
|
+
const age = a.status === 'sleeping'
|
|
38
|
+
? `${formatRelativeAge(a.createdAt)} · quiet`
|
|
39
|
+
: formatRelativeAge(a.createdAt);
|
|
50
40
|
|
|
51
41
|
const colNum = ` ${num} `;
|
|
52
|
-
const colTitle = padToWidth(
|
|
53
|
-
const colOrigin = padToWidth(origin,
|
|
54
|
-
const colTarget = padToWidth(target, 14);
|
|
55
|
-
const colCreated = created;
|
|
42
|
+
const colTitle = padToWidth(`${bar}${a.title}`, 42);
|
|
43
|
+
const colOrigin = padToWidth(origin, 22);
|
|
56
44
|
|
|
57
|
-
console.log(`${colNum}${
|
|
45
|
+
console.log(`${colNum}${colTitle} ${colOrigin} ${age}`);
|
|
58
46
|
});
|
|
59
47
|
|
|
60
|
-
console.log('\n
|
|
48
|
+
console.log('\n Run `anchor step <num>` (+1 step), `anchor done <num>` (tear off), or `anchor undo`.\n');
|
|
61
49
|
process.exit(0);
|
|
62
50
|
}
|
|
63
51
|
|
|
64
|
-
// 2.
|
|
52
|
+
// 2. Put back last torn-off note: `anchor undo`
|
|
65
53
|
if (args[0] === 'undo') {
|
|
66
54
|
try {
|
|
67
55
|
const restored = store.undoSettle();
|
|
68
|
-
console.log(`⌖
|
|
56
|
+
console.log(`⌖ Put back #${restored.id.replace(/^anc-/, '')}: "${restored.title}"`);
|
|
57
|
+
} catch (err) {
|
|
58
|
+
console.error(`Error: ${err.message}`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
process.exit(0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 3. Advance progress bar: `anchor step <num>`
|
|
65
|
+
if (args[0] === 'step' || args[0] === '+') {
|
|
66
|
+
const idInput = args[1] || '1';
|
|
67
|
+
const delta = args[2] ? parseInt(args[2], 10) : 1;
|
|
68
|
+
try {
|
|
69
|
+
const allNotes = store
|
|
70
|
+
.list({ cwd: process.cwd(), all: true })
|
|
71
|
+
.filter(a => a.status === 'active' || a.status === 'sleeping');
|
|
72
|
+
const sorted = sortAnchorsForDisplay(allNotes, process.cwd());
|
|
73
|
+
|
|
74
|
+
let targetId = idInput;
|
|
75
|
+
if (/^\d+$/.test(idInput)) {
|
|
76
|
+
const seqIndex = parseInt(idInput, 10);
|
|
77
|
+
if (seqIndex >= 1 && seqIndex <= sorted.length) {
|
|
78
|
+
targetId = sorted[seqIndex - 1].id;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const { anchor: updated } = store.step(targetId, isNaN(delta) ? 1 : delta);
|
|
83
|
+
console.log(`⌖ Advanced #${updated.id.replace(/^anc-/, '')} to ${formatProgressBar(updated.progress)}: "${updated.title}"`);
|
|
69
84
|
} catch (err) {
|
|
70
85
|
console.error(`Error: ${err.message}`);
|
|
71
86
|
process.exit(1);
|
|
@@ -73,53 +88,44 @@ if (args[0] === 'undo') {
|
|
|
73
88
|
process.exit(0);
|
|
74
89
|
}
|
|
75
90
|
|
|
76
|
-
//
|
|
91
|
+
// 4. Help: `anchor --help`
|
|
77
92
|
if (args[0] === '--help' || args[0] === '-h' || args[0] === 'help') {
|
|
78
93
|
console.log(`
|
|
79
|
-
⌖ Anchor
|
|
94
|
+
⌖ Anchor — Digital sticky notes for AI coding sessions
|
|
80
95
|
|
|
81
96
|
Usage:
|
|
82
|
-
anchor
|
|
83
|
-
anchor <
|
|
84
|
-
anchor
|
|
85
|
-
anchor
|
|
86
|
-
|
|
87
|
-
Options:
|
|
88
|
-
-h, --help Show this help message
|
|
89
|
-
-v, --version Show version
|
|
90
|
-
-d, --due <date> Specify expected completion date (e.g. tomorrow, friday, 2026-09-28)
|
|
97
|
+
anchor View all sticky notes
|
|
98
|
+
anchor "<note>" Stick a new note (supports [1/4] or 1. A 2. B progress steps)
|
|
99
|
+
anchor step <num> Advance progress bar on a note (e.g. anchor step 1)
|
|
100
|
+
anchor done <num> Tear off a completed note (e.g. anchor done 1)
|
|
101
|
+
anchor undo Put back the last torn-off note
|
|
91
102
|
`);
|
|
92
103
|
process.exit(0);
|
|
93
104
|
}
|
|
94
105
|
|
|
95
|
-
//
|
|
106
|
+
// 5. Tear off note: `anchor done <num>`
|
|
96
107
|
if (args[0] === 'done' || args[0] === 'rm' || args[0] === 'close') {
|
|
97
108
|
const idInput = args[1];
|
|
98
109
|
if (!idInput) {
|
|
99
|
-
console.error('Usage: anchor done <
|
|
110
|
+
console.error('Usage: anchor done <num>');
|
|
100
111
|
process.exit(1);
|
|
101
112
|
}
|
|
102
113
|
try {
|
|
103
|
-
|
|
104
|
-
const allUnfinished = store
|
|
114
|
+
const allNotes = store
|
|
105
115
|
.list({ cwd: process.cwd(), all: true })
|
|
106
116
|
.filter(a => a.status === 'active' || a.status === 'sleeping');
|
|
107
|
-
const
|
|
117
|
+
const sorted = sortAnchorsForDisplay(allNotes, process.cwd());
|
|
108
118
|
|
|
109
119
|
let targetId = idInput;
|
|
110
|
-
|
|
111
|
-
if (numMatch) {
|
|
120
|
+
if (/^\d+$/.test(idInput)) {
|
|
112
121
|
const seqIndex = parseInt(idInput, 10);
|
|
113
|
-
if (seqIndex >= 1 && seqIndex <=
|
|
114
|
-
targetId =
|
|
122
|
+
if (seqIndex >= 1 && seqIndex <= sorted.length) {
|
|
123
|
+
targetId = sorted[seqIndex - 1].id;
|
|
115
124
|
}
|
|
116
125
|
}
|
|
117
126
|
|
|
118
|
-
const settled = store.settle(targetId, { settledBy: 'manual
|
|
119
|
-
|
|
120
|
-
? `⌖ Completed for today: "${settled.title}" (resets tomorrow)`
|
|
121
|
-
: `⌖ Settled: "${settled.title}"`;
|
|
122
|
-
console.log(successMsg);
|
|
127
|
+
const settled = store.settle(targetId, { settledBy: 'manual' });
|
|
128
|
+
console.log(`⌖ Torn off: "${settled.title}"`);
|
|
123
129
|
} catch (err) {
|
|
124
130
|
console.error(`Error: ${err.message}`);
|
|
125
131
|
process.exit(1);
|
|
@@ -127,24 +133,16 @@ if (args[0] === 'done' || args[0] === 'rm' || args[0] === 'close') {
|
|
|
127
133
|
process.exit(0);
|
|
128
134
|
}
|
|
129
135
|
|
|
130
|
-
//
|
|
131
|
-
let targetDateFlag;
|
|
132
|
-
const dueIdx = args.findIndex(a => a === '--due' || a === '-d');
|
|
133
|
-
if (dueIdx !== -1 && args[dueIdx + 1]) {
|
|
134
|
-
targetDateFlag = args[dueIdx + 1];
|
|
135
|
-
args.splice(dueIdx, 2);
|
|
136
|
-
}
|
|
137
|
-
|
|
136
|
+
// 6. Stick a new note: `anchor <note text>`
|
|
138
137
|
const title = args.join(' ').trim();
|
|
139
138
|
if (!title) {
|
|
140
|
-
console.error('Error:
|
|
139
|
+
console.error('Error: Note text cannot be empty');
|
|
141
140
|
process.exit(1);
|
|
142
141
|
}
|
|
143
142
|
|
|
144
|
-
const
|
|
143
|
+
const created = store.create({
|
|
145
144
|
title,
|
|
146
|
-
targetDate: targetDateFlag,
|
|
147
145
|
cwd: process.cwd()
|
|
148
146
|
});
|
|
149
|
-
const
|
|
150
|
-
console.log(`⌖ Pinned #${
|
|
147
|
+
const bar = created.progress ? ` ${formatProgressBar(created.progress)}` : '';
|
|
148
|
+
console.log(`⌖ Pinned #${created.id.replace(/^anc-/, '')}${bar}: "${created.title}"`);
|