@hoplogic/hopjit 0.1.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.
Files changed (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +99 -0
  3. package/dist/act-body-interpreter.d.ts +24 -0
  4. package/dist/act-body-interpreter.js +159 -0
  5. package/dist/act-body-parser.d.ts +10 -0
  6. package/dist/act-body-parser.js +577 -0
  7. package/dist/act-builtins.d.ts +12 -0
  8. package/dist/act-builtins.js +104 -0
  9. package/dist/ast-helpers.d.ts +26 -0
  10. package/dist/ast-helpers.js +58 -0
  11. package/dist/ast-runtime.d.ts +49 -0
  12. package/dist/ast-runtime.js +224 -0
  13. package/dist/ast-types.d.ts +260 -0
  14. package/dist/ast-types.js +4 -0
  15. package/dist/cli-types.d.ts +190 -0
  16. package/dist/cli-types.js +4 -0
  17. package/dist/cli.d.ts +26 -0
  18. package/dist/cli.js +623 -0
  19. package/dist/dispatcher.d.ts +92 -0
  20. package/dist/dispatcher.js +692 -0
  21. package/dist/doc-ref.d.ts +41 -0
  22. package/dist/doc-ref.js +214 -0
  23. package/dist/engine-traverse.d.ts +37 -0
  24. package/dist/engine-traverse.js +385 -0
  25. package/dist/engine.d.ts +141 -0
  26. package/dist/engine.js +1792 -0
  27. package/dist/errors.d.ts +47 -0
  28. package/dist/errors.js +34 -0
  29. package/dist/hoplog.d.ts +120 -0
  30. package/dist/hoplog.js +501 -0
  31. package/dist/parser.d.ts +7 -0
  32. package/dist/parser.js +802 -0
  33. package/dist/persistence.d.ts +60 -0
  34. package/dist/persistence.js +208 -0
  35. package/dist/prompt.d.ts +130 -0
  36. package/dist/prompt.js +1014 -0
  37. package/dist/provider-types.d.ts +134 -0
  38. package/dist/provider-types.js +3 -0
  39. package/dist/runtime-types.d.ts +84 -0
  40. package/dist/runtime-types.js +4 -0
  41. package/dist/tools.d.ts +16 -0
  42. package/dist/tools.js +141 -0
  43. package/dist/validator.d.ts +23 -0
  44. package/dist/validator.js +959 -0
  45. package/driver/codex/AGENTS.md +54 -0
  46. package/driver/hopskill-build/SKILL.md +137 -0
  47. package/driver/hopskill-build/references/spec-skeleton.md +132 -0
  48. package/driver/hopskill-build/references/step-type-cheatsheet.md +56 -0
  49. package/driver/hopskill-build/references/three-focus-rules.md +148 -0
  50. package/driver/hopspec-skill.md +187 -0
  51. package/driver/references/cli-discovery.md +36 -0
  52. package/driver/references/discovery.md +45 -0
  53. package/driver/references/driver-subagent.md +50 -0
  54. package/driver/references/parallel-worker.md +50 -0
  55. package/driver/references/step-execution-rules.md +47 -0
  56. package/package.json +52 -0
@@ -0,0 +1,26 @@
1
+ import type { StepType, StepNode, SubtaskStep, ParallelStep, LoopStep, BranchStep, CaseStep } from './ast-types.js';
2
+ /** 7 种可执行步骤类型集合(reason/act/check/confirm/ask/commit/call),供 parser/validator/engine 判类。见 [[spec-ast#^anc-struct-spec-ast-exports]]。 */
3
+ export declare const EXECUTABLE_STEP_TYPES: ReadonlySet<StepType>;
4
+ /** 8 种结构/控制流步骤类型集合(subtask/parallel/loop/branch/case/break/continue/exit),由引擎内部展开而非交 LLM 执行。见 [[spec-ast#^anc-struct-spec-ast-exports]]。 */
5
+ export declare const STRUCTURAL_STEP_TYPES: ReadonlySet<StepType>;
6
+ /** 持有 children 的容器步骤类型集合(subtask/parallel/loop/branch/case),isContainerStep 据此判定。见 [[spec-ast#^anc-struct-spec-ast-exports]]。 */
7
+ export declare const CONTAINER_STEP_TYPES: ReadonlySet<StepType>;
8
+ /** 全部 15 种步骤类型集合(7 可执行 ∪ 8 结构/控制流),全类型判类的并集。见 [[spec-ast#^anc-struct-spec-ast-exports]]。 */
9
+ export declare const ALL_STEP_TYPES: ReadonlySet<StepType>;
10
+ export declare const DEFLATE_THRESHOLD = 4096;
11
+ export declare const HUMAN_PREVIEW_THRESHOLD = 5000;
12
+ export declare function isContainerStep(step: StepNode): step is SubtaskStep | ParallelStep | LoopStep | BranchStep | CaseStep;
13
+ /** 判定步骤是否实际持有 children 数组的类型守卫(结构存在性检查,收窄为容器步骤类型)。见 [[spec-ast#^anc-struct-spec-ast-exports]]。 */
14
+ export declare function hasChildren(step: StepNode): step is SubtaskStep | ParallelStep | LoopStep | BranchStep | CaseStep;
15
+ /** 取步骤的子步骤列表,非容器或无 children 时返回空数组。见 [[spec-ast#^anc-struct-spec-ast-exports]]。 */
16
+ export declare function getChildren(step: StepNode): StepNode[];
17
+ export declare function getParentStepId(stepId: string): string | null;
18
+ /** 判某输出名是否为该步的"更新模式"输出——步骤同时 `← outName` 且 `+ → outName`(读入即输出,
19
+ * 在既有变量基础上更新而非新产出)。三处共用同一判据:engine failStep 跳过 null 化 / check 失败
20
+ * 写回 / validator V3 放行遮蔽。抽此消除重复、保判据一致。见 ^anc-exec-failstep-skip-update / ^anc-rule-v3。
21
+ * @a: anc-exec-failstep-skip-update */
22
+ export declare function isUpdateModeOutput(step: {
23
+ inputs?: {
24
+ source: string;
25
+ }[];
26
+ }, outName: string): boolean;
@@ -0,0 +1,58 @@
1
+ // @module: spec-ast ^anc-struct-spec-ast
2
+ // AST 谓词函数 + 跨模块常量——非类型的运行时逻辑(从原 types.ts 剥离,回归 types 纯类型契约)。
3
+ // 见 design/spec-ast.md ^anc-struct-spec-ast(拆分动机:类型文件不应混逻辑)。
4
+ /** 7 种可执行步骤类型集合(reason/act/check/confirm/ask/commit/call),供 parser/validator/engine 判类。见 [[spec-ast#^anc-struct-spec-ast-exports]]。 */
5
+ export const EXECUTABLE_STEP_TYPES = new Set([
6
+ 'reason', 'act', 'check', 'confirm', 'ask', 'commit', 'call',
7
+ ]);
8
+ /** 8 种结构/控制流步骤类型集合(subtask/parallel/loop/branch/case/break/continue/exit),由引擎内部展开而非交 LLM 执行。见 [[spec-ast#^anc-struct-spec-ast-exports]]。 */
9
+ export const STRUCTURAL_STEP_TYPES = new Set([
10
+ 'subtask', 'parallel', 'loop', 'branch', 'case', 'break', 'continue', 'exit',
11
+ ]);
12
+ /** 持有 children 的容器步骤类型集合(subtask/parallel/loop/branch/case),isContainerStep 据此判定。见 [[spec-ast#^anc-struct-spec-ast-exports]]。 */
13
+ export const CONTAINER_STEP_TYPES = new Set([
14
+ 'subtask', 'parallel', 'loop', 'branch', 'case',
15
+ ]);
16
+ /** 全部 15 种步骤类型集合(7 可执行 ∪ 8 结构/控制流),全类型判类的并集。见 [[spec-ast#^anc-struct-spec-ast-exports]]。 */
17
+ export const ALL_STEP_TYPES = new Set([
18
+ ...EXECUTABLE_STEP_TYPES, ...STRUCTURAL_STEP_TYPES,
19
+ ]);
20
+ // 大内容阈值(agent 通道):NextResponse 中 inputs/outputs/params_for_child 等
21
+ // record 的单个值 JSON.stringify().length 超此阈值时,引擎自动写入 work_zone/vars/<key>.json,
22
+ // 响应中替换为 {$file: abs_path} 指针。driver/LLM 遇 $file 时 Read 取真实值。
23
+ // 见 design/shared-types.md ^anc-exec-deflate。// @a: anc-exec-deflate
24
+ export const DEFLATE_THRESHOLD = 4096;
25
+ // 人通道预览阈值:paused.presented_data.context(给 user 看的)单值超此字符数时,
26
+ // 引擎返 {$file, preview} 复合格式:preview = 头 5K 字符 + "...[完整内容见文件]",
27
+ // driver 完整 dump preview 给 user 看,$file 让 user 知完整在哪。
28
+ // 见 design/shared-types.md ^anc-exec-deflate / 概念 ^anc-exec-audience-routing。
29
+ // @a: anc-exec-deflate, anc-exec-audience-routing
30
+ export const HUMAN_PREVIEW_THRESHOLD = 5000;
31
+ // ===== Type guards =====
32
+ export function isContainerStep(step) {
33
+ return CONTAINER_STEP_TYPES.has(step.step_type);
34
+ }
35
+ /** 判定步骤是否实际持有 children 数组的类型守卫(结构存在性检查,收窄为容器步骤类型)。见 [[spec-ast#^anc-struct-spec-ast-exports]]。 */
36
+ export function hasChildren(step) {
37
+ return 'children' in step && Array.isArray(step.children);
38
+ }
39
+ /** 取步骤的子步骤列表,非容器或无 children 时返回空数组。见 [[spec-ast#^anc-struct-spec-ast-exports]]。 */
40
+ export function getChildren(step) {
41
+ if (hasChildren(step))
42
+ return step.children;
43
+ return [];
44
+ }
45
+ // ===== step_id 寻址 =====
46
+ // 取父 step_id:纯字符串操作("1.2.3" → "1.2","1" → null)。
47
+ // 无状态 AST 寻址,非执行调度职责——归 spec-ast(从 engine-traverse 迁入)。
48
+ export function getParentStepId(stepId) {
49
+ const lastDot = stepId.lastIndexOf('.');
50
+ return lastDot >= 0 ? stepId.slice(0, lastDot) : null;
51
+ }
52
+ /** 判某输出名是否为该步的"更新模式"输出——步骤同时 `← outName` 且 `+ → outName`(读入即输出,
53
+ * 在既有变量基础上更新而非新产出)。三处共用同一判据:engine failStep 跳过 null 化 / check 失败
54
+ * 写回 / validator V3 放行遮蔽。抽此消除重复、保判据一致。见 ^anc-exec-failstep-skip-update / ^anc-rule-v3。
55
+ * @a: anc-exec-failstep-skip-update */
56
+ export function isUpdateModeOutput(step, outName) {
57
+ return step.inputs?.some(b => b.source === outName) ?? false;
58
+ }
@@ -0,0 +1,49 @@
1
+ import type { OutputDecl, SpecAST, StepNode } from './ast-types.js';
2
+ export type StepStatus = 'pending' | 'running' | 'done' | 'failed' | 'skipped';
3
+ /** 步骤是否处于终态(done/failed/skipped)。单点定义终态集合——engine/engine-traverse 多处判据复用,
4
+ * 新增终态只改这里。undefined(从未 set 状态的 pending 步骤)返回 false。 */
5
+ export declare function isTerminalStatus(st: StepStatus | undefined): boolean;
6
+ /** 树状变量作用域节点:持有本层变量表并链向父作用域,read 沿链上溯实现遮蔽/继承。见 [[spec-ast#^anc-struct-spec-ast-exports]]。 */
7
+ export interface VariableScope {
8
+ id: string;
9
+ parent: VariableScope | null;
10
+ variables: Map<string, unknown>;
11
+ }
12
+ /** 树状作用域变量存储:按 scope_id 管理变量的读写/作用域创建/序列化,供 engine 与 prompt 消费(从 engine-vars 迁入语言运行时层)。见 [[spec-ast#^anc-struct-spec-ast-exports]]。 */
13
+ export declare class VariableStore {
14
+ private root;
15
+ private scopes;
16
+ constructor(inputs?: Record<string, unknown>);
17
+ createScope(scopeId: string, parentId: string): VariableScope;
18
+ /** scope 是否已存在(供 ensureScope 显式判 loop 重进/resume 已恢复,避免用 createScope 抛错做控制流)。 */
19
+ hasScope(scopeId: string): boolean;
20
+ findScope(stepId: string): VariableScope;
21
+ read(name: string, scopeId: string): unknown;
22
+ write(name: string, value: unknown, scopeId: string): void;
23
+ writeToRoot(name: string, value: unknown): void;
24
+ writeOutputs(outputs: Record<string, unknown>, scopeId: string): void;
25
+ setOutputsToNull(outputDecls: OutputDecl[], scopeId: string): void;
26
+ getAllVariables(): Record<string, unknown>;
27
+ getPendingOutputs(declaredOutputs: OutputDecl[]): string[];
28
+ clearScope(scopeId: string): void;
29
+ deleteVar(name: string, scopeId: string): void;
30
+ deleteScope(scopeId: string): void;
31
+ /** 序列化完整 scope 树(vars.json format_version=2):每个 scope 记 parent id + 本层变量。
32
+ * 见 [[exec-engine#^anc-exec-vars-scope-persist]]。不再拍平——拍平会丢兄弟 scope 同名变量。 */
33
+ toJSON(): Record<string, {
34
+ parent: string | null;
35
+ variables: Record<string, unknown>;
36
+ }>;
37
+ /** 从 scope 树重建(v2):三遍——① 建所有空 scope ② 连 parent 指针 ③ 灌变量,
38
+ * 保证连指针/灌变量前所有节点已在 map。见 [[exec-engine#^anc-exec-vars-scope-persist]]。 */
39
+ static fromScopes(scopes: Record<string, {
40
+ parent: string | null;
41
+ variables: Record<string, unknown>;
42
+ }>): VariableStore;
43
+ /** v1 legacy:扁平变量字典全塞 root(向后兼容旧 vars.json)。 */
44
+ static fromJSON(data: Record<string, unknown>): VariableStore;
45
+ }
46
+ export declare const SCOPE_CREATING_TYPES: Set<string>;
47
+ export declare function buildStepMap(spec: SpecAST): Map<string, StepNode>;
48
+ export declare function getWriteScope(stepId: string, spec: SpecAST): string;
49
+ export declare function isTruthy(value: unknown): boolean;
@@ -0,0 +1,224 @@
1
+ import { getParentStepId, hasChildren, getChildren } from './ast-helpers.js';
2
+ /** 步骤是否处于终态(done/failed/skipped)。单点定义终态集合——engine/engine-traverse 多处判据复用,
3
+ * 新增终态只改这里。undefined(从未 set 状态的 pending 步骤)返回 false。 */
4
+ export function isTerminalStatus(st) {
5
+ return st === 'done' || st === 'failed' || st === 'skipped';
6
+ }
7
+ /** 树状作用域变量存储:按 scope_id 管理变量的读写/作用域创建/序列化,供 engine 与 prompt 消费(从 engine-vars 迁入语言运行时层)。见 [[spec-ast#^anc-struct-spec-ast-exports]]。 */
8
+ export class VariableStore {
9
+ root;
10
+ scopes = new Map();
11
+ constructor(inputs) {
12
+ this.root = { id: 'root', parent: null, variables: new Map() };
13
+ this.scopes.set('root', this.root);
14
+ if (inputs) {
15
+ for (const [k, v] of Object.entries(inputs)) {
16
+ this.root.variables.set(k, v);
17
+ }
18
+ }
19
+ }
20
+ createScope(scopeId, parentId) {
21
+ const parent = this.scopes.get(parentId);
22
+ if (!parent)
23
+ throw new Error(`Parent scope '${parentId}' not found`);
24
+ const scope = { id: scopeId, parent, variables: new Map() };
25
+ this.scopes.set(scopeId, scope);
26
+ return scope;
27
+ }
28
+ /** scope 是否已存在(供 ensureScope 显式判 loop 重进/resume 已恢复,避免用 createScope 抛错做控制流)。 */
29
+ hasScope(scopeId) {
30
+ return this.scopes.has(scopeId);
31
+ }
32
+ findScope(stepId) {
33
+ return this.scopes.get(stepId) ?? this.root;
34
+ }
35
+ read(name, scopeId) {
36
+ // 整名优先:先按 name 原样向上查找(兼容真有 "a.b" 此名的扁平变量)。
37
+ let scope = this.scopes.get(scopeId) ?? this.root;
38
+ while (scope) {
39
+ if (scope.variables.has(name))
40
+ return scope.variables.get(name);
41
+ scope = scope.parent;
42
+ }
43
+ // 未命中且含路径分隔 → dotted path 成员访问:首段为根变量,逐段下钻。
44
+ // 类似 JSON 路径:对象字段按 key 取,数组按数字下标取(`arr.0` 或 `arr[0]` 皆可)。
45
+ // 用于 for-each 元素按字段/下标分流(如 branch 条件 {point.type}、{items.0.name})。
46
+ // 见 design ^anc-exec-dfs-traversal 条件求值。中途某段无法下钻(非对象/数组、越界、字段缺失)→ undefined。
47
+ if (name.includes('.') || name.includes('[')) {
48
+ // 归一化 `a[0].b` → `a.0.b`,再按 `.` 分段
49
+ const segs = name.replace(/\[(\w+)\]/g, '.$1').split('.').filter(s => s !== '');
50
+ let cur = this.scopes.get(scopeId) ?? this.root;
51
+ while (cur) {
52
+ if (cur.variables.has(segs[0])) {
53
+ let val = cur.variables.get(segs[0]);
54
+ for (let i = 1; i < segs.length; i++) {
55
+ if (val === null || typeof val !== 'object')
56
+ return undefined;
57
+ if (Array.isArray(val)) {
58
+ const idx = Number(segs[i]);
59
+ if (!Number.isInteger(idx))
60
+ return undefined; // 数组只接受整数下标
61
+ val = val[idx];
62
+ }
63
+ else {
64
+ val = val[segs[i]];
65
+ }
66
+ }
67
+ return val;
68
+ }
69
+ cur = cur.parent;
70
+ }
71
+ }
72
+ return undefined;
73
+ }
74
+ write(name, value, scopeId) {
75
+ const scope = this.scopes.get(scopeId) ?? this.root;
76
+ scope.variables.set(name, value);
77
+ }
78
+ writeToRoot(name, value) {
79
+ this.root.variables.set(name, value);
80
+ }
81
+ writeOutputs(outputs, scopeId) {
82
+ for (const [k, v] of Object.entries(outputs)) {
83
+ this.write(k, v, scopeId);
84
+ }
85
+ }
86
+ setOutputsToNull(outputDecls, scopeId) {
87
+ for (const decl of outputDecls) {
88
+ this.write(decl.name, null, scopeId);
89
+ }
90
+ }
91
+ getAllVariables() {
92
+ const result = {};
93
+ const collectScope = (scope) => {
94
+ for (const [k, v] of scope.variables) {
95
+ if (!(k in result))
96
+ result[k] = v;
97
+ }
98
+ };
99
+ for (const scope of this.scopes.values()) {
100
+ collectScope(scope);
101
+ }
102
+ return result;
103
+ }
104
+ getPendingOutputs(declaredOutputs) {
105
+ const allVars = this.getAllVariables();
106
+ return declaredOutputs
107
+ .filter(o => !(o.name in allVars) || allVars[o.name] === undefined)
108
+ .map(o => o.name);
109
+ }
110
+ clearScope(scopeId) {
111
+ const scope = this.scopes.get(scopeId);
112
+ if (scope)
113
+ scope.variables.clear();
114
+ }
115
+ // 从指定 scope 删除单个变量(删后 read 沿链上溯,本 scope 无则返回祖先值或 undefined)。
116
+ // 注:Python 语义改造后引擎不再每轮清变量(^anc-exec-loop-var-scope),此方法为通用工具、无引擎内部调用者。
117
+ deleteVar(name, scopeId) {
118
+ const scope = this.scopes.get(scopeId);
119
+ if (scope)
120
+ scope.variables.delete(name);
121
+ }
122
+ deleteScope(scopeId) {
123
+ this.scopes.delete(scopeId);
124
+ }
125
+ /** 序列化完整 scope 树(vars.json format_version=2):每个 scope 记 parent id + 本层变量。
126
+ * 见 [[exec-engine#^anc-exec-vars-scope-persist]]。不再拍平——拍平会丢兄弟 scope 同名变量。 */
127
+ // @a: anc-exec-vars-scope-persist
128
+ toJSON() {
129
+ const result = {};
130
+ for (const [scopeId, scope] of this.scopes) {
131
+ result[scopeId] = {
132
+ parent: scope.parent?.id ?? null,
133
+ variables: Object.fromEntries(scope.variables),
134
+ };
135
+ }
136
+ return result;
137
+ }
138
+ /** 从 scope 树重建(v2):三遍——① 建所有空 scope ② 连 parent 指针 ③ 灌变量,
139
+ * 保证连指针/灌变量前所有节点已在 map。见 [[exec-engine#^anc-exec-vars-scope-persist]]。 */
140
+ // @a: anc-exec-vars-scope-persist
141
+ static fromScopes(scopes) {
142
+ const store = new VariableStore();
143
+ // 第 1 遍:建所有 scope 节点(root 已由构造函数建好,复用之)
144
+ for (const scopeId of Object.keys(scopes)) {
145
+ if (scopeId === 'root')
146
+ continue;
147
+ store.scopes.set(scopeId, { id: scopeId, parent: null, variables: new Map() });
148
+ }
149
+ // 第 2 遍:连 parent 指针。孤儿 parent(数据里不存在该 parent id)响亮失败——vars.json v2 应含
150
+ // 完整 scope 树,parent 缺失是数据损坏,静默挂 root 会掩盖它。
151
+ for (const [scopeId, data] of Object.entries(scopes)) {
152
+ if (scopeId === 'root')
153
+ continue;
154
+ const scope = store.scopes.get(scopeId);
155
+ if (data.parent === null) {
156
+ scope.parent = store.root;
157
+ continue;
158
+ }
159
+ const parent = store.scopes.get(data.parent);
160
+ if (!parent)
161
+ throw new Error(`CORRUPT_STATE_FILE: vars.json scope '${scopeId}' 的 parent '${data.parent}' 不存在(scope 树损坏)`);
162
+ scope.parent = parent;
163
+ }
164
+ // 第 3 遍:灌变量(含 root)
165
+ for (const [scopeId, data] of Object.entries(scopes)) {
166
+ const scope = store.scopes.get(scopeId) ?? store.root;
167
+ for (const [k, v] of Object.entries(data.variables))
168
+ scope.variables.set(k, v);
169
+ }
170
+ return store;
171
+ }
172
+ /** v1 legacy:扁平变量字典全塞 root(向后兼容旧 vars.json)。 */
173
+ static fromJSON(data) {
174
+ return new VariableStore(data);
175
+ }
176
+ }
177
+ // ===== step_id 寻址 + 作用域定位(从 engine-traverse 迁入)=====
178
+ // 开作用域的容器类型:branch 声明聚合输出(统一接口名),各 case 同名填充。
179
+ // branch + case 都开作用域。见 design/exec-engine.md 变量作用域规则 5b / ^anc-exec-container-output
180
+ export const SCOPE_CREATING_TYPES = new Set(['subtask', 'parallel', 'loop', 'branch', 'case']);
181
+ let _stepMapCache = null;
182
+ // 建 step_id → StepNode 反查表(带 spec 身份缓存)。作用域定位/父节点寻址的公共底座。
183
+ export function buildStepMap(spec) {
184
+ if (_stepMapCache && _stepMapCache.spec === spec)
185
+ return _stepMapCache.map;
186
+ const map = new Map();
187
+ const walk = (steps) => {
188
+ for (const step of steps) {
189
+ map.set(step.step_id, step);
190
+ if (hasChildren(step))
191
+ walk(getChildren(step));
192
+ }
193
+ };
194
+ walk(spec.steps ?? []);
195
+ _stepMapCache = { spec, map };
196
+ return map;
197
+ }
198
+ // 给定 step_id,向上找最近的作用域容器 scope_id(写变量的归属作用域)。顶层→'root'。
199
+ export function getWriteScope(stepId, spec) {
200
+ const stepMap = buildStepMap(spec);
201
+ let current = getParentStepId(stepId);
202
+ while (current) {
203
+ const step = stepMap.get(current);
204
+ if (step && SCOPE_CREATING_TYPES.has(step.step_type)) {
205
+ return current;
206
+ }
207
+ current = getParentStepId(current);
208
+ }
209
+ return 'root';
210
+ }
211
+ // ===== 条件真值语义(从 engine-traverse 迁入)=====
212
+ // HopSpec 条件真值判断(branch/case 条件求值、None 传播共用)。
213
+ // null/undefined/false/''/0 为 falsy,其余 truthy。
214
+ export function isTruthy(value) {
215
+ if (value === null || value === undefined)
216
+ return false;
217
+ if (value === false)
218
+ return false;
219
+ if (value === '')
220
+ return false;
221
+ if (value === 0)
222
+ return false;
223
+ return true;
224
+ }
@@ -0,0 +1,260 @@
1
+ export interface SpecAST {
2
+ header: SpecHeader;
3
+ steps?: StepNode[];
4
+ }
5
+ /** SpecHeader:Spec 头部字段结构——title/id/goal/constraints/types/inputs/outputs/config/doc_refs。见 [[spec-ast#^anc-ast-spec-header]] */
6
+ export interface SpecHeader {
7
+ title: string;
8
+ id?: string;
9
+ goal?: string;
10
+ constraints?: string[];
11
+ types?: TypeDecl[];
12
+ inputs?: VarDecl[];
13
+ outputs?: OutputDecl[];
14
+ config?: SpecConfig;
15
+ doc_refs?: DocRef[];
16
+ }
17
+ /** TypeDecl:Types 段复用结构体(名称+字段字典),v1 仅校验字段名存在性。见 [[spec-ast#^anc-type-type-decl]] */
18
+ export interface TypeDecl {
19
+ name: string;
20
+ fields: Record<string, string>;
21
+ }
22
+ /** VarDecl:变量声明(Inputs 段等),含名称、类型、描述与默认值。见 [[spec-ast#^anc-ast-spec-header]] */
23
+ export interface VarDecl {
24
+ name: string;
25
+ type: ValueTypeString | string;
26
+ description?: string;
27
+ default?: unknown;
28
+ }
29
+ /** SpecConfig:Config 段配置项——max_depth/max_retries/Spec 级默认 model,允许扩展键。见 [[spec-ast#^anc-ast-spec-header]] */
30
+ export interface SpecConfig {
31
+ max_depth?: number;
32
+ max_retries?: number;
33
+ model?: string;
34
+ [key: string]: unknown;
35
+ }
36
+ export type ExecutableStepType = 'reason' | 'act' | 'check' | 'confirm' | 'ask' | 'commit' | 'call';
37
+ /** StructuralStepType:8 种结构/控制流步骤类型字面量——由 ExecutionEngine 内部展开,不直接交 LLM。见 [[spec-ast#^anc-ast-step-type]] */
38
+ export type StructuralStepType = 'subtask' | 'parallel' | 'loop' | 'branch' | 'case' | 'break' | 'continue' | 'exit';
39
+ /** StepType:全部 14 种步骤类型联合(可执行 ∪ 结构),BaseStep.step_type 的判别基座。见 [[spec-ast#^anc-ast-step-type]] */
40
+ export type StepType = ExecutableStepType | StructuralStepType;
41
+ /** VarBinding:← 输入绑定(变量名与引用来源,二者同值)。见 [[spec-ast#^anc-ast-base-step]] */
42
+ export interface VarBinding {
43
+ name: string;
44
+ source: string;
45
+ }
46
+ /** SourceLocation:markdown 原文行位置(错误报告与定位用)。见 [[spec-ast#^anc-ast-base-step]] */
47
+ export interface SourceLocation {
48
+ line_start: number;
49
+ line_end: number;
50
+ }
51
+ /** ParamMapping:call 步骤的父子变量搬运映射(from=来源变量名, to=目标变量名),v1 不做类型匹配。见 [[spec-ast#^anc-step-call]] */
52
+ export interface ParamMapping {
53
+ from: string;
54
+ to: string;
55
+ }
56
+ /** BaseStep:所有步骤共享的公共字段基座(step_id/step_type/summary/inputs/outputs/instruction 等)。见 [[spec-ast#^anc-ast-base-step]] */
57
+ export interface BaseStep {
58
+ step_id: string;
59
+ step_type: StepType;
60
+ summary: string;
61
+ inputs?: VarBinding[];
62
+ outputs?: OutputDecl[];
63
+ instruction?: string;
64
+ model_override?: string;
65
+ doc_refs?: DocRef[];
66
+ source_location?: SourceLocation;
67
+ }
68
+ export interface DocRef {
69
+ doc: string;
70
+ section: string;
71
+ }
72
+ /** DocRefFragment:engine 运行期解析出的 doc-ref 章节内容(命中标题/正文/匹配级别),注入前的中间形态。见 [[spec-ast#^anc-type-doc-ref]] */
73
+ export interface DocRefFragment {
74
+ doc: string;
75
+ section: string;
76
+ heading: string;
77
+ content: string;
78
+ matched: 'exact' | 'normalized' | 'fuzzy';
79
+ file_path?: string;
80
+ }
81
+ export interface ReasonStep extends BaseStep {
82
+ step_type: 'reason';
83
+ }
84
+ /** ActStep:act 步骤 AST 节点——执行可逆副作用(限 SandboxConfig 沙箱内),可选 ActBody 结构化 body。见 [[spec-ast#^anc-step-act]] */
85
+ export interface ActStep extends BaseStep {
86
+ step_type: 'act';
87
+ body?: ActBody;
88
+ }
89
+ /** CheckStep:check 步骤 AST 节点——验证判定(is_finally 为 Constraints 可执行化身),固定 bool+text 输出签名。见 [[spec-ast#^anc-step-check]] */
90
+ export interface CheckStep extends BaseStep {
91
+ step_type: 'check';
92
+ is_finally?: boolean;
93
+ }
94
+ /** ConfirmStep:confirm 步骤 AST 节点——纯审批闸门(+→ 仅 bool),可配 require_human 与 response_options。见 [[spec-ast#^anc-step-confirm]] */
95
+ export interface ConfirmStep extends BaseStep {
96
+ step_type: 'confirm';
97
+ require_human?: boolean;
98
+ response_options?: ResponseOption[];
99
+ }
100
+ /** AskStep:ask 步骤 AST 节点——CITL 数据收集(answer 落到 +→ 变量),present_inputs 声明必须完整展示的输入子集。见 [[spec-ast#^anc-step-ask]] */
101
+ export interface AskStep extends BaseStep {
102
+ step_type: 'ask';
103
+ require_human?: boolean;
104
+ present_inputs?: string[];
105
+ }
106
+ /** CommitStep:commit 步骤 AST 节点——不可逆动作(irreversible_action),与 act 同源复用 ActBody,requires_commit 放行且不可重试。见 [[spec-ast#^anc-step-commit]] */
107
+ export interface CommitStep extends BaseStep {
108
+ step_type: 'commit';
109
+ irreversible_action: string;
110
+ body?: ActBody;
111
+ }
112
+ /** CallStep:call 步骤 AST 节点——调用子 Spec(callee_spec_id),param_mapping/output_mapping 搬运父子变量。见 [[spec-ast#^anc-step-call]] */
113
+ export interface CallStep extends BaseStep {
114
+ step_type: 'call';
115
+ callee_spec_id?: string;
116
+ param_mapping?: ParamMapping[];
117
+ output_mapping?: ParamMapping[];
118
+ }
119
+ export interface BranchStep extends BaseStep {
120
+ step_type: 'branch';
121
+ children: CaseStep[];
122
+ }
123
+ /** SubtaskStep:subtask 结构步骤 AST 节点——容器(children),支持 retry 与 adaptive replan。见 [[spec-ast#^anc-step-subtask]] */
124
+ export interface SubtaskStep extends BaseStep {
125
+ step_type: 'subtask';
126
+ retry?: number;
127
+ adaptive?: boolean;
128
+ children: StepNode[];
129
+ }
130
+ /** ParallelStep:parallel 结构步骤 AST 节点——并行容器(children),forEach 表达动态 for-each 展开。见 [[spec-ast#^anc-step-parallel]] */
131
+ export interface ParallelStep extends BaseStep {
132
+ step_type: 'parallel';
133
+ children: StepNode[];
134
+ forEach?: {
135
+ listVar: string;
136
+ itemVar: string;
137
+ };
138
+ }
139
+ /** LoopStep:loop 结构步骤 AST 节点——循环容器(children),max_iterations 限迭代,靠 break/continue/exit 终止。见 [[spec-ast#^anc-step-loop]] */
140
+ export interface LoopStep extends BaseStep {
141
+ step_type: 'loop';
142
+ max_iterations?: number;
143
+ children: StepNode[];
144
+ }
145
+ /** CaseStep:case 结构步骤 AST 节点——branch 下的分支子任务(condition 条件,空为 default),继承 subtask 重试语义。见 [[spec-ast#^anc-step-case]] */
146
+ export interface CaseStep extends BaseStep {
147
+ step_type: 'case';
148
+ condition?: string;
149
+ retry?: number;
150
+ adaptive?: boolean;
151
+ children: StepNode[];
152
+ }
153
+ /** BreakStep:break 控制流步骤 AST 节点——仅 loop 内合法,Engine 检测后终止循环。见 [[spec-ast#^anc-step-break]] */
154
+ export interface BreakStep extends BaseStep {
155
+ step_type: 'break';
156
+ }
157
+ /** ContinueStep:continue 控制流步骤 AST 节点——仅 loop 内合法,Engine 检测后跳过当前迭代。见 [[spec-ast#^anc-step-continue]] */
158
+ export interface ContinueStep extends BaseStep {
159
+ step_type: 'continue';
160
+ }
161
+ /** ExitStep:exit 控制流步骤 AST 节点——任意位置合法,Engine 检测后终止整个 Spec,exit_outputs 为提前退出的输出值。见 [[spec-ast#^anc-step-exit]] */
162
+ export interface ExitStep extends BaseStep {
163
+ step_type: 'exit';
164
+ exit_outputs?: Record<string, unknown>;
165
+ }
166
+ /** StepNode:14 个步骤接口的判别联合(按 step_type 编译期收窄),AST steps 树的节点类型。见 [[spec-ast#^anc-ast-step-type]] */
167
+ export type StepNode = ReasonStep | ActStep | CheckStep | ConfirmStep | AskStep | CommitStep | CallStep | BranchStep | SubtaskStep | ParallelStep | LoopStep | CaseStep | BreakStep | ContinueStep | ExitStep;
168
+ /** ValueTypeString:HopSpec 内置值类型字符串字面量集合(text/bool/number/enum(...)/列表/元组等)。见 [[spec-ast#^anc-ast-spec-header]] */
169
+ export type ValueTypeString = 'text' | 'bool' | 'line' | 'number' | 'int' | 'float' | 'markdown' | 'yaml' | 'prompt' | 'HopSpec' | '[line]' | `[${string}]` | `(${string})` | `enum(${string})`;
170
+ /** OutputDecl:+→ 输出声明(名称、类型、描述、可选初值),用于 SpecHeader.outputs 与 BaseStep.outputs。见 [[spec-ast#^anc-type-output-decl]] */
171
+ export interface OutputDecl {
172
+ name: string;
173
+ type: ValueTypeString | string;
174
+ description: string;
175
+ default?: unknown;
176
+ }
177
+ export interface ActBody {
178
+ statements: ActStatement[];
179
+ source_location?: SourceLocation;
180
+ }
181
+ /** ActStatement:act body 语句联合——赋值/调用/if 分支(禁循环)。见 [[spec-ast#^anc-ast-act-body]] */
182
+ export type ActStatement = AssignStmt | CallStmt | IfStmt;
183
+ /** AssignStmt:act body 赋值语句——target(body 局部或 +→ 输出名)= value 表达式。见 [[spec-ast#^anc-ast-act-body]] */
184
+ export interface AssignStmt {
185
+ type: 'assign';
186
+ target: string;
187
+ value: ActExpr;
188
+ line?: number;
189
+ }
190
+ /** CallStmt:act body 调用语句——把工具/内置调用作为独立副作用语句(如 write)。见 [[spec-ast#^anc-ast-act-body]] */
191
+ export interface CallStmt {
192
+ type: 'call';
193
+ call: CallExpr;
194
+ line?: number;
195
+ }
196
+ /** IfStmt:act body 无推理分支语句——condition 须确定性可求值,elif 展开为 else_body 嵌套。见 [[spec-ast#^anc-ast-act-body]] */
197
+ export interface IfStmt {
198
+ type: 'if';
199
+ condition: ActExpr;
200
+ then_body: ActStatement[];
201
+ else_body?: ActStatement[];
202
+ line?: number;
203
+ }
204
+ /** ActExpr:act body 表达式联合——字面量/变量引用/字段访问/二元/一元/调用。见 [[spec-ast#^anc-ast-act-body]] */
205
+ export type ActExpr = LiteralExpr | VarRefExpr | FieldAccessExpr | BinaryExpr | UnaryExpr | CallExpr;
206
+ /** LiteralExpr:act body 字面量表达式——string/number/bool 值及其 literal_kind。见 [[spec-ast#^anc-ast-act-body]] */
207
+ export interface LiteralExpr {
208
+ type: 'literal';
209
+ value: string | number | boolean;
210
+ literal_kind: 'string' | 'number' | 'bool';
211
+ }
212
+ /** VarRefExpr:act body 变量引用表达式(← 输入 / body 局部 / 上文赋值)。见 [[spec-ast#^anc-ast-act-body]] */
213
+ export interface VarRefExpr {
214
+ type: 'var';
215
+ name: string;
216
+ }
217
+ /** FieldAccessExpr:act body 字段访问表达式——object.field,可链式 a.b.c。见 [[spec-ast#^anc-ast-act-body]] */
218
+ export interface FieldAccessExpr {
219
+ type: 'field';
220
+ object: ActExpr;
221
+ field: string;
222
+ }
223
+ /** BinaryOp:act body 二元运算符集合——算术/比较/逻辑(+ 按操作数分派数加或串接)。见 [[spec-ast#^anc-ast-act-body]] */
224
+ export type BinaryOp = '+' | '-' | '*' | '/' | '==' | '!=' | '<' | '>' | '<=' | '>=' | 'and' | 'or';
225
+ /** BinaryExpr:act body 二元表达式——op 及左右操作数。见 [[spec-ast#^anc-ast-act-body]] */
226
+ export interface BinaryExpr {
227
+ type: 'binary';
228
+ op: BinaryOp;
229
+ left: ActExpr;
230
+ right: ActExpr;
231
+ }
232
+ /** UnaryExpr:act body 一元表达式——not/取负 作用于 operand。见 [[spec-ast#^anc-ast-act-body]] */
233
+ export interface UnaryExpr {
234
+ type: 'unary';
235
+ op: 'not' | '-';
236
+ operand: ActExpr;
237
+ }
238
+ /** CallExpr:act body 调用表达式——callee 必须 ∈ 白名单(内置函数 ∪ ToolProvider 工具名),args 参数列表。见 [[spec-ast#^anc-ast-act-body]] */
239
+ export interface CallExpr {
240
+ type: 'call';
241
+ callee: string;
242
+ args: CallArg[];
243
+ }
244
+ /** CallArg:act body 调用实参——工具调用用命名参数(name 必填),内置函数用位置参数(name 省略)。见 [[spec-ast#^anc-ast-act-body]] */
245
+ export interface CallArg {
246
+ name?: string;
247
+ value: ActExpr;
248
+ }
249
+ /** StepSummary:步骤精简摘要(step_id/step_type/summary/输出名列表),供 replan 等场景引用。见 [[spec-ast]] */
250
+ export interface StepSummary {
251
+ step_id: string;
252
+ step_type: StepType;
253
+ summary: string;
254
+ outputs: string[];
255
+ }
256
+ export interface ResponseOption {
257
+ value: string;
258
+ label: string;
259
+ description?: string;
260
+ }
@@ -0,0 +1,4 @@
1
+ // @module: spec-ast ^anc-struct-spec-ast
2
+ // AST 类型契约——最稳的契约层(语言身份)。SpecAST/14 步骤类型/ActBody 表达式/DocRef + 共享辅助类型。
3
+ // 拆自原 types.ts(按稳定性,见 design/spec-ast.md ^anc-struct-spec-ast);types.ts 保留为 barrel re-export。
4
+ export {};