pi-anchor 0.2.3 → 0.3.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 CHANGED
@@ -1,36 +1,49 @@
1
1
  # ⌖ Anchor
2
2
 
3
- > **Zero-pollution, 0-idle-token cross-session task memory for AI coding agents**
4
- > Maintain cross-session intent with zero idle tokens, syntax-safe JIT touch wakeups, and zero git repository pollution.
3
+ > **Compact, Autonomous, Persistent Task Memory for Pi Coding Agent**
4
+ > Pin tasks across sessions (`/pin`), wake them automatically when entering the project or touching files, and settle them in real time on `git commit` — with **0 `TODO.md` repo clutter** and **0 idle tokens**.
5
5
 
6
6
  [![CI Status](https://github.com/3ZEROS12/anchor/actions/workflows/ci.yml/badge.svg)](https://github.com/3ZEROS12/anchor/actions/workflows/ci.yml)
7
7
  [![Node v20+](https://img.shields.io/badge/Node-v20+-22c55e.svg)](package.json)
8
8
  [![TypeScript Strict](https://img.shields.io/badge/TypeScript-Strict-3b82f6.svg)](tsconfig.json)
9
- [![Tests: 29 Passed](https://img.shields.io/badge/Tests-29%20Passed-22c55e.svg)](tests/store.test.ts)
9
+ [![Tests: 34 Passed](https://img.shields.io/badge/Tests-34%20Passed-22c55e.svg)](tests/store.test.ts)
10
10
  [![Startup: < 90ms](https://img.shields.io/badge/Startup-%3C%2090ms-success.svg)](package.json)
11
11
  [![Zero Repo Pollution](https://img.shields.io/badge/Storage-Zero%20Repo%20Pollution-success.svg)](#1-zero-repository-contamination--storage-topology)
12
12
  [![License: MIT](https://img.shields.io/badge/License-MIT-f97316.svg)](LICENSE)
13
13
 
14
14
  **English** | [简体中文](./README_zh.md)
15
15
 
16
+ ```bash
17
+ pi install npm:pi-anchor
18
+ ```
19
+
16
20
  <p align="center">
17
21
  <img src="assets/hero-en.svg" alt="Anchor Terminal Dashboard" width="820">
18
22
  </p>
19
23
 
20
24
  ```text
21
- ⌖ Anchors (4 active):
25
+ ⌖ Anchors (3 active, 1 quiet):
22
26
 
23
- [Today · Today's Focus]
24
- 01 [Today] Optimize token truncation & JIT safety Desktop Today Today 10:02
27
+ 01 [P0] Migrate auth module to HttpOnly cookies [src/auth.ts] anchor Today Today 10:02
28
+ 02 [P1] Add concurrent file lock unit tests anchor Tomorrow Yesterday 21:34
29
+ 03 [P1] Polish CLI interactive dashboard & TUI Desktop In 2d Today 10:02
30
+ 04 [Quiet] Read external architecture notes before refactor College/优化 Quiet (0 tok) 09-28 14:20
25
31
 
26
- [Upcoming · Scheduled]
27
- 02 [Upcoming] Add concurrent file lock unit tests Desktop Tomorrow Yesterday 21:34
28
- 03 [Upcoming] Migrate auth module to HttpOnly cookies Desktop Tomorrow Today 10:02
29
- 04 [Upcoming] Polish CLI interactive dashboard & TUI Desktop In 2d Today 10:02
30
-
31
- Use `anchor done <id>` to complete.
32
+ Use `anchor done <id>` to complete, or `anchor undo` to restore.
32
33
  ```
33
34
 
35
+ ### The Three Pillars: Compact · Autonomous · Persistent
36
+
37
+ 1. **Compact (小巧 · Zero Bloat & 0 Idle Tokens)**:
38
+ - Pure TypeScript (~20KB bundle, zero external runtime dependencies, zero background daemons, zero SQL databases in your repo).
39
+ - Flat, priority-sorted engineering list (`/anchor`, `/pin`, `/done 1`). Briefs the AI on Turn 1 of a session, then drops to **0 tokens** from Turn 2+ while you code.
40
+ 2. **Autonomous (自主 · Smart Path Inference & Real-Time Commit Settlement)**:
41
+ - Automatically extracts file/folder paths mentioned in your task description and binds them to the target workspace even if you pinned the task from another directory.
42
+ - Settles tasks **in real time during the session** the moment `git commit` or a verification test command (`verifyCommand`) succeeds — works for both file-bound and plain-text tasks (`files: []`).
43
+ 3. **Persistent (持久 · Never Loses Unfinished Work)**:
44
+ - Stored safely in `~/.anchor/state.json` outside your git working tree.
45
+ - Unfinished tasks are **never silently deleted**. Tasks untouched for 7+ days enter `[Quiet]` mode (saving Turn 1 prompt tokens), stay 100% visible in `/anchor`, and automatically wake up the moment you open their target project or touch matching files.
46
+
34
47
  ---
35
48
 
36
49
  ## Why Anchor?
@@ -143,8 +156,10 @@ anchor undo # Restore last archived task
143
156
  ### Pi Coding Agent Commands
144
157
  | Command | Description |
145
158
  | :--- | :--- |
146
- | `/pin "task description"` | Pin an anchor task for the current workspace |
159
+ | `/pin <task> [--due tomorrow]` | Pin a task across sessions with optional due date |
147
160
  | `/anchor` | Open interactive terminal task dashboard |
161
+ | `/done <id>` or `/anchor done <id>` | Complete task by row number (`1`) or ID (`anc-1`) |
162
+ | `/anchor undo` | Restore the last settled task |
148
163
  | Status bar `⌖ N` | Displays active task count in status row; 100% hidden when 0 tasks exist |
149
164
 
150
165
  ---
@@ -186,7 +201,7 @@ Engineered with strict TypeScript and 100% standard library test coverage using
186
201
 
187
202
  ```bash
188
203
  npm run typecheck # Strict tsc --noEmit check (0 errors)
189
- npm test # Native Node test runner (29/29 passing)
204
+ npm test # Native Node test runner (34/34 passing)
190
205
  npm run build # Dual ESM/CJS compilation via tsup + declaration emit
191
206
  ```
192
207
 
package/README_zh.md CHANGED
@@ -1,36 +1,49 @@
1
1
  # ⌖ Anchor
2
2
 
3
- > **面向 AI 编程智能体的零污染、0 闲置 Token 跨会话任务记忆系统**
4
- > 告别发霉的 TODO.md。零 Git 历史污染,0 闲置 Token 损耗,代码提交自动核销结算。
3
+ > **面向 Pi Coding Agent 的「小巧 · 自主 · 持久」跨会话任务记忆**
4
+ > 一句话钉住待办(`/pin`),进入目标工程或触碰关联文件自动唤醒,会话内执行 `git commit` 当场实时自动销账 —— **0 `TODO.md` 仓库污染,0 闲置 Token 损耗**。
5
5
 
6
6
  [![CI 状态](https://github.com/3ZEROS12/anchor/actions/workflows/ci.yml/badge.svg)](https://github.com/3ZEROS12/anchor/actions/workflows/ci.yml)
7
7
  [![Node v20+](https://img.shields.io/badge/Node-v20+-22c55e.svg)](package.json)
8
8
  [![TypeScript Strict](https://img.shields.io/badge/TypeScript-Strict-3b82f6.svg)](tsconfig.json)
9
- [![Tests: 29 Passed](https://img.shields.io/badge/Tests-29%20通过-22c55e.svg)](tests/store.test.ts)
9
+ [![Tests: 34 Passed](https://img.shields.io/badge/Tests-34%20通过-22c55e.svg)](tests/store.test.ts)
10
10
  [![启动耗时: < 90ms](https://img.shields.io/badge/启动耗时-%3C%2090ms-success.svg)](package.json)
11
11
  [![零仓库污染](https://img.shields.io/badge/存储-零仓库污染-success.svg)](#1-绝对零仓库污染与跨进程文件锁)
12
12
  [![开源协议: MIT](https://img.shields.io/badge/开源协议-MIT-f97316.svg)](LICENSE)
13
13
 
14
14
  [English](./README.md) | **简体中文**
15
15
 
16
+ ```bash
17
+ pi install npm:pi-anchor
18
+ ```
19
+
16
20
  <p align="center">
17
21
  <img src="assets/hero-zh.svg" alt="Anchor 终端仪表盘实录" width="820">
18
22
  </p>
19
23
 
20
24
  ```text
21
- ⌖ Anchors (4 active):
25
+ ⌖ Anchors (3 active, 1 quiet):
22
26
 
23
- [Today · 今日聚焦]
24
- 01 [Today] 今天完成anchor项目后端优化 Desktop Today Today 10:02
27
+ 01 [P0] 重构鉴权模块为 HttpOnly Cookie [src/auth.ts] anchor Today Today 10:02
28
+ 02 [P1] 补充并发文件锁单元测试 anchor Tomorrow Yesterday 21:34
29
+ 03 [P1] 打磨 CLI 交互式极简工程列表 Desktop In 2d Today 10:02
30
+ 04 [Quiet] College 重构前置查阅外部架构参考库 College/优化 Quiet (0 tok) 09-28 14:20
25
31
 
26
- [Upcoming · 近期排期]
27
- 02 [Upcoming] 明天优化并发文件锁单元测试 Desktop Tomorrow Yesterday 21:34
28
- 03 [Upcoming] 重构鉴权模块为HttpOnly Cookie Desktop Tomorrow Today 10:02
29
- 04 [Upcoming] 完善CLI交互式仪表盘与TUI组件 Desktop In 2d Today 10:02
30
-
31
- Use `anchor done <id>` to complete.
32
+ Use `anchor done <id>` to complete, or `anchor undo` to restore.
32
33
  ```
33
34
 
35
+ ### 三大核心设计:小巧 · 自主 · 持久
36
+
37
+ 1. **小巧 (Compact · 极简顺手 & 0 闲置 Token)**:
38
+ - 纯 TypeScript 实现(~20KB 产物,0 外部二进制依赖,不在仓库塞数据库,不开后台常驻进程)。
39
+ - 砍掉繁琐的四象限与打卡分类,回归一屏看清的优先级工程列表(`/anchor`、`/pin`、`/done 1`)。第 1 轮冷启动简要提醒 AI,第 2 轮起 **0 Token 损耗**。
40
+ 2. **自主 (Autonomous · 智能路径识别 & 会话内实时核销)**:
41
+ - 即使你在别的目录随口记下一句任务,也会自动提取标题/描述里的文件与目录路径并绑定目标工程,下次切换到该目录时自动唤醒。
42
+ - **不等关闭终端**:会话内一旦执行 `git commit` 或通过测试命令(`verifyCommand`),哪怕没填 `files` 也能根据提交信息当场实时自动核销,状态栏 `⌖` 即刻更新。
43
+ 3. **持久 (Persistent · 永不莫名丢任务)**:
44
+ - 独立托管于全局 `~/.anchor/state.json`,项目 Git 树 100% 纯净。
45
+ - **绝不因过期而静默删任务**:超过 7 天未触碰的任务自动转为 `[Quiet]` 静默省流态(不在无关会话塞 Prompt),但在 `/anchor` 面板中始终可见,可随时一键唤醒或在进入对应工程时自动激活。
46
+
34
47
  ---
35
48
 
36
49
  ## 核心价值:为什么需要 Anchor?
@@ -146,8 +159,10 @@ anchor undo # 撤销上一次完成归档
146
159
  ### Pi 扩展内交互命令
147
160
  | 命令 | 说明 |
148
161
  | :--- | :--- |
149
- | `/pin "任务描述"` | 快速立项当前工程的跨会话任务 |
162
+ | `/pin <任务描述> [--due tomorrow]` | 快速立项当前工程的跨会话任务(支持指定到期日) |
150
163
  | `/anchor` | 在终端内弹出全景交互式任务仪表盘 |
164
+ | `/done <编号>` 或 `/anchor done <编号>` | 按列表行号(`1`)或 ID(`anc-1`)直接完成核销 |
165
+ | `/anchor undo` | 撤销上一次归档的任务 |
151
166
  | 状态栏 `⌖ N` | 底部常驻微标签,有活跃任务时显示数量,无任务时 100% 静默隐形 |
152
167
 
153
168
  ---
@@ -193,7 +208,7 @@ Anchor 选择了一条极度克制的工程路径:把状态移出代码仓库
193
208
 
194
209
  ```bash
195
210
  npm run typecheck # TypeScript 严格类型检查 (0 错误)
196
- npm test # 全套自动化单元测试 (29/29 全绿通过)
211
+ npm test # 全套自动化单元测试 (34/34 全绿通过)
197
212
  npm run build # tsup 双格式打包 (ESM/CJS) 与 .d.ts 类型生成
198
213
  ```
199
214
 
@@ -0,0 +1,87 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 430" width="840" height="430">
2
+ <defs>
3
+ <filter id="shadow" x="-5%" y="-5%" width="110%" height="115%" filterUnits="userSpaceOnUse">
4
+ <feDropShadow dx="0" dy="12" stdDeviation="16" flood-color="#000000" flood-opacity="0.45" />
5
+ </filter>
6
+ <linearGradient id="headerGrad" x1="0%" y1="0%" x2="0%" y2="100%">
7
+ <stop offset="0%" stop-color="#2b3339" />
8
+ <stop offset="100%" stop-color="#232a2e" />
9
+ </linearGradient>
10
+ </defs>
11
+
12
+ <g filter="url(#shadow)">
13
+ <rect x="20" y="15" width="800" height="390" rx="12" fill="#1e2326" stroke="#343f44" stroke-width="1.2" />
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
+ <line x1="20" y1="52" x2="820" y2="52" stroke="#2d353b" stroke-width="1" />
16
+ <circle cx="42" cy="33.5" r="5.5" fill="#e67e80" />
17
+ <circle cx="60" cy="33.5" r="5.5" fill="#dbbc7f" />
18
+ <circle cx="78" cy="33.5" r="5.5" fill="#a7c080" />
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.3.0) · Compact · Autonomous · Persistent
21
+ </text>
22
+ </g>
23
+
24
+ <g font-family="'JetBrains Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace" font-size="13" xml:space="preserve">
25
+ <text x="45" y="84">
26
+ <tspan fill="#a7c080" font-weight="bold">~/Workspace</tspan>
27
+ <tspan fill="#7fbbb3"> ❯ </tspan>
28
+ <tspan fill="#d3c6aa" font-weight="bold">anchor</tspan>
29
+ </text>
30
+
31
+ <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
+ <tspan fill="#859289"> 01 </tspan>
38
+ <tspan fill="#e67e80" font-weight="bold">[P0] </tspan>
39
+ <tspan fill="#d3c6aa">Migrate auth to HttpOnly cookies [src/auth.ts]</tspan>
40
+ <tspan fill="#7fbbb3"> anchor </tspan>
41
+ <tspan fill="#e67e80" font-weight="bold">Today </tspan>
42
+ <tspan fill="#7a8478">Today 10:02</tspan>
43
+ </text>
44
+
45
+ <text x="45" y="182">
46
+ <tspan fill="#859289"> 02 </tspan>
47
+ <tspan fill="#dbbc7f" font-weight="bold">[P1] </tspan>
48
+ <tspan fill="#d3c6aa">Add concurrent file lock unit tests </tspan>
49
+ <tspan fill="#7fbbb3"> anchor </tspan>
50
+ <tspan fill="#dbbc7f">Tomorrow </tspan>
51
+ <tspan fill="#7a8478">Yesterday 21:34</tspan>
52
+ </text>
53
+
54
+ <text x="45" y="212">
55
+ <tspan fill="#859289"> 03 </tspan>
56
+ <tspan fill="#dbbc7f" font-weight="bold">[P1] </tspan>
57
+ <tspan fill="#d3c6aa">Polish CLI interactive dashboard &amp; TUI </tspan>
58
+ <tspan fill="#7fbbb3"> Desktop </tspan>
59
+ <tspan fill="#a7c080">In 2d </tspan>
60
+ <tspan fill="#7a8478">Today 10:02</tspan>
61
+ </text>
62
+
63
+ <text x="45" y="242">
64
+ <tspan fill="#859289"> 04 </tspan>
65
+ <tspan fill="#7a8478" font-weight="bold">[Quiet] </tspan>
66
+ <tspan fill="#859289">Review external architecture reference notes </tspan>
67
+ <tspan fill="#7a8478"> College/Opt </tspan>
68
+ <tspan fill="#7a8478">Quiet (0 tok) </tspan>
69
+ <tspan fill="#56635f">09-28 14:20</tspan>
70
+ </text>
71
+
72
+ <rect x="45" y="274" width="750" height="58" rx="6" fill="#232a2e" stroke="#3a464c" stroke-width="1" />
73
+ <text x="62" y="298" fill="#a7c080" font-weight="bold">⚡ Real-Time Autonomous Settlement (on `git commit` or passing `verifyCommand`):</text>
74
+ <text x="62" y="319" fill="#d3c6aa"> git commit -m "feat(auth): migrate auth to HttpOnly cookies" ➔ ⌖ Auto-settled #anc-1</text>
75
+
76
+ <text x="45" y="366" fill="#7a8478">
77
+ <tspan> Commands: </tspan>
78
+ <tspan fill="#7fbbb3" font-weight="bold">`/pin &lt;task&gt;`</tspan>
79
+ <tspan> · </tspan>
80
+ <tspan fill="#7fbbb3" font-weight="bold">`/anchor`</tspan>
81
+ <tspan> · </tspan>
82
+ <tspan fill="#7fbbb3" font-weight="bold">`/done 1`</tspan>
83
+ <tspan> · </tspan>
84
+ <tspan fill="#7fbbb3" font-weight="bold">`/anchor undo`</tspan>
85
+ </text>
86
+ </g>
87
+ </svg>
@@ -0,0 +1,87 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 430" width="840" height="430">
2
+ <defs>
3
+ <filter id="shadow" x="-5%" y="-5%" width="110%" height="115%" filterUnits="userSpaceOnUse">
4
+ <feDropShadow dx="0" dy="12" stdDeviation="16" flood-color="#000000" flood-opacity="0.45" />
5
+ </filter>
6
+ <linearGradient id="headerGrad" x1="0%" y1="0%" x2="0%" y2="100%">
7
+ <stop offset="0%" stop-color="#2b3339" />
8
+ <stop offset="100%" stop-color="#232a2e" />
9
+ </linearGradient>
10
+ </defs>
11
+
12
+ <g filter="url(#shadow)">
13
+ <rect x="20" y="15" width="800" height="390" rx="12" fill="#1e2326" stroke="#343f44" stroke-width="1.2" />
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
+ <line x1="20" y1="52" x2="820" y2="52" stroke="#2d353b" stroke-width="1" />
16
+ <circle cx="42" cy="33.5" r="5.5" fill="#e67e80" />
17
+ <circle cx="60" cy="33.5" r="5.5" fill="#dbbc7f" />
18
+ <circle cx="78" cy="33.5" r="5.5" fill="#a7c080" />
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.3.0) · 小巧 · 自主 · 持久
21
+ </text>
22
+ </g>
23
+
24
+ <g font-family="'JetBrains Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace" font-size="13" xml:space="preserve">
25
+ <text x="45" y="84">
26
+ <tspan fill="#a7c080" font-weight="bold">~/Workspace</tspan>
27
+ <tspan fill="#7fbbb3"> ❯ </tspan>
28
+ <tspan fill="#d3c6aa" font-weight="bold">anchor</tspan>
29
+ </text>
30
+
31
+ <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
+ <tspan fill="#859289"> 01 </tspan>
38
+ <tspan fill="#e67e80" font-weight="bold">[P0] </tspan>
39
+ <tspan fill="#d3c6aa">重构鉴权模块为 HttpOnly Cookie [src/auth.ts]</tspan>
40
+ <tspan fill="#7fbbb3"> anchor </tspan>
41
+ <tspan fill="#e67e80" font-weight="bold">Today </tspan>
42
+ <tspan fill="#7a8478">Today 10:02</tspan>
43
+ </text>
44
+
45
+ <text x="45" y="182">
46
+ <tspan fill="#859289"> 02 </tspan>
47
+ <tspan fill="#dbbc7f" font-weight="bold">[P1] </tspan>
48
+ <tspan fill="#d3c6aa">补充并发文件锁单元测试 </tspan>
49
+ <tspan fill="#7fbbb3"> anchor </tspan>
50
+ <tspan fill="#dbbc7f">Tomorrow </tspan>
51
+ <tspan fill="#7a8478">Yesterday 21:34</tspan>
52
+ </text>
53
+
54
+ <text x="45" y="212">
55
+ <tspan fill="#859289"> 03 </tspan>
56
+ <tspan fill="#dbbc7f" font-weight="bold">[P1] </tspan>
57
+ <tspan fill="#d3c6aa">打磨 CLI 交互式极简工程列表 </tspan>
58
+ <tspan fill="#7fbbb3"> Desktop </tspan>
59
+ <tspan fill="#a7c080">In 2d </tspan>
60
+ <tspan fill="#7a8478">Today 10:02</tspan>
61
+ </text>
62
+
63
+ <text x="45" y="242">
64
+ <tspan fill="#859289"> 04 </tspan>
65
+ <tspan fill="#7a8478" font-weight="bold">[Quiet] </tspan>
66
+ <tspan fill="#859289">College 重构前置查阅外部架构参考库 </tspan>
67
+ <tspan fill="#7a8478"> College/优化 </tspan>
68
+ <tspan fill="#7a8478">Quiet (0 tok) </tspan>
69
+ <tspan fill="#56635f">09-28 14:20</tspan>
70
+ </text>
71
+
72
+ <rect x="45" y="274" width="750" height="58" rx="6" fill="#232a2e" stroke="#3a464c" stroke-width="1" />
73
+ <text x="62" y="298" fill="#a7c080" font-weight="bold">⚡ 会话内实时自主核销(执行 git commit 或测试通过当场自动结案):</text>
74
+ <text x="62" y="319" fill="#d3c6aa"> git commit -m "feat(auth): 重构鉴权模块为 HttpOnly Cookie" ➔ ⌖ Auto-settled #anc-1</text>
75
+
76
+ <text x="45" y="366" fill="#7a8478">
77
+ <tspan> 常用命令: </tspan>
78
+ <tspan fill="#7fbbb3" font-weight="bold">`/pin &lt;任务&gt;`</tspan>
79
+ <tspan> · </tspan>
80
+ <tspan fill="#7fbbb3" font-weight="bold">`/anchor`</tspan>
81
+ <tspan> · </tspan>
82
+ <tspan fill="#7fbbb3" font-weight="bold">`/done 1`</tspan>
83
+ <tspan> · </tspan>
84
+ <tspan fill="#7fbbb3" font-weight="bold">`/anchor undo`</tspan>
85
+ </text>
86
+ </g>
87
+ </svg>
@@ -0,0 +1,108 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 430" width="840" height="430">
2
+ <defs>
3
+ <filter id="shadow" x="-5%" y="-5%" width="110%" height="115%" filterUnits="userSpaceOnUse">
4
+ <feDropShadow dx="0" dy="12" stdDeviation="16" flood-color="#000000" flood-opacity="0.45" />
5
+ </filter>
6
+ <linearGradient id="headerGrad" x1="0%" y1="0%" x2="0%" y2="100%">
7
+ <stop offset="0%" stop-color="#2b3339" />
8
+ <stop offset="100%" stop-color="#232a2e" />
9
+ </linearGradient>
10
+ </defs>
11
+
12
+ <!-- Window Container with Shadow -->
13
+ <g filter="url(#shadow)">
14
+ <rect x="20" y="15" width="800" height="390" rx="12" fill="#1e2326" stroke="#343f44" stroke-width="1.2" />
15
+
16
+ <!-- Titlebar -->
17
+ <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" />
18
+ <line x1="20" y1="52" x2="820" y2="52" stroke="#2d353b" stroke-width="1" />
19
+
20
+ <!-- Window Controls (macOS Dots) -->
21
+ <circle cx="42" cy="33.5" r="5.5" fill="#e67e80" />
22
+ <circle cx="60" cy="33.5" r="5.5" fill="#dbbc7f" />
23
+ <circle cx="78" cy="33.5" r="5.5" fill="#a7c080" />
24
+
25
+ <!-- Window Title -->
26
+ <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" letter-spacing="0.3">
27
+ Jason@laptop ~ ⌖ anchor (v0.2.1)
28
+ </text>
29
+ </g>
30
+
31
+ <!-- Terminal Text Content -->
32
+ <g font-family="'JetBrains Mono', 'Fira Code', 'Cascadia Code', Menlo, Consolas, monospace" font-size="13" xml:space="preserve">
33
+ <!-- Prompt Command Line -->
34
+ <text x="45" y="85">
35
+ <tspan fill="#a7c080" font-weight="bold">~/Workspace</tspan>
36
+ <tspan fill="#7fbbb3"> ❯ </tspan>
37
+ <tspan fill="#d3c6aa" font-weight="bold">anchor</tspan>
38
+ </text>
39
+
40
+ <!-- Header Line -->
41
+ <text x="45" y="118">
42
+ <tspan fill="#7fbbb3" font-weight="bold">⌖ Anchors </tspan>
43
+ <tspan fill="#859289">(4 active):</tspan>
44
+ </text>
45
+
46
+ <!-- Today Section Header -->
47
+ <text x="45" y="152" fill="#e67e80" font-weight="bold"> [Today · 今日聚焦]</text>
48
+
49
+ <!-- Today Item -->
50
+ <text x="45" y="178">
51
+ <tspan fill="#859289"> 01 </tspan>
52
+ <tspan fill="#e67e80" font-weight="bold">[Today] </tspan>
53
+ <tspan fill="#d3c6aa">今天完成anchor项目后端优化 </tspan>
54
+ <tspan fill="#859289"> Desktop </tspan>
55
+ <tspan fill="#e67e80" font-weight="bold">Today </tspan>
56
+ <tspan fill="#7a8478">Today 10:02</tspan>
57
+ </text>
58
+
59
+ <!-- Upcoming Section Header -->
60
+ <text x="45" y="218" fill="#dbbc7f" font-weight="bold"> [Upcoming · 近期排期]</text>
61
+
62
+ <!-- Upcoming Items -->
63
+ <text x="45" y="244">
64
+ <tspan fill="#859289"> 02 </tspan>
65
+ <tspan fill="#dbbc7f">[Upcoming] </tspan>
66
+ <tspan fill="#d3c6aa">明天优化并发文件锁单元测试 </tspan>
67
+ <tspan fill="#859289"> Desktop </tspan>
68
+ <tspan fill="#dbbc7f">Tomorrow </tspan>
69
+ <tspan fill="#7a8478">Yesterday 21:34</tspan>
70
+ </text>
71
+
72
+ <text x="45" y="270">
73
+ <tspan fill="#859289"> 03 </tspan>
74
+ <tspan fill="#dbbc7f">[Upcoming] </tspan>
75
+ <tspan fill="#d3c6aa">重构鉴权模块为HttpOnly Cookie </tspan>
76
+ <tspan fill="#859289"> Desktop </tspan>
77
+ <tspan fill="#dbbc7f">Tomorrow </tspan>
78
+ <tspan fill="#7a8478">Today 10:02</tspan>
79
+ </text>
80
+
81
+ <text x="45" y="296">
82
+ <tspan fill="#859289"> 04 </tspan>
83
+ <tspan fill="#dbbc7f">[Upcoming] </tspan>
84
+ <tspan fill="#d3c6aa">完善CLI交互式仪表盘与TUI组件 </tspan>
85
+ <tspan fill="#859289"> Desktop </tspan>
86
+ <tspan fill="#dbbc7f">In 2d </tspan>
87
+ <tspan fill="#7a8478">Today 10:02</tspan>
88
+ </text>
89
+
90
+ <!-- Footer Action -->
91
+ <text x="45" y="340" fill="#7a8478">
92
+ <tspan> Use </tspan>
93
+ <tspan fill="#7fbbb3" font-weight="bold">`anchor done &lt;id&gt;`</tspan>
94
+ <tspan> to complete.</tspan>
95
+ </text>
96
+
97
+ <!-- Active Input Cursor -->
98
+ <text x="45" y="378">
99
+ <tspan fill="#a7c080" font-weight="bold">~/Workspace</tspan>
100
+ <tspan fill="#7fbbb3"> ❯ </tspan>
101
+ <tspan fill="#7fbbb3">⌖</tspan>
102
+ <tspan fill="#d3c6aa"> </tspan>
103
+ <rect x="175" y="364" width="8" height="16" fill="#a7c080" opacity="0.8">
104
+ <animate attributeName="opacity" values="0.8;0.1;0.8" dur="1.1s" repeatCount="indefinite" />
105
+ </rect>
106
+ </text>
107
+ </g>
108
+ </svg>
package/bin/anchor.js CHANGED
@@ -7,11 +7,10 @@
7
7
 
8
8
  import {
9
9
  AnchorStore,
10
- classifyAnchor,
11
10
  formatOrigin,
12
11
  formatTargetDate,
13
12
  formatCreationTime,
14
- groupAnchorsByQuadrant,
13
+ sortAnchorsForDisplay,
15
14
  padToWidth
16
15
  } from '../dist/index.js';
17
16
 
@@ -20,53 +19,45 @@ const args = process.argv.slice(2);
20
19
 
21
20
  // 1. View pending tasks: `anchor` or `anchor list`
22
21
  if (args.length === 0 || args[0] === 'list' || args[0] === 'ls') {
23
- const active = store.list({ status: 'active', cwd: process.cwd() });
22
+ const allUnfinished = store
23
+ .list({ cwd: process.cwd(), all: true })
24
+ .filter(a => a.status === 'active' || a.status === 'sleeping');
24
25
 
25
- if (active.length === 0) {
26
+ if (allUnfinished.length === 0) {
26
27
  console.log('\n⌖ No active anchors. Use `anchor <task>` to record.\n');
27
28
  process.exit(0);
28
29
  }
29
30
 
30
- console.log(`\n⌖ Anchors (${active.length} active):\n`);
31
-
32
- const groups = groupAnchorsByQuadrant(active);
33
- const sections = [
34
- { title: 'Today · 今日聚焦', list: groups.today },
35
- { title: 'Upcoming · 近期排期', list: groups.upcoming },
36
- { title: 'Habits · 每日循环', list: groups.habits },
37
- { title: 'Backlog · 长期愿景', list: groups.backlog },
38
- ];
39
-
40
- let seqNum = 1;
41
-
42
- for (const sec of sections) {
43
- if (sec.list.length === 0) continue;
44
- console.log(` [${sec.title}]`);
45
- sec.list.forEach((a) => {
46
- const num = seqNum.toString().padStart(2, '0');
47
- seqNum++;
48
-
49
- const category = padToWidth(`[${classifyAnchor(a)}]`, 12);
50
- const origin = formatOrigin(a);
51
- const target = formatTargetDate(a);
52
- const created = formatCreationTime(a.createdAt);
53
-
54
- const titleWithFiles = (a.files && a.files.length > 0)
55
- ? `${a.title} [${a.files.slice(0, 1).join(', ')}]`
56
- : a.title;
57
-
58
- const colNum = ` ${num} `;
59
- const colTitle = padToWidth(titleWithFiles, 28);
60
- const colOrigin = padToWidth(origin, 10);
61
- const colTarget = padToWidth(target, 12);
62
- const colCreated = created;
63
-
64
- console.log(`${colNum}${category}${colTitle} ${colOrigin} ${colTarget} ${colCreated}`);
65
- });
66
- console.log('');
67
- }
31
+ const sorted = sortAnchorsForDisplay(allUnfinished, process.cwd());
32
+ const activeCount = sorted.filter(a => a.status === 'active').length;
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`);
37
+
38
+ sorted.forEach((a, idx) => {
39
+ const num = String(idx + 1).padStart(2, '0');
40
+ const badge = a.status === 'sleeping'
41
+ ? padToWidth('[Quiet]', 10)
42
+ : padToWidth(`[${a.priority.toUpperCase()}]`, 10);
43
+ const origin = formatOrigin(a);
44
+ const target = a.status === 'sleeping' ? 'Quiet (0 tok)' : formatTargetDate(a);
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;
50
+
51
+ const colNum = ` ${num} `;
52
+ const colTitle = padToWidth(titleWithFiles, 36);
53
+ const colOrigin = padToWidth(origin, 14);
54
+ const colTarget = padToWidth(target, 14);
55
+ const colCreated = created;
56
+
57
+ console.log(`${colNum}${badge}${colTitle} ${colOrigin} ${colTarget} ${colCreated}`);
58
+ });
68
59
 
69
- console.log(' Use `anchor done <id>` to complete.\n');
60
+ console.log('\n Use `anchor done <id>` to complete, or `anchor undo` to restore.\n');
70
61
  process.exit(0);
71
62
  }
72
63
 
@@ -110,14 +101,10 @@ if (args[0] === 'done' || args[0] === 'rm' || args[0] === 'close') {
110
101
  }
111
102
  try {
112
103
  // 1. Check if idInput is a 1-based sequential display number (e.g. '1', '01')
113
- const active = store.list({ status: 'active', cwd: process.cwd() });
114
- const groups = groupAnchorsByQuadrant(active);
115
- const sortedActive = [
116
- ...groups.today,
117
- ...groups.upcoming,
118
- ...groups.habits,
119
- ...groups.backlog
120
- ];
104
+ const allUnfinished = store
105
+ .list({ cwd: process.cwd(), all: true })
106
+ .filter(a => a.status === 'active' || a.status === 'sleeping');
107
+ const sortedActive = sortAnchorsForDisplay(allUnfinished, process.cwd());
121
108
 
122
109
  let targetId = idInput;
123
110
  const numMatch = idInput.match(/^\d+$/);