@fooksky/lodestar 0.2.1 → 0.2.2
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 +46 -81
- package/docs/branch-management.md +1 -1
- package/docs/design.md +3 -3
- package/package.json +1 -1
- package/skills/dev-workflow/SKILL.md +3 -3
- package/skills/dev-workflow/references/workspace.md +1 -1
- package/src/preset.js +1 -1
- package/src/tool.js +4 -4
package/README.md
CHANGED
|
@@ -1,109 +1,74 @@
|
|
|
1
1
|
# Lodestar
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Lodestar 是 DeepSeek Harness(DSH)的开发工作流插件,让 Agent 从需求确认、方案评审、实施授权,一直推进到验证和交付,并通过项目内的材料与结构化状态恢复工作。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## 提供什么
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- **`dev-workflow` skill**:指导需求澄清、设计取舍、授权判断、任务组织和验收。
|
|
8
|
+
- **`lodestar_change` 工具**:维护 change 的文档版本、决定、验收项、执行引用、验证记录及流程状态,校验阶段前置条件。
|
|
9
|
+
- **可选“开发工作流”preset**:为新会话提供流程入口,默认关闭,复用部署已有的原生工具。
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
写代码、运行测试和分工协作使用 DSH 原生工具与 Agent Teams。Lodestar 不承担跨需求调度,不创建或切换分支,也不自动提交、推送或发布。工具校验记录的结构和关联;用户授权的含义及证据是否足以支持交付仍由 Lead 判断。
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
## 开始使用
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
包名为 `@fooksky/lodestar`,通过 DSH 的插件管理安装并启用核心插件。运行需要 Node.js 24+、Git,以及提供文件、工作目录和 subprocess 等服务的兼容 DSH 宿主;版本要求见 [package.json](package.json)。
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
在会话中加载 `dev-workflow` skill,再用自然语言说明目标,例如:
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
> 帮我设计并实现这个功能:……
|
|
20
|
+
>
|
|
21
|
+
> 继续 change `20261108-example`,先检查当前状态和未完成事项。
|
|
22
|
+
>
|
|
23
|
+
> 这次只需要设计方案,先不要实施。
|
|
18
24
|
|
|
19
|
-
|
|
25
|
+
核心流程可在兼容会话中直接使用。也可启用可选 preset,在新会话开始前选择“开发工作流”;已有会话通过加载 skill 进入流程。选择 preset 本身不构成实施授权。
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
{"action":"workspace","projectRoot":"."}
|
|
23
|
-
```
|
|
27
|
+
## 材料与工作区
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
默认一个独立需求对应一个 change、一条分支、一个 worktree 和一个 Lead。用户或外部助手先准备工作区;代码、知识、change 材料和需保留的证据均在本 worktree 内维护。
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
{"action":"create","projectRoot":".","changeId":"20261107-example","title":"示例需求"}
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
create 自动生成 schemaVersion 2,绑定当前命名分支或普通目录。Git 绑定保存分支、绑定时的 `baseCommit`(unborn 可为 null)及项目相对 checkout 路径;不保存机器绝对路径或可变 HEAD。每个 action 的顶层 workspace 直接返回实时观察,无 current/status 嵌套;workspace action 不返回 bindingStatus。get 顶层 bindingStatus 仅为 matched/mismatch/detached,binding 为已存绑定;list 有效行的 workspace 为已存绑定并附 bindingStatus。历史 change 合入后不会自动改绑。分支改名、明确接管或普通目录初始化为仓库后,用当前 revision 单独重绑:
|
|
31
|
+
材料保存在项目的 `.dev-docs/changes/<change-id>/`:
|
|
32
32
|
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
```text
|
|
34
|
+
intent.md 真实需求与范围
|
|
35
|
+
spec.md 方案与验收要求
|
|
36
|
+
plan.md 实施计划与交付材料
|
|
37
|
+
state.json 工具维护的状态、版本和关联
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
Lead 按阶段编写正文,`lodestar_change` 原子更新状态,并复用项目已有的 `.dev-docs/index.md` 和 `knowledge/`。状态仅接受 `schemaVersion: 2`,旧格式或损坏记录会明确报错,不自动迁移或修复。
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
## 状态工具
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
{
|
|
46
|
-
"action":"update","projectRoot":".","changeId":"20261107-example","expectedRevision":1,
|
|
47
|
-
"operations":[{"type":"register-document","kind":"intent","classification":"semantic","basedOn":{},"reason":"初次登记"}]
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
其他操作和确切字段参见 [工具输入 schema](src/schema.js) 与 [skill](skills/dev-workflow/SKILL.md)。每次更新最多 32 个操作,全部成功才发布。遇到冲突先 get 再合并;未知回执先核对记录,不盲重试。材料链接不作为写入目标;材料目录与文件拒绝符号链接,项目根可以由宿主解析为规范路径。
|
|
44
|
+
每次调用显式提供 `projectRoot`。Git 项目根必须与调用 Agent 的工作目录属于同一 checkout;普通目录项目根必须位于 Agent 工作目录内。
|
|
52
45
|
|
|
53
|
-
|
|
46
|
+
| Action | 用途 |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `workspace` | 观察当前工作区、分支及 HEAD |
|
|
49
|
+
| `list` | 分页列出 change 及其阶段、状态和绑定情况 |
|
|
50
|
+
| `get` | 读取 change 或指定部分,检查文档一致性和阻塞项 |
|
|
51
|
+
| `create` | 创建 change 并绑定当前工作区 |
|
|
52
|
+
| `update` | 使用 `expectedRevision` 原子提交有类型的领域操作 |
|
|
54
53
|
|
|
55
|
-
|
|
54
|
+
例如,调用 `lodestar_change` 观察已准备的工作区,再创建 change:
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
需要 Node.js 24+、pnpm(不固定版本)、Git 及宿主 subprocess 服务,核对宿主版本为 DSH `0.2.2-rc.1`;Git 查询遵守调用会话的 sandbox policy,不使用裸 Node child_process 或 shell 绕过宿主。依赖无安装脚本:
|
|
60
|
-
|
|
61
|
-
```sh
|
|
62
|
-
pnpm install --frozen-lockfile --ignore-scripts
|
|
63
|
-
# prepack 自动执行语法检查和测试,并预览实际发布文件
|
|
64
|
-
npm pack --dry-run
|
|
56
|
+
```json
|
|
57
|
+
{"action":"workspace","projectRoot":"."}
|
|
65
58
|
```
|
|
66
59
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
```sh
|
|
70
|
-
DSH_HOST_ROOT=/absolute/path/to/node_modules/@deepseek-ai/dsh pnpm test
|
|
60
|
+
```json
|
|
61
|
+
{"action":"create","projectRoot":".","changeId":"20261108-example","title":"示例需求"}
|
|
71
62
|
```
|
|
72
63
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
## 文档
|
|
76
|
-
|
|
77
|
-
- [设计](docs/design.md) 与 [提案](docs/proposal.md)
|
|
78
|
-
- [Agent 角色调查](docs/research/agent-presets.md) 与 [开发模式调查](docs/research/development-mode.md)
|
|
79
|
-
- [工作流调研](docs/research/workflow-survey.md) 与 [会话成本案例](docs/research/labwarden-session-cost.md)
|
|
80
|
-
|
|
81
|
-
## npm 发布与 GitHub Actions
|
|
64
|
+
文档登记、分支重绑及恢复规则见 [skill](skills/dev-workflow/SKILL.md) 和 [工作区参考](skills/dev-workflow/references/workspace.md);确切参数以 [工具 schema](src/schema.js) 为准。
|
|
82
65
|
|
|
83
|
-
|
|
66
|
+
## 项目文档
|
|
84
67
|
|
|
85
|
-
[
|
|
86
|
-
|
|
87
|
-
[
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
1. GitHub origin 和包元数据 `repository.url` 已指向 `urzz/lodestar`,保持两者与 Trusted Publisher 中配置的仓库一致;GitHub 仓库保持私有。
|
|
92
|
-
2. 使用 npm 账号 `fooksky` 发布公开包 `@fooksky/lodestar`(公开 scoped 包免费)。如果 npm 尚无该包,先在受信任本机通过 `npm login --registry=https://registry.npmjs.org/`、`npm publish --access public --registry=https://registry.npmjs.org/` 完成首次发布,再配置自动发布;不要重复发布同一版本。npm 账号与 GitHub owner `urzz` 可以不同。
|
|
93
|
-
3. 在 npm 包设置中添加 GitHub Actions Trusted Publisher:owner 填 `urzz`,仓库名填 `lodestar`,workflow filename 填 `publish.yml`,允许直接使用 `npm publish`。本工作流没有配置 GitHub Environment,该项留空。无需在 GitHub 配置 `NPM_TOKEN`。
|
|
94
|
-
|
|
95
|
-
后续发布流程:
|
|
96
|
-
|
|
97
|
-
```sh
|
|
98
|
-
# 更新版本,再同步 pnpm 锁文件;暂不自动创建提交和标签
|
|
99
|
-
npm version patch --no-git-tag-version
|
|
100
|
-
pnpm install --lockfile-only --ignore-scripts
|
|
101
|
-
# 审阅后提交版本文件,并创建匹配标签;示例版本需替换成实际版本
|
|
102
|
-
git add package.json pnpm-lock.yaml
|
|
103
|
-
git commit -m "chore: release v0.2.1"
|
|
104
|
-
git tag v0.2.1
|
|
105
|
-
git push origin main
|
|
106
|
-
git push origin v0.2.1
|
|
107
|
-
```
|
|
68
|
+
- [仓库开发约定](AGENTS.md):开发环境、宿主接口边界、验证及发布流程。
|
|
69
|
+
- [分支与 worktree 隔离设计](docs/branch-management.md):当前工作区与持久绑定契约。
|
|
70
|
+
- [首版设计](docs/design.md) 与 [提案](docs/proposal.md):设计背景和历史范围。
|
|
71
|
+
- [场景清单](tests/scenarios.md):真实模型授权理解、Team 协作和中断恢复的行为验收。
|
|
72
|
+
- [Agent 角色调查](docs/research/agent-presets.md)、[开发模式调查](docs/research/development-mode.md)、[工作流调研](docs/research/workflow-survey.md) 与 [会话成本案例](docs/research/labwarden-session-cost.md)。
|
|
108
73
|
|
|
109
|
-
|
|
74
|
+
采用 [MIT 许可证](LICENSE)。[GitHub 源码仓库](https://github.com/urzz/lodestar) 为私有仓库,npm 包公开分发;包内源码、skill 和文档均可公开下载。
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
## 2. 当前工作区观察
|
|
12
12
|
|
|
13
|
-
`
|
|
13
|
+
`lodestar_change` 增加只读 `action: workspace`。每个 action 在调用 Agent 的实际 cwd 和显式 projectRoot 上识别当前 Git checkout,返回有界 workspace 信息。Git 查询经宿主 subprocess 和调用会话的 sandbox policy 执行;不使用 Node child_process 或 shell,也不绕过文件 backend。Git 是运行依赖,缺少 Git/宿主服务、取消、权限拒绝、仓库损坏均保持错误,不伪装成非 Git。
|
|
14
14
|
|
|
15
15
|
通过 Git 的明确“not a git repository”诊断识别普通目录;固定查询语言并清除改变仓库发现的 Git 环境变量。普通目录继续支持工作流。bare 仓库拒绝使用。Git 支持标准 checkout、linked worktree、子模块与项目子目录;projectRoot 必须存在。
|
|
16
16
|
|
package/docs/design.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
## 1. 目标和范围
|
|
10
10
|
|
|
11
|
-
交付独立 DSH bundle,包含一个 `dev-workflow` skill 和一个 `
|
|
11
|
+
交付独立 DSH bundle,包含一个 `dev-workflow` skill 和一个 `lodestar_change` 状态工具。用户用自然语言开始或继续工作,不需要学习命令族。
|
|
12
12
|
|
|
13
13
|
主流程:意图澄清及用户确认 → 具体方案及用户审核 → AI 生成 plan → 原生执行与必要验证 → 交付及必要知识更新。新项目按真实可运行的功能切片推进,同样遵循此流程。
|
|
14
14
|
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
用户 ↔ Lead / dev-workflow skill
|
|
46
46
|
├─ 原生 Teams、文件、测试、浏览器等工具
|
|
47
47
|
├─ Markdown 需求、方案、计划及知识
|
|
48
|
-
└─
|
|
48
|
+
└─ lodestar_change 工具
|
|
49
49
|
↓
|
|
50
50
|
状态更新模块 ← 后续原生事件适配器
|
|
51
51
|
↓
|
|
@@ -168,7 +168,7 @@ passed 必须有依据引用;not-applicable 必须说明原因,并且不能
|
|
|
168
168
|
|
|
169
169
|
## 8. 工具 API
|
|
170
170
|
|
|
171
|
-
仅暴露 `
|
|
171
|
+
仅暴露 `lodestar_change`,以 action 区分四类操作。每次提供 projectRoot;changeId 是单一路径段,不能包含目录跳转。所有路径经宿主解析,并限定在当前授权项目的 `.dev-docs/changes/<id>/` 内;证据外部路径只作引用,不作为写入目标。不会接受任意 state 文件路径。
|
|
172
172
|
|
|
173
173
|
| action | 输入 | 输出 |
|
|
174
174
|
|---|---|---|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fooksky/lodestar",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": { "type": "git", "url": "git+https://github.com/urzz/lodestar.git" },
|
|
6
6
|
"publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/", "provenance": false },
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
## 开始与材料
|
|
8
8
|
|
|
9
|
-
先确定用户范围,由用户或外部助手准备隔离 worktree,再读取 references/workspace.md 并调用 workspace 核对实际 projectRoot、分支与绑定。默认一个独立需求对应一个 change、一条分支、一个 worktree 和一个 Lead;插件不负责跨需求调度或创建/切换分支。每次
|
|
9
|
+
先确定用户范围,由用户或外部助手准备隔离 worktree,再读取 references/workspace.md 并调用 workspace 核对实际 projectRoot、分支与绑定。默认一个独立需求对应一个 change、一条分支、一个 worktree 和一个 Lead;插件不负责跨需求调度或创建/切换分支。每次 lodestar_change 调用显式传本 worktree 的 projectRoot,不维护全局当前 change。恢复时读 references/recover.md;新工作按需读 references/intent.md。没有状态工具时明确报告能力缺失,不手工伪造 state.json。
|
|
10
10
|
|
|
11
11
|
新 change 先调用 create 创建 schemaVersion: 2 状态,workspace 必填并自动绑定当前命名分支或普通目录,再按阶段写正文并登记;create 拒绝已存在目录,不自动接管或覆盖。材料位于本 worktree 的 .dev-docs/changes/<change-id>/,ID 用 YYYYMMDD-short-slug,冲突才加短后缀。只复用本 worktree 的 .dev-docs/index.md、knowledge/ 和已有项目文档,不读取其他 checkout 的实时材料或共享材料根。intent.md 在澄清时创建,spec.md 在设计时创建,plan.md 在实施授权后创建;不预建空模板树。正文可短,Markdown 是语义权威,state 是状态与关联权威,DSH 是执行事实权威。
|
|
12
12
|
|
|
13
|
-
通过宿主文件工具先写正文,再用
|
|
13
|
+
通过宿主文件工具先写正文,再用 lodestar_change update/register-document 登记;固定正文 SHA-256 仅用于检测变化,不证明语义一致。不得用裸 fs 绕过宿主权限、手改 state、自动覆盖损坏记录或把未经核实的材料当成用户确认。
|
|
14
14
|
|
|
15
15
|
## 授权与阶段
|
|
16
16
|
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
## 工具使用
|
|
24
24
|
|
|
25
|
-
工具只有
|
|
25
|
+
工具只有 lodestar_change,action 为 workspace/list/get/create/update。workspace 只读观察当前工作区;get/list 返回实时工作区与绑定状态,list 默认分页 20,get 可按 section 读取且不附正文。create 不覆盖;update 携 expectedRevision 和最多 32 个有类型 operations。领域操作是 bind-workspace、register-document、record-decision、set-acceptance、bind-step、set-step-progress、record-verification、invalidate-verification、set-blocker、set-workflow、close。具体字段以工具 schema 为准,不用 JSON Patch。
|
|
26
26
|
|
|
27
27
|
bindingStatus 仅为 matched、mismatch 或 detached。mismatch 先核对工作区和接管依据;分支改名、明确接管或普通目录初始化为仓库后,单独 bind-workspace 并提供 reason,不能夹带业务变更,workspaceHistory 每项的 previous 必填。未知或旧 schema、缺失 workspace 均拒绝,不能用重绑修复。list 不特殊识别未受管目录,缺失或非法 state 显示错误。detached 只读;unborn 命名分支允许 baseCommit 为 null。Git projectRoot 必须与 Agent cwd 属于同一 checkout,普通目录根须位于 cwd 内。写正文前也遵守这些边界,状态绑定不能限制其他文件工具;运行期间不外部切分支或清理工作区。详细规则见 references/workspace.md。
|
|
28
28
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 工作区与分支绑定
|
|
2
2
|
|
|
3
|
-
开始新需求或恢复前调用 `
|
|
3
|
+
开始新需求或恢复前调用 `lodestar_change` 的 `workspace` action,显式传当前 worktree 内的 `projectRoot`。默认一个独立需求对应一个 change、一条分支、一个 worktree 和一个 Lead。外部助手或用户负责领取 Issue、跨需求分配、创建/选择 worktree 和启动会话;插件只维护当前分支内的流程与状态,不创建/切换/删除分支、不扫描其他工作区、不调度需求、不自动提交或调用 PR API。
|
|
4
4
|
|
|
5
5
|
代码、`.dev-docs/knowledge/`、change 正文、state 和需保留的证据全部位于本 worktree。新工作区继承基准提交的知识快照,之后只读写本地材料;不使用共享材料根、符号链接或主 checkout 的实时知识。材料以当前 worktree 为唯一权威,不能复制后两处继续写;插件不自动搬移或提交。
|
|
6
6
|
|
package/src/preset.js
CHANGED
|
@@ -3,7 +3,7 @@ export const inject = ['tools', 'agentPresets', 'systemPrompt'];
|
|
|
3
3
|
|
|
4
4
|
// Reuse the deployment's native services and visible tools, without cloning a profile.
|
|
5
5
|
export const requiredTools = [
|
|
6
|
-
'
|
|
6
|
+
'lodestar_change', 'read', 'write', 'edit', 'glob', 'grep', 'bash',
|
|
7
7
|
'job_output', 'job_list', 'job_kill', 'skill', 'ask_user_question',
|
|
8
8
|
'session_search', 'session_event_search', 'session_event_read',
|
|
9
9
|
'team_task_list', 'team_task_get', 'team_task_update', 'team_task_create',
|
package/src/tool.js
CHANGED
|
@@ -21,8 +21,8 @@ export function hostSchema(schema) {
|
|
|
21
21
|
|
|
22
22
|
export function createTool(ctx) {
|
|
23
23
|
return {
|
|
24
|
-
name: '
|
|
25
|
-
description: 'Inspect the current workspace and
|
|
24
|
+
name: 'lodestar_change',
|
|
25
|
+
description: 'Inspect the current workspace and manage branch-local development changes, including document versions, decisions, acceptance criteria, execution references, verification records, and lifecycle constraints. State updates in .dev-docs are atomic. projectRoot must belong to the calling Agent checkout. Load dev-workflow for workflow semantics. create binds the current branch; get/list expose bindingStatus; an intentional branch rename or reassignment uses a separate update with bind-workspace and reason. User decisions require real sources. This tool does not authorize implementation or schedule tasks. On revision conflicts, get and merge before retrying.',
|
|
26
26
|
parameters: { type: 'object', ...hostSchema(inputSchema) },
|
|
27
27
|
output: {
|
|
28
28
|
schema: hostSchema(outputSchema),
|
|
@@ -32,11 +32,11 @@ export function createTool(ctx) {
|
|
|
32
32
|
const parsed = inputSchema.safeParse(raw);
|
|
33
33
|
if (!parsed.success) throw new DomainError('INVALID_STATE', parsed.error.message);
|
|
34
34
|
const args = parsed.data;
|
|
35
|
-
if (!exec.agent) throw new Error('
|
|
35
|
+
if (!exec.agent) throw new Error('lodestar_change requires a calling Agent and session.');
|
|
36
36
|
exec.signal?.throwIfAborted();
|
|
37
37
|
const cwd = await ctx.workingDirectory.ensure(exec.agent, exec.signal);
|
|
38
38
|
const policyService = ctx.get('sandboxPolicy');
|
|
39
|
-
if (ctx.fs.sandboxMode !== undefined && !policyService) throw new Error('
|
|
39
|
+
if (ctx.fs.sandboxMode !== undefined && !policyService) throw new Error('lodestar_change: sandboxed filesystem requires sandboxPolicy.');
|
|
40
40
|
const sandboxPolicy = policyService?.resolve({ session: exec.agent.session });
|
|
41
41
|
try {
|
|
42
42
|
const workspace = await inspectWorkspace(ctx, { cwd, projectRoot: args.projectRoot, signal: exec.signal, sandboxPolicy });
|