@geeseeker/easyai-dev 3.0.0-alpha.1 → 3.0.1
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 +90 -88
- package/README_AI.md +143 -0
- package/bin/easyai-dev.js +127 -1
- package/lib/init.js +425 -0
- package/lib/server/index.d.ts +14 -0
- package/lib/server/index.d.ts.map +1 -0
- package/lib/server/index.js +126 -0
- package/lib/server/index.js.map +1 -0
- package/lib/server/resources/journal-resource.d.ts +8 -0
- package/lib/server/resources/journal-resource.d.ts.map +1 -0
- package/lib/server/resources/journal-resource.js +46 -0
- package/lib/server/resources/journal-resource.js.map +1 -0
- package/lib/server/resources/spec-resource.d.ts +11 -0
- package/lib/server/resources/spec-resource.d.ts.map +1 -0
- package/lib/server/resources/spec-resource.js +126 -0
- package/lib/server/resources/spec-resource.js.map +1 -0
- package/lib/server/resources/status-resource.d.ts +8 -0
- package/lib/server/resources/status-resource.d.ts.map +1 -0
- package/lib/server/resources/status-resource.js +36 -0
- package/lib/server/resources/status-resource.js.map +1 -0
- package/lib/server/resources/subtask-context-resource.d.ts +8 -0
- package/lib/server/resources/subtask-context-resource.d.ts.map +1 -0
- package/lib/server/resources/subtask-context-resource.js +93 -0
- package/lib/server/resources/subtask-context-resource.js.map +1 -0
- package/lib/server/resources/task-context-resource.d.ts +8 -0
- package/lib/server/resources/task-context-resource.d.ts.map +1 -0
- package/lib/server/resources/task-context-resource.js +76 -0
- package/lib/server/resources/task-context-resource.js.map +1 -0
- package/lib/server/tools/conflict-check.d.ts +7 -0
- package/lib/server/tools/conflict-check.d.ts.map +1 -0
- package/lib/server/tools/conflict-check.js +242 -0
- package/lib/server/tools/conflict-check.js.map +1 -0
- package/lib/server/tools/context-budget.d.ts +7 -0
- package/lib/server/tools/context-budget.d.ts.map +1 -0
- package/lib/server/tools/context-budget.js +178 -0
- package/lib/server/tools/context-budget.js.map +1 -0
- package/lib/server/tools/context-generate.d.ts +7 -0
- package/lib/server/tools/context-generate.d.ts.map +1 -0
- package/lib/server/tools/context-generate.js +208 -0
- package/lib/server/tools/context-generate.js.map +1 -0
- package/lib/server/tools/framework-tools.d.ts +20 -0
- package/lib/server/tools/framework-tools.d.ts.map +1 -0
- package/lib/server/tools/framework-tools.js +412 -0
- package/lib/server/tools/framework-tools.js.map +1 -0
- package/lib/server/tools/journal-append.d.ts +7 -0
- package/lib/server/tools/journal-append.d.ts.map +1 -0
- package/lib/server/tools/journal-append.js +55 -0
- package/lib/server/tools/journal-append.js.map +1 -0
- package/lib/server/tools/journal-search.d.ts +7 -0
- package/lib/server/tools/journal-search.d.ts.map +1 -0
- package/lib/server/tools/journal-search.js +63 -0
- package/lib/server/tools/journal-search.js.map +1 -0
- package/lib/server/tools/plan-validate.d.ts +7 -0
- package/lib/server/tools/plan-validate.d.ts.map +1 -0
- package/lib/server/tools/plan-validate.js +146 -0
- package/lib/server/tools/plan-validate.js.map +1 -0
- package/lib/server/tools/spec-validate.d.ts +7 -0
- package/lib/server/tools/spec-validate.d.ts.map +1 -0
- package/lib/server/tools/spec-validate.js +170 -0
- package/lib/server/tools/spec-validate.js.map +1 -0
- package/lib/server/tools/subtask-tools.d.ts +12 -0
- package/lib/server/tools/subtask-tools.d.ts.map +1 -0
- package/lib/server/tools/subtask-tools.js +383 -0
- package/lib/server/tools/subtask-tools.js.map +1 -0
- package/lib/server/tools/task-append-log.d.ts +7 -0
- package/lib/server/tools/task-append-log.d.ts.map +1 -0
- package/lib/server/tools/task-append-log.js +108 -0
- package/lib/server/tools/task-append-log.js.map +1 -0
- package/lib/server/tools/task-cancel.d.ts +7 -0
- package/lib/server/tools/task-cancel.d.ts.map +1 -0
- package/lib/server/tools/task-cancel.js +104 -0
- package/lib/server/tools/task-cancel.js.map +1 -0
- package/lib/server/tools/task-create.d.ts +7 -0
- package/lib/server/tools/task-create.d.ts.map +1 -0
- package/lib/server/tools/task-create.js +98 -0
- package/lib/server/tools/task-create.js.map +1 -0
- package/lib/server/tools/task-get.d.ts +7 -0
- package/lib/server/tools/task-get.d.ts.map +1 -0
- package/lib/server/tools/task-get.js +152 -0
- package/lib/server/tools/task-get.js.map +1 -0
- package/lib/server/tools/task-list.d.ts +7 -0
- package/lib/server/tools/task-list.d.ts.map +1 -0
- package/lib/server/tools/task-list.js +66 -0
- package/lib/server/tools/task-list.js.map +1 -0
- package/lib/server/tools/task-transition.d.ts +7 -0
- package/lib/server/tools/task-transition.d.ts.map +1 -0
- package/lib/server/tools/task-transition.js +259 -0
- package/lib/server/tools/task-transition.js.map +1 -0
- package/lib/server/tools/worktree-tools.d.ts +17 -0
- package/lib/server/tools/worktree-tools.d.ts.map +1 -0
- package/lib/server/tools/worktree-tools.js +336 -0
- package/lib/server/tools/worktree-tools.js.map +1 -0
- package/lib/server/utils/capability-gate.d.ts +50 -0
- package/lib/server/utils/capability-gate.d.ts.map +1 -0
- package/lib/server/utils/capability-gate.js +146 -0
- package/lib/server/utils/capability-gate.js.map +1 -0
- package/lib/server/utils/git-utils.d.ts +33 -0
- package/lib/server/utils/git-utils.d.ts.map +1 -0
- package/lib/server/utils/git-utils.js +84 -0
- package/lib/server/utils/git-utils.js.map +1 -0
- package/lib/server/utils/hash-utils.d.ts +78 -0
- package/lib/server/utils/hash-utils.d.ts.map +1 -0
- package/lib/server/utils/hash-utils.js +153 -0
- package/lib/server/utils/hash-utils.js.map +1 -0
- package/lib/server/utils/journal-utils.d.ts +69 -0
- package/lib/server/utils/journal-utils.d.ts.map +1 -0
- package/lib/server/utils/journal-utils.js +387 -0
- package/lib/server/utils/journal-utils.js.map +1 -0
- package/lib/server/utils/status-utils.d.ts +58 -0
- package/lib/server/utils/status-utils.d.ts.map +1 -0
- package/lib/server/utils/status-utils.js +70 -0
- package/lib/server/utils/status-utils.js.map +1 -0
- package/lib/server/utils/task-utils.d.ts +104 -0
- package/lib/server/utils/task-utils.d.ts.map +1 -0
- package/lib/server/utils/task-utils.js +396 -0
- package/lib/server/utils/task-utils.js.map +1 -0
- package/lib/server/utils/uri-utils.d.ts +9 -0
- package/lib/server/utils/uri-utils.d.ts.map +1 -0
- package/lib/server/utils/uri-utils.js +21 -0
- package/lib/server/utils/uri-utils.js.map +1 -0
- package/package.json +30 -21
- package/skeleton/.agents/rules/anti-hallucination.md +42 -0
- package/skeleton/.agents/rules/coding-standards.md +41 -0
- package/skeleton/.agents/rules/project-identity.md +71 -0
- package/skeleton/.agents/skills/common-framework-evolve/.gitkeep +0 -0
- package/skeleton/.agents/skills/common-framework-evolve/SKILL.md +105 -0
- package/skeleton/.agents/skills/common-session-close/.gitkeep +0 -0
- package/skeleton/.agents/skills/common-session-close/SKILL.md +83 -0
- package/skeleton/.agents/skills/common-spec-update/.gitkeep +0 -0
- package/skeleton/.agents/skills/common-spec-update/SKILL.md +87 -0
- package/skeleton/.agents/skills/pm-brainstorm/.gitkeep +0 -0
- package/skeleton/.agents/skills/pm-brainstorm/SKILL.md +114 -0
- package/skeleton/.agents/skills/pm-session-start/.gitkeep +0 -0
- package/skeleton/.agents/skills/pm-session-start/SKILL.md +73 -0
- package/skeleton/.agents/skills/pm-task-planning/SKILL.md +200 -0
- package/skeleton/.agents/skills/pm-task-review/.gitkeep +0 -0
- package/skeleton/.agents/skills/pm-task-review/SKILL.md +144 -0
- package/skeleton/.agents/skills/worker-check/.gitkeep +0 -0
- package/skeleton/.agents/skills/worker-check/SKILL.md +194 -0
- package/skeleton/.agents/skills/worker-debug/.gitkeep +0 -0
- package/skeleton/.agents/skills/worker-debug/SKILL.md +241 -0
- package/skeleton/.agents/skills/worker-implement/.gitkeep +0 -0
- package/skeleton/.agents/skills/worker-implement/SKILL.md +192 -0
- package/skeleton/.agents/workflows/pm.md +81 -0
- package/skeleton/.agents/workflows/worker.md +100 -0
- package/skeleton/.docs/README.md +25 -0
- package/skeleton/.docs/archive/.gitkeep +0 -0
- package/skeleton/.docs/design/.gitkeep +0 -0
- package/skeleton/.docs/guides/.gitkeep +0 -0
- package/skeleton/.docs/notes/.gitkeep +0 -0
- package/skeleton/.docs/requirements/.gitkeep +0 -0
- package/skeleton/.trellis/config/config.yaml +48 -0
- package/skeleton/.trellis/spec/backend/.gitkeep +0 -0
- package/skeleton/.trellis/spec/frontend/.gitkeep +0 -0
- package/skeleton/.trellis/spec/guides/.gitkeep +0 -0
- package/skeleton/.trellis/spec/guides/external-cli-guide.md +253 -0
- package/skeleton/.trellis/spec/guides/task-workflow.md +34 -0
- package/skeleton/.trellis/spec/guides/testing.md +32 -0
- package/skeleton/.trellis/spec/spec-schema.json +64 -0
- package/skeleton/.trellis/tasks/.gitkeep +0 -0
- package/skeleton/.trellis/workspace/.gitkeep +0 -0
- package/skeleton/README.md +25 -0
- package/LICENSE +0 -21
- package/src/cli/index.js +0 -40
- package/src/commands/init.js +0 -37
- package/src/commands/update.js +0 -33
- package/templates/README.md +0 -22
- package/templates/agents/README.md +0 -4
- package/templates/trellis/README.md +0 -4
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
// ============ 工具函数 ============
|
|
3
|
+
/**
|
|
4
|
+
* 获取当前 Git 分支名
|
|
5
|
+
* @returns 当前分支名,失败返回 'HEAD'
|
|
6
|
+
*/
|
|
7
|
+
function getGitBranch() {
|
|
8
|
+
try {
|
|
9
|
+
const result = execSync('git rev-parse --abbrev-ref HEAD', {
|
|
10
|
+
encoding: 'utf-8',
|
|
11
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
12
|
+
});
|
|
13
|
+
return result.trim();
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
return 'HEAD';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 获取 Git 状态(简短格式)
|
|
21
|
+
* @returns `git status --short` 输出,失败返回空字符串
|
|
22
|
+
*/
|
|
23
|
+
function getGitStatus() {
|
|
24
|
+
try {
|
|
25
|
+
const result = execSync('git status --short', {
|
|
26
|
+
encoding: 'utf-8',
|
|
27
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
28
|
+
});
|
|
29
|
+
return result.trim();
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
return '';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 获取最近 N 条 commit 记录
|
|
37
|
+
* @param count - 获取的 commit 数量,默认为 10
|
|
38
|
+
* @returns commit 信息列表
|
|
39
|
+
*/
|
|
40
|
+
function getRecentCommits(count = 10) {
|
|
41
|
+
try {
|
|
42
|
+
// 使用 git log 格式化输出
|
|
43
|
+
const format = '%H|%s|%ci|%an';
|
|
44
|
+
const result = execSync(`git log -n ${count} --format="${format}"`, {
|
|
45
|
+
encoding: 'utf-8',
|
|
46
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
47
|
+
});
|
|
48
|
+
const commits = [];
|
|
49
|
+
const lines = result.trim().split('\n');
|
|
50
|
+
for (const line of lines) {
|
|
51
|
+
const parts = line.split('|');
|
|
52
|
+
if (parts.length >= 4) {
|
|
53
|
+
commits.push({
|
|
54
|
+
hash: parts[0],
|
|
55
|
+
message: parts[1],
|
|
56
|
+
date: parts[2],
|
|
57
|
+
author: parts[3],
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return commits;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 检查当前目录是否在 Git 仓库中
|
|
69
|
+
* @returns 是否在 Git 仓库中
|
|
70
|
+
*/
|
|
71
|
+
function isGitRepo() {
|
|
72
|
+
try {
|
|
73
|
+
execSync('git rev-parse --git-dir', {
|
|
74
|
+
encoding: 'utf-8',
|
|
75
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
76
|
+
});
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export { getGitBranch, getGitStatus, getRecentCommits, isGitRepo, };
|
|
84
|
+
//# sourceMappingURL=git-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-utils.js","sourceRoot":"","sources":["../../src/utils/git-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAc9C,iCAAiC;AAEjC;;;GAGG;AACH,SAAS,YAAY;IACnB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,iCAAiC,EAAE;YACzD,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,MAAM,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY;IACnB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,oBAAoB,EAAE;YAC5C,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,QAAgB,EAAE;IAC1C,IAAI,CAAC;QACH,mBAAmB;QACnB,MAAM,MAAM,GAAG,eAAe,CAAC;QAC/B,MAAM,MAAM,GAAG,QAAQ,CAAC,cAAc,KAAK,cAAc,MAAM,GAAG,EAAE;YAClE,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAgB,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAExC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC9B,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;gBACtB,OAAO,CAAC,IAAI,CAAC;oBACX,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;oBACd,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;oBACjB,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;oBACd,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;iBACjB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,SAAS;IAChB,IAAI,CAAC;QACH,QAAQ,CAAC,yBAAyB,EAAE;YAClC,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAKD,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,SAAS,GACV,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* context.jsonl 中每条记录的结构
|
|
3
|
+
*/
|
|
4
|
+
interface ContextEntry {
|
|
5
|
+
uri: string;
|
|
6
|
+
phase?: string;
|
|
7
|
+
priority?: string;
|
|
8
|
+
reason?: string;
|
|
9
|
+
confidence?: number;
|
|
10
|
+
token_estimate?: number;
|
|
11
|
+
source?: string;
|
|
12
|
+
content_hash?: string;
|
|
13
|
+
frozen_at?: string | null;
|
|
14
|
+
stale?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 快照生成结果
|
|
18
|
+
*/
|
|
19
|
+
interface SnapshotResult {
|
|
20
|
+
snapshotPath: string;
|
|
21
|
+
entriesCount: number;
|
|
22
|
+
frozenAt: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Stale 检测结果
|
|
26
|
+
*/
|
|
27
|
+
interface StaleCheckResult {
|
|
28
|
+
totalEntries: number;
|
|
29
|
+
staleEntries: StaleEntry[];
|
|
30
|
+
allFresh: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 单条 stale 记录
|
|
34
|
+
*/
|
|
35
|
+
interface StaleEntry {
|
|
36
|
+
uri: string;
|
|
37
|
+
snapshotHash: string;
|
|
38
|
+
currentHash: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 计算文件内容的 SHA256 哈希值
|
|
42
|
+
* @param filePath - 文件绝对路径
|
|
43
|
+
* @returns 格式为 "sha256:xxxx" 的哈希字符串
|
|
44
|
+
*/
|
|
45
|
+
declare function computeContentHash(filePath: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* 将 URI 解析为文件系统绝对路径
|
|
48
|
+
* 支持 trellis:// 和 spec:// 协议
|
|
49
|
+
* @param uri - 资源 URI
|
|
50
|
+
* @returns 文件绝对路径,无法解析时返回 null
|
|
51
|
+
*/
|
|
52
|
+
declare function resolveUriToPath(uri: string): string | null;
|
|
53
|
+
/**
|
|
54
|
+
* 解析 context.jsonl 文件
|
|
55
|
+
* 每行一条 JSON 记录,跳过空行和解析失败的行
|
|
56
|
+
* @param jsonlPath - context.jsonl 文件绝对路径
|
|
57
|
+
* @returns 解析后的条目数组
|
|
58
|
+
*/
|
|
59
|
+
declare function parseContextJsonl(jsonlPath: string): ContextEntry[];
|
|
60
|
+
/**
|
|
61
|
+
* 生成 Phase-Frozen 快照
|
|
62
|
+
* 读取任务目录下的 context.jsonl,为每条 URI 条目计算 content_hash,
|
|
63
|
+
* 填入 frozen_at 时间戳,写入 context-snapshot-{phase}.jsonl
|
|
64
|
+
*
|
|
65
|
+
* @param taskDir - 任务目录绝对路径
|
|
66
|
+
* @param phase - 阶段标识(如 "implement")
|
|
67
|
+
* @returns 快照结果,context.jsonl 不存在时返回 null
|
|
68
|
+
*/
|
|
69
|
+
declare function generateSnapshot(taskDir: string, phase: string): SnapshotResult | null;
|
|
70
|
+
/**
|
|
71
|
+
* Stale 检测 — 比对快照中每条记录的 content_hash 与当前文件 hash
|
|
72
|
+
* @param snapshotPath - 快照文件绝对路径
|
|
73
|
+
* @returns stale 检测结果
|
|
74
|
+
*/
|
|
75
|
+
declare function checkStale(snapshotPath: string): StaleCheckResult;
|
|
76
|
+
export type { ContextEntry, SnapshotResult, StaleCheckResult, StaleEntry, };
|
|
77
|
+
export { computeContentHash, resolveUriToPath, parseContextJsonl, generateSnapshot, checkStale, };
|
|
78
|
+
//# sourceMappingURL=hash-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash-utils.d.ts","sourceRoot":"","sources":["../../src/utils/hash-utils.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,UAAU,YAAY;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,UAAU,cAAc;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,UAAU,gBAAgB;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,UAAU,EAAE,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,UAAU,UAAU;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAID;;;;GAIG;AACH,iBAAS,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIpD;AAED;;;;;GAKG;AACH,iBAAS,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkCpD;AAED;;;;;GAKG;AACH,iBAAS,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,EAAE,CAmB5D;AAED;;;;;;;;GAQG;AACH,iBAAS,gBAAgB,CACvB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,cAAc,GAAG,IAAI,CAsCvB;AAED;;;;GAIG;AACH,iBAAS,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,gBAAgB,CAsC1D;AAID,YAAY,EACV,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,UAAU,GACX,CAAC;AAEF,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,GACX,CAAC"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import * as crypto from "node:crypto";
|
|
4
|
+
import { getProjectRoot } from "./task-utils.js";
|
|
5
|
+
// ============ 核心函数 ============
|
|
6
|
+
/**
|
|
7
|
+
* 计算文件内容的 SHA256 哈希值
|
|
8
|
+
* @param filePath - 文件绝对路径
|
|
9
|
+
* @returns 格式为 "sha256:xxxx" 的哈希字符串
|
|
10
|
+
*/
|
|
11
|
+
function computeContentHash(filePath) {
|
|
12
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
13
|
+
const hash = crypto.createHash("sha256").update(content).digest("hex");
|
|
14
|
+
return `sha256:${hash}`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 将 URI 解析为文件系统绝对路径
|
|
18
|
+
* 支持 trellis:// 和 spec:// 协议
|
|
19
|
+
* @param uri - 资源 URI
|
|
20
|
+
* @returns 文件绝对路径,无法解析时返回 null
|
|
21
|
+
*/
|
|
22
|
+
function resolveUriToPath(uri) {
|
|
23
|
+
const projectRoot = getProjectRoot();
|
|
24
|
+
// 统一前缀:追加 sep 防止匹配兄弟目录如 spec-malicious/
|
|
25
|
+
const specRoot = path.join(projectRoot, ".trellis", "spec") + path.sep;
|
|
26
|
+
// spec:// 简写 → trellis://spec/...
|
|
27
|
+
if (uri.startsWith("spec://")) {
|
|
28
|
+
let specPath = uri.replace("spec://", "");
|
|
29
|
+
// 规范化:去除已有 .md 后缀后统一追加,防止 .md.md
|
|
30
|
+
if (specPath.endsWith(".md")) {
|
|
31
|
+
specPath = specPath.slice(0, -3);
|
|
32
|
+
}
|
|
33
|
+
const fullPath = path.resolve(projectRoot, ".trellis", "spec", `${specPath}.md`);
|
|
34
|
+
if (!fullPath.startsWith(specRoot))
|
|
35
|
+
return null;
|
|
36
|
+
return fs.existsSync(fullPath) ? fullPath : null;
|
|
37
|
+
}
|
|
38
|
+
// trellis://spec/{category}/{name}
|
|
39
|
+
if (uri.startsWith("trellis://spec/")) {
|
|
40
|
+
let specPath = uri.replace("trellis://spec/", "");
|
|
41
|
+
// 规范化:去除已有 .md 后缀后统一追加,防止 .md.md
|
|
42
|
+
if (specPath.endsWith(".md")) {
|
|
43
|
+
specPath = specPath.slice(0, -3);
|
|
44
|
+
}
|
|
45
|
+
const fullPath = path.resolve(projectRoot, ".trellis", "spec", `${specPath}.md`);
|
|
46
|
+
if (!fullPath.startsWith(specRoot))
|
|
47
|
+
return null;
|
|
48
|
+
return fs.existsSync(fullPath) ? fullPath : null;
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 解析 context.jsonl 文件
|
|
54
|
+
* 每行一条 JSON 记录,跳过空行和解析失败的行
|
|
55
|
+
* @param jsonlPath - context.jsonl 文件绝对路径
|
|
56
|
+
* @returns 解析后的条目数组
|
|
57
|
+
*/
|
|
58
|
+
function parseContextJsonl(jsonlPath) {
|
|
59
|
+
const content = fs.readFileSync(jsonlPath, "utf-8");
|
|
60
|
+
const entries = [];
|
|
61
|
+
for (const line of content.split("\n")) {
|
|
62
|
+
const trimmed = line.trim();
|
|
63
|
+
if (!trimmed)
|
|
64
|
+
continue;
|
|
65
|
+
try {
|
|
66
|
+
entries.push(JSON.parse(trimmed));
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
// 记录解析失败的行,便于排查 context.jsonl 格式错误
|
|
70
|
+
console.warn(`[hash-utils] context.jsonl 解析失败,跳过该行: ${trimmed.substring(0, 80)}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return entries;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 生成 Phase-Frozen 快照
|
|
77
|
+
* 读取任务目录下的 context.jsonl,为每条 URI 条目计算 content_hash,
|
|
78
|
+
* 填入 frozen_at 时间戳,写入 context-snapshot-{phase}.jsonl
|
|
79
|
+
*
|
|
80
|
+
* @param taskDir - 任务目录绝对路径
|
|
81
|
+
* @param phase - 阶段标识(如 "implement")
|
|
82
|
+
* @returns 快照结果,context.jsonl 不存在时返回 null
|
|
83
|
+
*/
|
|
84
|
+
function generateSnapshot(taskDir, phase) {
|
|
85
|
+
const contextPath = path.join(taskDir, "context.jsonl");
|
|
86
|
+
if (!fs.existsSync(contextPath)) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
const entries = parseContextJsonl(contextPath);
|
|
90
|
+
const frozenAt = new Date().toISOString();
|
|
91
|
+
// 为每条记录计算 content_hash 并设置 frozen_at
|
|
92
|
+
const frozenEntries = entries.map((entry) => {
|
|
93
|
+
const filePath = resolveUriToPath(entry.uri);
|
|
94
|
+
const contentHash = filePath ? computeContentHash(filePath) : (entry.content_hash || "");
|
|
95
|
+
return {
|
|
96
|
+
...entry,
|
|
97
|
+
content_hash: contentHash,
|
|
98
|
+
frozen_at: frozenAt,
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
// 写入快照文件
|
|
102
|
+
const snapshotPath = path.join(taskDir, `context-snapshot-${phase}.jsonl`);
|
|
103
|
+
const snapshotContent = frozenEntries
|
|
104
|
+
.map((e) => JSON.stringify(e))
|
|
105
|
+
.join("\n");
|
|
106
|
+
fs.writeFileSync(snapshotPath, snapshotContent + "\n", "utf-8");
|
|
107
|
+
return {
|
|
108
|
+
snapshotPath,
|
|
109
|
+
entriesCount: frozenEntries.length,
|
|
110
|
+
frozenAt,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Stale 检测 — 比对快照中每条记录的 content_hash 与当前文件 hash
|
|
115
|
+
* @param snapshotPath - 快照文件绝对路径
|
|
116
|
+
* @returns stale 检测结果
|
|
117
|
+
*/
|
|
118
|
+
function checkStale(snapshotPath) {
|
|
119
|
+
if (!fs.existsSync(snapshotPath)) {
|
|
120
|
+
return { totalEntries: 0, staleEntries: [], allFresh: true };
|
|
121
|
+
}
|
|
122
|
+
const entries = parseContextJsonl(snapshotPath);
|
|
123
|
+
const staleEntries = [];
|
|
124
|
+
for (const entry of entries) {
|
|
125
|
+
if (!entry.content_hash)
|
|
126
|
+
continue;
|
|
127
|
+
const filePath = resolveUriToPath(entry.uri);
|
|
128
|
+
// 文件已删除或重命名 → 标记为 stale(漂移的最严重形式)
|
|
129
|
+
if (!filePath) {
|
|
130
|
+
staleEntries.push({
|
|
131
|
+
uri: entry.uri,
|
|
132
|
+
snapshotHash: entry.content_hash,
|
|
133
|
+
currentHash: "deleted",
|
|
134
|
+
});
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const currentHash = computeContentHash(filePath);
|
|
138
|
+
if (currentHash !== entry.content_hash) {
|
|
139
|
+
staleEntries.push({
|
|
140
|
+
uri: entry.uri,
|
|
141
|
+
snapshotHash: entry.content_hash,
|
|
142
|
+
currentHash,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
totalEntries: entries.length,
|
|
148
|
+
staleEntries,
|
|
149
|
+
allFresh: staleEntries.length === 0,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
export { computeContentHash, resolveUriToPath, parseContextJsonl, generateSnapshot, checkStale, };
|
|
153
|
+
//# sourceMappingURL=hash-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash-utils.js","sourceRoot":"","sources":["../../src/utils/hash-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
declare const WORKSPACE_ROOT = ".trellis/workspace";
|
|
2
|
+
declare const MAX_LINES_PER_FILE = 2000;
|
|
3
|
+
declare const DEFAULT_USER = "default";
|
|
4
|
+
/**
|
|
5
|
+
* Journal 条目接口
|
|
6
|
+
*/
|
|
7
|
+
export interface JournalEntry {
|
|
8
|
+
date: string;
|
|
9
|
+
tags: string[];
|
|
10
|
+
tasks_touched?: string[];
|
|
11
|
+
content: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 日志搜索查询选项
|
|
15
|
+
*/
|
|
16
|
+
interface JournalSearchQuery {
|
|
17
|
+
tags?: string[];
|
|
18
|
+
keywords?: string[];
|
|
19
|
+
date_range?: {
|
|
20
|
+
from?: string;
|
|
21
|
+
to?: string;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 获取用户 journal 目录
|
|
26
|
+
* 按 architecture §6.4,journal 文件位于 .trellis/workspace/{user}/
|
|
27
|
+
* @param user - 用户名,默认为 'default'
|
|
28
|
+
* @returns journal 目录的绝对路径
|
|
29
|
+
*/
|
|
30
|
+
declare function getJournalDir(user?: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* 获取最新(或当前活跃)的 journal 文件路径
|
|
33
|
+
* 返回当前正在写入的文件(最高页码的文件,或 journal.md 如果不存在编号文件)
|
|
34
|
+
* @param user - 用户名,默认为 'default'
|
|
35
|
+
* @returns 最新 journal 文件的绝对路径
|
|
36
|
+
*/
|
|
37
|
+
declare function getLatestJournalFile(user?: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* 追加日志条目到 journal 文件
|
|
40
|
+
* 如果当前文件超过 MAX_LINES_PER_FILE,自动创建新文件
|
|
41
|
+
* @param entry - 日志条目
|
|
42
|
+
* @param user - 用户名,默认为 'default'
|
|
43
|
+
*/
|
|
44
|
+
declare function appendJournalEntry(entry: JournalEntry, user?: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* 解析 journal 文件中的所有条目
|
|
47
|
+
* 条目由 YAML frontmatter 包裹,使用 `---` 作为开始和结束标记
|
|
48
|
+
* @param content - journal 文件内容
|
|
49
|
+
* @returns 解析后的日志条目列表
|
|
50
|
+
*/
|
|
51
|
+
declare function parseJournalEntries(content: string): JournalEntry[];
|
|
52
|
+
/**
|
|
53
|
+
* 搜索日志条目
|
|
54
|
+
* @param query - 搜索查询选项
|
|
55
|
+
* @param user - 用户名,默认为 'default'
|
|
56
|
+
* @returns 匹配的日志条目列表
|
|
57
|
+
*/
|
|
58
|
+
declare function searchJournal(query: JournalSearchQuery, user?: string): JournalEntry[];
|
|
59
|
+
/**
|
|
60
|
+
* 获取最新的 N 条日志条目
|
|
61
|
+
* 条目按时间倒序排列(最新的在前)
|
|
62
|
+
* @param count - 获取的条目数量,默认为 10
|
|
63
|
+
* @param user - 用户名,默认为 'default'
|
|
64
|
+
* @returns 最新的日志条目列表
|
|
65
|
+
*/
|
|
66
|
+
declare function getLatestEntries(count?: number, user?: string): JournalEntry[];
|
|
67
|
+
export type { JournalSearchQuery };
|
|
68
|
+
export { WORKSPACE_ROOT, MAX_LINES_PER_FILE, DEFAULT_USER, getJournalDir, getLatestJournalFile, appendJournalEntry, parseJournalEntries, searchJournal, getLatestEntries, };
|
|
69
|
+
//# sourceMappingURL=journal-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal-utils.d.ts","sourceRoot":"","sources":["../../src/utils/journal-utils.ts"],"names":[],"mappings":"AAMA,QAAA,MAAM,cAAc,uBAAuB,CAAC;AAC5C,QAAA,MAAM,kBAAkB,OAAO,CAAC;AAChC,QAAA,MAAM,YAAY,YAAY,CAAC;AAI/B;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,UAAU,kBAAkB;IAC1B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE;QACX,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,EAAE,CAAC,EAAE,MAAM,CAAC;KACb,CAAC;CACH;AAID;;;;;GAKG;AACH,iBAAS,aAAa,CAAC,IAAI,GAAE,MAAqB,GAAG,MAAM,CAU1D;AAED;;;;;GAKG;AACH,iBAAS,oBAAoB,CAAC,IAAI,GAAE,MAAqB,GAAG,MAAM,CA8BjE;AAoCD;;;;;GAKG;AACH,iBAAS,kBAAkB,CACzB,KAAK,EAAE,YAAY,EACnB,IAAI,GAAE,MAAqB,GAC1B,IAAI,CAuBN;AAqDD;;;;;GAKG;AACH,iBAAS,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,CA6E5D;AA+ED;;;;;GAKG;AACH,iBAAS,aAAa,CACpB,KAAK,EAAE,kBAAkB,EACzB,IAAI,GAAE,MAAqB,GAC1B,YAAY,EAAE,CA0EhB;AAED;;;;;;GAMG;AACH,iBAAS,gBAAgB,CACvB,KAAK,GAAE,MAAW,EAClB,IAAI,GAAE,MAAqB,GAC1B,YAAY,EAAE,CAIhB;AAID,YAAY,EAAE,kBAAkB,EAAE,CAAC;AACnC,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,GACjB,CAAC"}
|