@istuen/pt 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 (166) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +219 -0
  3. package/dist/agent/api-bridge.d.ts +8 -0
  4. package/dist/agent/api-bridge.js +83 -0
  5. package/dist/agent/index.d.ts +2 -0
  6. package/dist/agent/index.js +3 -0
  7. package/dist/agent/pi-adapter.d.ts +35 -0
  8. package/dist/agent/pi-adapter.js +251 -0
  9. package/dist/agent/registry.d.ts +4 -0
  10. package/dist/agent/registry.js +40 -0
  11. package/dist/asset-health.d.ts +50 -0
  12. package/dist/asset-health.js +267 -0
  13. package/dist/asset-pack/loader.d.ts +47 -0
  14. package/dist/asset-pack/loader.js +121 -0
  15. package/dist/asset-pack/manifest.d.ts +23 -0
  16. package/dist/asset-pack/manifest.js +96 -0
  17. package/dist/asset-pack/md-file-pack.d.ts +41 -0
  18. package/dist/asset-pack/md-file-pack.js +153 -0
  19. package/dist/asset-pack/validate.d.ts +55 -0
  20. package/dist/asset-pack/validate.js +131 -0
  21. package/dist/builtin/assets/blueprints/dev-knowledge.blueprint.yaml +13 -0
  22. package/dist/builtin/assets/domains/agent-info.md +15 -0
  23. package/dist/builtin/assets/domains/authoring.md +201 -0
  24. package/dist/builtin/assets/domains/pack-repair.md +47 -0
  25. package/dist/builtin/assets/domains/project-analysis.md +52 -0
  26. package/dist/builtin/assets/domains/usage.md +81 -0
  27. package/dist/builtin/assets/domains/user-info.md +15 -0
  28. package/dist/builtin/assets/profiles/guide.profile.md +28 -0
  29. package/dist/commands.d.ts +69 -0
  30. package/dist/commands.js +344 -0
  31. package/dist/compile/agent-context.d.ts +48 -0
  32. package/dist/compile/agent-context.js +423 -0
  33. package/dist/compile/index.d.ts +1 -0
  34. package/dist/compile/index.js +5 -0
  35. package/dist/compile/resolve-use.d.ts +36 -0
  36. package/dist/compile/resolve-use.js +171 -0
  37. package/dist/compile/type-guards.d.ts +29 -0
  38. package/dist/compile/type-guards.js +107 -0
  39. package/dist/config.d.ts +31 -0
  40. package/dist/config.js +133 -0
  41. package/dist/constants.d.ts +52 -0
  42. package/dist/constants.js +81 -0
  43. package/dist/diagnostics.d.ts +14 -0
  44. package/dist/diagnostics.js +29 -0
  45. package/dist/index.d.ts +2 -0
  46. package/dist/index.js +838 -0
  47. package/dist/injection-status.d.ts +45 -0
  48. package/dist/injection-status.js +134 -0
  49. package/dist/log.d.ts +64 -0
  50. package/dist/log.js +139 -0
  51. package/dist/manual-session.d.ts +24 -0
  52. package/dist/manual-session.js +152 -0
  53. package/dist/manual-track.d.ts +35 -0
  54. package/dist/manual-track.js +107 -0
  55. package/dist/parse/blueprint.d.ts +5 -0
  56. package/dist/parse/blueprint.js +59 -0
  57. package/dist/parse/domain-renderers.d.ts +8 -0
  58. package/dist/parse/domain-renderers.js +115 -0
  59. package/dist/parse/domain.d.ts +7 -0
  60. package/dist/parse/domain.js +69 -0
  61. package/dist/parse/index.d.ts +9 -0
  62. package/dist/parse/index.js +223 -0
  63. package/dist/parse/profile.d.ts +18 -0
  64. package/dist/parse/profile.js +117 -0
  65. package/dist/parse/ref-resolver.d.ts +63 -0
  66. package/dist/parse/ref-resolver.js +174 -0
  67. package/dist/parse/shared.d.ts +76 -0
  68. package/dist/parse/shared.js +273 -0
  69. package/dist/profile-persist.d.ts +22 -0
  70. package/dist/profile-persist.js +53 -0
  71. package/dist/render/cache.d.ts +15 -0
  72. package/dist/render/cache.js +135 -0
  73. package/dist/render/index.d.ts +3 -0
  74. package/dist/render/index.js +14 -0
  75. package/dist/render/session-inject.d.ts +5 -0
  76. package/dist/render/session-inject.js +24 -0
  77. package/dist/render/turn-inject.d.ts +36 -0
  78. package/dist/render/turn-inject.js +248 -0
  79. package/dist/schema.d.ts +448 -0
  80. package/dist/schema.js +45 -0
  81. package/dist/session.d.ts +82 -0
  82. package/dist/session.js +102 -0
  83. package/dist/slog.d.ts +3 -0
  84. package/dist/slog.js +27 -0
  85. package/dist/transpile.d.ts +34 -0
  86. package/dist/transpile.js +220 -0
  87. package/dist/verify/file-hash.d.ts +2 -0
  88. package/dist/verify/file-hash.js +30 -0
  89. package/dist/verify/fs-content-match.d.ts +2 -0
  90. package/dist/verify/fs-content-match.js +26 -0
  91. package/dist/verify/fs-exists.d.ts +2 -0
  92. package/dist/verify/fs-exists.js +13 -0
  93. package/dist/verify/fs-not-exists.d.ts +2 -0
  94. package/dist/verify/fs-not-exists.js +13 -0
  95. package/dist/verify/git-status-clean.d.ts +2 -0
  96. package/dist/verify/git-status-clean.js +19 -0
  97. package/dist/verify/index.d.ts +7 -0
  98. package/dist/verify/index.js +46 -0
  99. package/dist/verify/lint-check.d.ts +2 -0
  100. package/dist/verify/lint-check.js +17 -0
  101. package/dist/verify/read-stderr.d.ts +5 -0
  102. package/dist/verify/read-stderr.js +20 -0
  103. package/dist/verify/ref-check.d.ts +13 -0
  104. package/dist/verify/ref-check.js +88 -0
  105. package/dist/verify/test-pass.d.ts +2 -0
  106. package/dist/verify/test-pass.js +17 -0
  107. package/dist/verify/ts-compiles.d.ts +2 -0
  108. package/dist/verify/ts-compiles.js +17 -0
  109. package/package.json +62 -0
  110. package/src/agent/api-bridge.ts +105 -0
  111. package/src/agent/index.ts +4 -0
  112. package/src/agent/pi-adapter.ts +326 -0
  113. package/src/agent/registry.ts +44 -0
  114. package/src/asset-health.ts +327 -0
  115. package/src/asset-pack/loader.ts +141 -0
  116. package/src/asset-pack/manifest.ts +118 -0
  117. package/src/asset-pack/md-file-pack.ts +202 -0
  118. package/src/asset-pack/validate.ts +186 -0
  119. package/src/builtin/assets/blueprints/dev-knowledge.blueprint.yaml +13 -0
  120. package/src/builtin/assets/domains/agent-info.md +15 -0
  121. package/src/builtin/assets/domains/authoring.md +201 -0
  122. package/src/builtin/assets/domains/pack-repair.md +47 -0
  123. package/src/builtin/assets/domains/project-analysis.md +52 -0
  124. package/src/builtin/assets/domains/usage.md +81 -0
  125. package/src/builtin/assets/domains/user-info.md +15 -0
  126. package/src/builtin/assets/profiles/guide.profile.md +28 -0
  127. package/src/commands.ts +405 -0
  128. package/src/compile/agent-context.ts +487 -0
  129. package/src/compile/index.ts +5 -0
  130. package/src/compile/resolve-use.ts +208 -0
  131. package/src/compile/type-guards.ts +132 -0
  132. package/src/config.ts +154 -0
  133. package/src/constants.ts +104 -0
  134. package/src/diagnostics.ts +36 -0
  135. package/src/index.ts +1028 -0
  136. package/src/injection-status.ts +155 -0
  137. package/src/log.ts +173 -0
  138. package/src/manual-session.ts +190 -0
  139. package/src/manual-track.ts +127 -0
  140. package/src/parse/blueprint.ts +82 -0
  141. package/src/parse/domain-renderers.ts +120 -0
  142. package/src/parse/domain.ts +78 -0
  143. package/src/parse/index.ts +266 -0
  144. package/src/parse/profile.ts +139 -0
  145. package/src/parse/ref-resolver.ts +198 -0
  146. package/src/parse/shared.ts +331 -0
  147. package/src/profile-persist.ts +60 -0
  148. package/src/render/cache.ts +150 -0
  149. package/src/render/index.ts +14 -0
  150. package/src/render/session-inject.ts +26 -0
  151. package/src/render/turn-inject.ts +278 -0
  152. package/src/schema.ts +542 -0
  153. package/src/session.ts +190 -0
  154. package/src/slog.ts +32 -0
  155. package/src/transpile.ts +302 -0
  156. package/src/verify/file-hash.ts +29 -0
  157. package/src/verify/fs-content-match.ts +28 -0
  158. package/src/verify/fs-exists.ts +14 -0
  159. package/src/verify/fs-not-exists.ts +17 -0
  160. package/src/verify/git-status-clean.ts +23 -0
  161. package/src/verify/index.ts +57 -0
  162. package/src/verify/lint-check.ts +21 -0
  163. package/src/verify/read-stderr.ts +24 -0
  164. package/src/verify/ref-check.ts +118 -0
  165. package/src/verify/test-pass.ts +18 -0
  166. package/src/verify/ts-compiles.ts +21 -0
@@ -0,0 +1,202 @@
1
+ // src/asset-pack/md-file-pack.ts — AssetPack 的文件系统实现(v15.x PR1)
2
+ //
3
+ // 设计源:.pt/docs/designs/pt-asset-pack.md §2.3(MdFilePack)
4
+ //
5
+ // 与 src/parse/{domain,blueprint,profile}.ts 现有 parser 复用,不重写 parse 算法。
6
+ // AssetPack 只是把"目录"封装成可命名、可版本化的单元。
7
+ //
8
+ // PR1 简化(按 PR1.2 + PR1.6 文档):
9
+ // - name 由构造传入(reserved 固定名 "prj"/"gbl"/"pt",PR4 接通后 settings pack 走 basename 兜底)
10
+ // - version / description 固定占位(PR2 接通 manifest 后从 manifest 读)
11
+ // - loadXxx 内 parse 失败的文件返 null 后 filter 掉——**不**调 reportWarn/reportError
12
+ // (那些是 adapterCtx 依赖;PR1 的 MdFilePack 内部错误由 validatePack 层捕获,见 PR1.6)
13
+ // - loadXxx 不接 adapterCtx 参数(AssetPack interface 不暴露)——
14
+ // parseProfile 内 modName 解析失败的 warn 通道在本 PR 阶段丢失(已知 PR1 简化,
15
+ // 不影响 pack 加载本身;后续 PR 可选把 adapterCtx 透传回 parseProfile)
16
+
17
+ import { basename as pathBasename } from "node:path";
18
+ import { readdir } from "node:fs/promises";
19
+ import { join } from "node:path";
20
+ import { SUFFIX_BLUEPRINT_YAML, SUFFIX_MD } from "../constants.js";
21
+ import { errMsg, reportError } from "../diagnostics.js";
22
+ import type {
23
+ AssetPack,
24
+ Blueprint,
25
+ Domain,
26
+ PackSource,
27
+ Profile,
28
+ SourceAdapterContext,
29
+ } from "../schema.js";
30
+ import { parseBlueprint } from "../parse/blueprint.js";
31
+ import { parseDomain } from "../parse/domain.js";
32
+ import { parseProfile } from "../parse/profile.js";
33
+ import { parseManifest } from "./manifest.js";
34
+
35
+ /**
36
+ * v15.x PR2:文件系统 Pack 实现——读 <rootDir>/{domains,blueprints,profiles}/。
37
+ * 与 src/parse/{domain,blueprint,profile}.ts 现有 parser 共用,不重写 parse 算法。
38
+ *
39
+ * PR2:构造从 sync 改 async(读 manifest),走 `MdFilePack.create()` 工厂方法。
40
+ * name 解析优先级(§2.4.2):
41
+ * - reserved pack(source=project/global/builtin)→ 固定名 prj/gbl/pt,跳过 manifest
42
+ * - 显式 pack + 合法 manifest.name → manifest.name
43
+ * - 隐式 pack(无 manifest / manifest 无 name / name 校验失败)→ basename 兜底
44
+ *
45
+ * PR1 补丁(S2 修复):构造可选接 adapterCtx——loadXxx 内部 parse 失败时调
46
+ * reportError,恢复 v10.x 旧 loadDir 行为的"错误可见性"。未传则 fallback
47
+ * console.error(diagnostics.ts:reportError 三通道 fallback)。
48
+ */
49
+ export class MdFilePack implements AssetPack {
50
+ readonly name: string;
51
+ readonly version: string; // PR2:从 manifest 读(缺失则 "0.0.0")
52
+ readonly rootDir: string;
53
+ readonly description: string | undefined; // PR2:从 manifest 读(缺失则 undefined)
54
+ readonly source: PackSource;
55
+ /** adapterCtx 可选——parse 失败时调 reportError 走 notify + log 通道。 */
56
+ private readonly adapterCtx: SourceAdapterContext | undefined;
57
+
58
+ private constructor(args: {
59
+ rootDir: string;
60
+ name: string;
61
+ version: string;
62
+ description?: string;
63
+ source: PackSource;
64
+ adapterCtx?: SourceAdapterContext;
65
+ }) {
66
+ this.rootDir = args.rootDir;
67
+ this.name = args.name;
68
+ this.version = args.version;
69
+ this.description = args.description;
70
+ this.source = args.source;
71
+ this.adapterCtx = args.adapterCtx;
72
+ }
73
+
74
+ /** 位置别名退化表(v15.x §2.4.2 缺口 1-b):reserved pack 无 manifest 时 name 退化到位置别名。
75
+ * 用途:back-compat——今天无 manifest 的项目 pack.name 仍是 prj/gbl/pt,行为等价。 */
76
+ private static readonly RESERVED_FALLBACK_NAME: ReadonlyMap<PackSource, string> = new Map([
77
+ ["project", "prj"],
78
+ ["global", "gbl"],
79
+ ["builtin", "pt"],
80
+ ]);
81
+
82
+ /** PR2(v15.x §2.4.2 双层语义):工厂方法(async,读 manifest)。
83
+ * 所有 pack 都走 manifest 解析;reserved pack 无 manifest 时 name 退化到位置别名(back-compat)。
84
+ * - manifest.name 优先(身份 alias)
85
+ * - reserved pack 无 manifest → 退化到 RESERVED_FALLBACK_NAME.get(source)
86
+ * - 非 reserved pack 无 manifest → basename 兜底 */
87
+ static async create(args: {
88
+ rootDir: string;
89
+ source: PackSource;
90
+ adapterCtx?: SourceAdapterContext;
91
+ }): Promise<MdFilePack> {
92
+ const manifest = await parseManifest(args.rootDir);
93
+ const dirName = pathBasename(args.rootDir);
94
+
95
+ // manifest warnings 上抛 notify(不阻断——parseManifest 已容错)
96
+ if (manifest.warnings.length > 0 && args.adapterCtx?.notify) {
97
+ args.adapterCtx.notify(
98
+ `Pt: pack "${dirName}" manifest 警告:${manifest.warnings.join("; ")}`,
99
+ "warning"
100
+ );
101
+ }
102
+
103
+ // name 解析优先级(§2.4.2):
104
+ // 1. manifest.name(身份 alias 优先)
105
+ // 2. reserved pack 无 manifest → 退化到位置别名(prj/gbl/pt,back-compat)
106
+ // 3. 非 reserved 无 manifest → basename 兜底
107
+ const fallbackName = MdFilePack.RESERVED_FALLBACK_NAME.get(args.source) ?? dirName;
108
+ const name = manifest.name ?? fallbackName;
109
+
110
+ return new MdFilePack({
111
+ rootDir: args.rootDir,
112
+ name,
113
+ version: manifest.version ?? "0.0.0",
114
+ description: manifest.description,
115
+ source: args.source,
116
+ adapterCtx: args.adapterCtx,
117
+ });
118
+ }
119
+
120
+ async loadDomains(): Promise<Domain[]> {
121
+ const dir = join(this.rootDir, "domains");
122
+ return loadDomainsRecursive(dir, this.adapterCtx);
123
+ }
124
+
125
+ async loadBlueprints(): Promise<Blueprint[]> {
126
+ const dir = join(this.rootDir, "blueprints");
127
+ return loadDir(dir, SUFFIX_BLUEPRINT_YAML, (f) => parseBlueprint(dir, f), this.adapterCtx);
128
+ }
129
+
130
+ async loadProfiles(): Promise<Profile[]> {
131
+ const dir = join(this.rootDir, "profiles");
132
+ const profiles = await loadDir(
133
+ dir,
134
+ SUFFIX_MD,
135
+ (f) => parseProfile(dir, f, this.adapterCtx),
136
+ this.adapterCtx
137
+ );
138
+ // v15.x PR3(§4.4.1):MdFilePack 加载时给每个 Profile 打上 sourcePack——parseRef 不限定 ref 自动绑定用。
139
+ for (const p of profiles) {
140
+ p.sourcePack = this.name;
141
+ }
142
+ return profiles;
143
+ }
144
+ }
145
+
146
+ // ==================== 共享加载辅助(PR1 内部,未来抽到独立模块) ====================
147
+
148
+ /** 顶层目录加载:只扫顶层文件(Blueprint/Profile 不递归——避免破坏现有结构)。
149
+ * parse 失败的文件:调 reportError 上抛 notify + log(恢复 v10.x 旧 loadDir 行为,
150
+ * PR1 补丁 S2 修复),未传 adapterCtx 时 fallback console.error。
151
+ * 目录不存在返空数组(与现有 loadDir 行为一致)。 */
152
+ async function loadDir<T>(
153
+ dir: string,
154
+ suffix: string,
155
+ parser: (f: string) => Promise<T>,
156
+ adapterCtx: SourceAdapterContext | undefined
157
+ ): Promise<T[]> {
158
+ let files: string[];
159
+ try {
160
+ files = (await readdir(dir)).filter((f) => f.endsWith(suffix));
161
+ } catch {
162
+ return []; // 目录不存在返空
163
+ }
164
+ const results: Array<T | null> = await Promise.all(
165
+ files.map(async (f): Promise<T | null> => {
166
+ try {
167
+ return await parser(f);
168
+ } catch (e) {
169
+ reportError(adapterCtx, `parse ${dir}/${f} failed: ${errMsg(e)}`, { file: f });
170
+ return null;
171
+ }
172
+ })
173
+ );
174
+ return results.filter((r): r is T => r !== null);
175
+ }
176
+
177
+ /** 递归加载 domains/ 下所有 .md(多级目录支持)。
178
+ * Node.js 20+ readdir({ recursive: true }) 跨平台统一返回 POSIX '/' 分隔路径。
179
+ * Domain.name = POSIX 相对路径去 .md(支持 "workflow/dev-workflow" 等多级命名)。
180
+ * parse 失败的文件:调 reportError 上抛(PR1 补丁 S2)。 */
181
+ async function loadDomainsRecursive(
182
+ dir: string,
183
+ adapterCtx: SourceAdapterContext | undefined
184
+ ): Promise<Domain[]> {
185
+ let files: string[];
186
+ try {
187
+ files = (await readdir(dir, { recursive: true })).filter((f) => f.endsWith(SUFFIX_MD));
188
+ } catch {
189
+ return []; // 目录不存在返空
190
+ }
191
+ const results: Array<Domain | null> = await Promise.all(
192
+ files.map(async (relPath) => {
193
+ try {
194
+ return await parseDomain(dir, relPath);
195
+ } catch (e) {
196
+ reportError(adapterCtx, `parse ${dir}/${relPath} failed: ${errMsg(e)}`, { file: relPath });
197
+ return null;
198
+ }
199
+ })
200
+ );
201
+ return results.filter((r): r is Domain => !!r);
202
+ }
@@ -0,0 +1,186 @@
1
+ // src/asset-pack/validate.ts — Pack 校验(v15.x PR1)
2
+ //
3
+ // 设计源:.pt/docs/designs/pt-asset-pack.md §6.7.2(两层校验)/ §6.7.7(不抛异常)
4
+ //
5
+ // 关键纪律:validatePack 永远返结果对象,不抛异常——失败不阻断加载链。
6
+ // 错误收集到 errors[] / warnings[],返 ok: boolean。
7
+ //
8
+ // 层 1(pack 结构):rootDir 存在 + 至少一个 asset 子目录
9
+ // 层 2(asset 解析):loadDomains/loadBlueprints/loadProfiles 不抛即过
10
+ //
11
+ // PR1 简化:
12
+ // - 不做 manifest 校验(PR2)
13
+ // - 不做 pack 内同 name asset 冲突检测(PR2 与 manifest 校验一起做)
14
+ // - 不做 settings pack 之间冲突报错(PR4 接通 settings 加载时一起做)
15
+
16
+ import { existsSync } from "node:fs";
17
+ import { join } from "node:path";
18
+ import { errMsg } from "../diagnostics.js";
19
+ import type { AssetPack } from "../schema.js";
20
+
21
+ /** v15.x §2.4.4(位置 alias 表):reserved pack 的位置别名。reserved pack 才有,非 reserved 为 undefined。
22
+ * UI 显示层用——reserved 显位置别名,settings 显 pack 名(§4.4.4 双层语义)。 */
23
+ const RESERVED_ALIAS: ReadonlyMap<AssetPack["source"], "prj" | "gbl" | "pt"> = new Map([
24
+ ["project", "prj"],
25
+ ["global", "gbl"],
26
+ ["builtin", "pt"],
27
+ ]);
28
+
29
+ /** 校验结果(§6.7.7)。validatePack 永远返结果对象,不抛异常。 */
30
+ export interface ValidationResult {
31
+ /** Pack 名(来源 pack.name——manifest.name 或退化别名) */
32
+ pack: string;
33
+ /** Pack 来源类型 */
34
+ source: AssetPack["source"];
35
+ /** v15.x §4.4.4(缺口 4):reserved pack 的位置别名(prj/gbl/pt),非 reserved 为 undefined。
36
+ * UI 显示层用——reserved 显位置别名,settings 显 pack 名。 */
37
+ reservedAlias?: "prj" | "gbl" | "pt";
38
+ /** 整体是否可用 */
39
+ ok: boolean;
40
+ /** 致命问题(pack 不可用) */
41
+ errors: PackIssue[];
42
+ /** 非致命(pack 可用但有隐患——目前未使用,预留扩展) */
43
+ warnings: PackIssue[];
44
+ /** v15.x PR2(§6.7.6 展示用):pack version。 */
45
+ version: string;
46
+ /** v15.x PR2(§6.7.6 展示用):pack description(可选)。 */
47
+ description?: string;
48
+ /** v15.x PR2(§6.7.6 展示用):pack rootDir。 */
49
+ rootDir: string;
50
+ }
51
+
52
+ /** 单条校验问题。code 机器可读,msg 人类可读,hint 修复建议。 */
53
+ export interface PackIssue {
54
+ /** 机器可读错误码(如 "dir-not-found") */
55
+ code: string;
56
+ /** 人类可读 */
57
+ msg: string;
58
+ /** 修复建议(可选) */
59
+ hint?: string;
60
+ }
61
+
62
+ /**
63
+ * 两层校验(§6.7.2):
64
+ * 层 1 pack 结构:rootDir 存在 + 至少一个 asset 子目录
65
+ * 层 2 asset 解析:loadDomains/loadBlueprints/loadProfiles 不抛即过
66
+ * (parse 失败的文件已在 MdFilePack 内部 filter 掉,不阻断 pack 加载)
67
+ *
68
+ * 永远返结果对象,不抛异常(§6.7.7)——失败不阻断加载链。
69
+ */
70
+ export async function validatePack(pack: AssetPack): Promise<ValidationResult> {
71
+ const errors: PackIssue[] = [];
72
+ const warnings: PackIssue[] = [];
73
+
74
+ // 层 1:pack 结构——目录存在
75
+ if (!existsSync(pack.rootDir)) {
76
+ errors.push({
77
+ code: "dir-not-found",
78
+ msg: `pack 目录不存在: ${pack.rootDir}`,
79
+ hint: "检查路径配置,或创建该目录(参考 /manual:pack-repair)",
80
+ });
81
+ return {
82
+ pack: pack.name,
83
+ source: pack.source,
84
+ reservedAlias: RESERVED_ALIAS.get(pack.source),
85
+ ok: false,
86
+ errors,
87
+ warnings,
88
+ version: pack.version,
89
+ rootDir: pack.rootDir,
90
+ };
91
+ }
92
+
93
+ // 层 1:pack 结构——至少一个 asset 子目录
94
+ const hasDomains = existsSync(join(pack.rootDir, "domains"));
95
+ const hasBlueprints = existsSync(join(pack.rootDir, "blueprints"));
96
+ const hasProfiles = existsSync(join(pack.rootDir, "profiles"));
97
+ if (!hasDomains && !hasBlueprints && !hasProfiles) {
98
+ errors.push({
99
+ code: "no-asset-subdir",
100
+ msg: `pack "${pack.name}" 无任何 asset 子目录(domains/blueprints/profiles)`,
101
+ hint: "至少创建一个 asset 子目录(参考 /manual:pack-repair)",
102
+ });
103
+ return {
104
+ pack: pack.name,
105
+ source: pack.source,
106
+ reservedAlias: RESERVED_ALIAS.get(pack.source),
107
+ ok: false,
108
+ errors,
109
+ warnings,
110
+ version: pack.version,
111
+ rootDir: pack.rootDir,
112
+ };
113
+ }
114
+
115
+ // 层 2:asset 解析 + pack 内一致性(§6.7.2 补全)
116
+ try {
117
+ const domains = await pack.loadDomains();
118
+ const blueprints = await pack.loadBlueprints();
119
+ const profiles = await pack.loadProfiles();
120
+ // v15.x PR2(§6.7.2 层 2):同 Pack 内同 name asset 冲突检测
121
+ checkIntraPackConflicts("domain", domains, errors);
122
+ checkIntraPackConflicts("blueprint", blueprints, errors);
123
+ checkIntraPackConflicts("profile", profiles, errors);
124
+ } catch (e) {
125
+ errors.push({
126
+ code: "load-failed",
127
+ msg: `pack "${pack.name}" 加载失败: ${errMsg(e)}`,
128
+ hint: "检查资产文件格式(参考 /manual:pack-repair)",
129
+ });
130
+ }
131
+
132
+ // pack 内一致性(同 name asset 冲突)—— v15.x PR2 在层 2 已做(checkIntraPackConflicts)
133
+
134
+ return {
135
+ pack: pack.name,
136
+ source: pack.source,
137
+ reservedAlias: RESERVED_ALIAS.get(pack.source),
138
+ ok: errors.length === 0,
139
+ errors,
140
+ warnings,
141
+ version: pack.version,
142
+ description: pack.description,
143
+ rootDir: pack.rootDir,
144
+ };
145
+ }
146
+
147
+ /** v15.x PR2(§6.7.2 层 2):同 Pack 内同 name asset 冲突检测。
148
+ * 重复 name 报错——同 Pack 内 asset name 必须唯一。
149
+ * 不检测跨 Pack 冲突(那是 dedupByNameN 的职责,前者赢)。 */
150
+ function checkIntraPackConflicts<T extends { name: string }>(
151
+ kind: string,
152
+ assets: T[],
153
+ errors: PackIssue[]
154
+ ): void {
155
+ const seen = new Map<string, number>();
156
+ for (const a of assets) {
157
+ const count = seen.get(a.name) ?? 0;
158
+ if (count > 0) {
159
+ errors.push({
160
+ code: "intra-pack-conflict",
161
+ msg: `pack 内 ${kind} "${a.name}" 重复(${count + 1} 次)`,
162
+ hint: `同 Pack 内 ${kind} name 必须唯一——重命名或删除重复文件`,
163
+ });
164
+ }
165
+ seen.set(a.name, count + 1);
166
+ }
167
+ }
168
+
169
+ /**
170
+ * v15.x PR1(§7.5 + §7.5.1):判断是否该弹全局 Pack 初始化引导。
171
+ * pure helper——抽出来让 session_start handler 简洁,也便于单元测试。
172
+ *
173
+ * 约束:TTY + 目录不存在 + 首次(每个 session 只提示一次)+ 非 CI + 非 PT_NO_GUIDE 禁用。
174
+ * 调用方负责检查 isFirstRun(读 session state.globalPackGuideShown)和传 env。
175
+ */
176
+ export function shouldPromptGlobalPackGuide(args: {
177
+ isTTY: boolean;
178
+ globalPackExists: boolean;
179
+ isFirstRun: boolean;
180
+ isCi: boolean;
181
+ guideDisabled: boolean;
182
+ }): boolean {
183
+ return (
184
+ args.isTTY && !args.globalPackExists && args.isFirstRun && !args.isCi && !args.guideDisabled
185
+ );
186
+ }
@@ -0,0 +1,13 @@
1
+ name: dev-knowledge
2
+ groups:
3
+ - name: 会话背景
4
+ inject: session
5
+ mode: hybrid
6
+ # v9.1(modules-to-profile 迁移):modules 字段已删除——由 Profile `### Modules` 提供
7
+ # Phase term-P8:会话参与者信息段——user-info Domain 的 H3 项(user-profile/pt-goal/collab-mode 等)走 Participant
8
+ - name: 触发索引
9
+ inject: session
10
+ # 桥接 Session↔Turn:把有什么手册、何时查作为索引注入,每轮 LLM 可见
11
+ - name: 参考手册
12
+ inject: turn
13
+ # Phase term-P9.2:Manual 拆三段——Rules / Flows / Checklists
@@ -0,0 +1,15 @@
1
+ ---
2
+ name: agent-info
3
+ ---
4
+
5
+ # agent-info
6
+
7
+ ## Agent
8
+ ### role
9
+ - desc: 你是 Pt 引导下的编码助手——理解 Pt 资产结构,帮用户创作/修改 Domain 与 Profile
10
+
11
+ ### collaboration
12
+ - desc: 用户=需求方+决策者(主导方向);你=方案推理者+可行性验证者+代码/文档实现者
13
+
14
+ ### boundaries
15
+ - desc: 不自行发挥架构方向;改资产前先读 authoring 的格式规范;改完删 cache 重编译验证
@@ -0,0 +1,201 @@
1
+ ---
2
+ name: authoring
3
+ ---
4
+
5
+ # authoring
6
+
7
+ ## Trigger
8
+ ### authoring-trigger
9
+ - desc: 创作/修改 Pt 资产 md 时参考;含 Pt Domain/Blueprint/Pt Profile 格式(v9.1+) + 创建流程 + 角色隔离配置
10
+ - hint: /manual:authoring 查看完整创作手册
11
+
12
+ ## Scene
13
+
14
+ ### domain-format
15
+ - desc: frontmatter(name: 域路径名——根目录写裸名 `user-info`,多级目录写 path 形式 `workflow/dev-workflow`,与加载路径一致;无 type 字段——Module/H2 段名即 schema 选择器)+ Module(## Scene / ## Trigger / ## Rules / ## Flows / ## Checklists / ## Participant / ## User / ## Agent / ...,按需写)+ H3 项(### 项名 + - desc: 描述 / - path: 路径 / - check: 规则 / - fields: 字段清单 / - note: 补充说明)。文件放 .pt/assets/domains/<name>.md 或 .pt/assets/domains/<subdir>/<name>.md。
16
+
17
+ ### blueprint-format
18
+ - desc: YAML 格式(.blueprint.yaml)。字段:name + groups(聚合组列表,每个含 name + inject: session/turn + mode)。**v9.1+:Blueprint 不带 modules 字段**——Blueprint 退化为插槽契约(声明有哪些插槽 + inject + mode),modules 由 Profile H2 下的 ### Modules 列表填。无 agent 字段(Blueprint Agent-agnostic,运行时硬编码 "pi")。无 Compilation 段(cacheDir 用 CACHE_DIR 常量)。文件放 .pt/assets/blueprints/<name>.blueprint.yaml(v9.1+ 可省略——`src/parse/index.ts` 的 `dedupByName` 机制保证项目优先 + 内建补充,profile 引 `blueprint: dev-knowledge` 自动 fallback 到 builtin)。
19
+
20
+ ### profile-format
21
+ - desc: frontmatter(name + blueprint: 引用名 + domains: [全局 Domain 列表,**多级目录用 path 形式**如 `workflow/dev-workflow`,自动分发到所有聚合组])+ H2 聚合组实例化(## 聚合组名 与 Blueprint.groups[].name 同名)+ H3 段下两类追加列表:(a) `### Domains` 追加到本聚合组的 Domain 名列表;(b) `### Modules` 本插槽填的 modName 列表(v9.1+)。**v9.1+ 的 modules 形态 2 种**:段名(`Scene` / `User`)和 段.项(`Agent.senior-developer`),无形态 3。domains 顺序影响 LLM attention——身份类放前,约束类放后。文件放 .pt/assets/profiles/<name>.profile.md。
22
+
23
+ ### profile-modules-section
24
+ - desc: v9.1+ Profile H2 段下 ### Modules 段填法——按 modName 2 形态逐行列出本插槽的 modules。**形态 1:段名**(整段聚合,跨所有引用域)——例 `- Scene`(所有引用域的 Scene 段都进)。**形态 2:段.项**(精确选 H3 项)——例 `- Agent.agent-role-senior-developer`(agent-info 段下 senior-developer 项进)。modName 解析失败(段名不在 `KNOWN_SECTION_NAMES` 集合)→ log warn 跳过。**解析规则**:`Scene` / `User.user-profile` / `Trigger.authoring-trigger` 都合法;`my-domain:Scene.foo` 这种形态 3 形式不合法——限定到单 domain 用专用段名(`User` / `Agent`)。
25
+
26
+ ### profile-section-namespace
27
+ - desc: 段名 = 命名空间(v9.1+)——通用段(`Scene` / `Trigger` / `Rules` / `Flows` / `Checklists`)跨 domain 通用;专用段(`User` / `Agent`)限定到单 domain(`user-info` 用 `User`、`agent-info` 用 `Agent`)。**Profile 角色隔离的核心机制**——专用段名让 profile 可以"只选自己需要的身份角色"而不影响其他 profile。例:pt-arch 与 pt-dev 共享同一 agent-info Domain(6 个 H3 项:architect / senior-developer / qa-engineer / code-reviewer / devops-engineer / active-role-rule),但 pt-arch `### Modules: [Agent.agent-role-architect, Agent.active-role-rule]` 只看到 architect + active-role-rule;pt-dev `### Modules: [Agent.agent-role-senior-developer, Agent.agent-role-qa-engineer, Agent.agent-role-code-reviewer, Agent.active-role-rule]` 只看到 dev 3 角色 + active-role-rule。
28
+
29
+ ### profile-role-isolation
30
+ - desc: v9.1+ Profile 角色隔离配置示例(共享 agent-info Domain,各 profile 只看自己角色 + active-role-rule):
31
+ - sample-pt-arch: |
32
+ ## 会话背景
33
+ ### Modules
34
+ - Scene
35
+ - User
36
+ - Agent.agent-role-architect
37
+ - Agent.active-role-rule
38
+ - sample-pt-design: |
39
+ ## 会话背景
40
+ ### Modules
41
+ - Scene
42
+ - User
43
+ - Agent.agent-role-architect
44
+ - Agent.active-role-rule
45
+ - sample-pt-dev: |
46
+ ## 会话背景
47
+ ### Modules
48
+ - Scene
49
+ - User
50
+ - Agent.agent-role-senior-developer
51
+ - Agent.agent-role-qa-engineer
52
+ - Agent.agent-role-code-reviewer
53
+ - Agent.active-role-rule
54
+ - sample-pt-devops: |
55
+ ## 会话背景
56
+ ### Modules
57
+ - Scene
58
+ - User
59
+ - Agent.agent-role-devops-engineer
60
+ - Agent.active-role-rule
61
+ - step: 复制 sample 改 name + domains + ### Modules 即可
62
+
63
+ ### profile-multi-level-dir
64
+ - desc: 多级目录引用(v9.1+)——Profile frontmatter `domains:` 列表用 path 形式引用多级目录的 Domain。例:`.pt/assets/domains/workflow/dev-workflow.md` → `domains: [user-info, agent-info, workflow/dev-workflow, workflow/issue-workflow, workflow/testing-workflow, ...]`。**同目录不重名**(硬约束,文件系统约束);不同子目录可同名(path 天然区分——`meta/login` 和 `auth/login` 不冲突)。Domain frontmatter.name 也用 path 形式(与加载路径一致)。
65
+
66
+ ### profile-h2-sections
67
+ - desc: Profile 范本必加 H2 聚合组段——即使无追加也保留段让配置入口可见。具体格式:YAML 后用 H2 标题写出 Blueprint.groups[].name 同名的段;段下用 `### Domains` 追加(如有)+ `### Modules` 列本插槽的 modules 列表(v9.1+)。例如 pt-dev 范本保留 ## 会话背景 + ## 触发索引 + ## 参考手册 三段(与 dev-knowledge 的 groups 对齐)。配置可观测性:parseProfile groups 数 > 0,用户能看出本 Profile 覆盖哪些聚合组 + 每个聚合组的 modules 选择。
68
+
69
+ ### term-domain-pattern
70
+ - desc: 概念/术语/规则类 Domain 写法:## Scene 下 ### 概念名 + - desc: 定义;## Rules 下 ### 规则名 + - check: 不变量描述。适合概念/术语/架构知识。(注:v9 已删 type 字段,不再有 term/workflow/stack 分类——H2 段名决定 schema。)
71
+
72
+ ### workflow-domain-pattern
73
+ - desc: 流程/手册类 Domain 写法:## Scene 下 ### 引用名 + - path: 路径 + - desc: 说明;## Flows 下 ### 流程名 + - intent: 目的 + - step: 步骤。适合操作流程/开发手册。(注:v9 已删 type 字段。)
74
+
75
+ ### participant-domain-pattern
76
+ - desc: 身份类 Domain 写法(v9.1+ 重命名)——user-info Domain 用 `## User` 段下 H3 角色项(user-profile / pt-goal / collab-mode / ...);agent-info Domain 用 `## Agent` 段下 H3 角色项(agent-role-architect / agent-role-senior-developer / ...)。**段名 = 命名空间**:`User` 限定 user-info、`Agent` 限定 agent-info。Profile 通过 `### Modules: [User]` 聚合 user-info 整段;通过 `### Modules: [Agent.agent-role-architect]` 精确选单角色——角色隔离的"开关"。
77
+
78
+ ### build-roadmap
79
+ - desc: 从零构建 Pt 资产的顺序:(1)分析项目知识结构(参考 project-analysis 的 analyze-steps + section-as-namespace + role-isolation)→ 识别概念/流程/工具栈;(2)创建 Pt Domain 资产(每个知识单元一个 .md,H2 段名决定 schema)→ create-domain-procedure;(3)选 Blueprint(优先复用内建 dev-knowledge,聚合组需求不同才 create-blueprint-procedure——v9.1+ 通常省略,dedupByName 自动 fallback 到 builtin)→(4)创建 Pt Profile 组装 Domain 列表 + ### Modules 填 H3 粒度 → create-profile-procedure;(5)/pt-profile 验证产物 + 检查角色隔离。执行 procedure 时用 /pt manual <procedure-name> <args> 创建实例文档跟踪。
80
+
81
+ ### minimal-example
82
+ - desc: 从零上手的最小样本——两个 Domain(user-info + agent-info)+ 一个 Profile,照抄改即可跑通
83
+ - sample-domain-user: |
84
+ ---
85
+ name: user-info
86
+ ---
87
+ # user-info
88
+ ## User
89
+ ### who-am-i
90
+ - desc: 我是这个项目的开发者
91
+
92
+ ### preferences
93
+ - desc: 偏好类型安全、模块化设计
94
+ - sample-domain-agent: |
95
+ ---
96
+ name: agent-info
97
+ ---
98
+ # agent-info
99
+ ## Agent
100
+ ### role
101
+ - desc: 你是编码助手,帮用户创作 Pt 资产
102
+ - sample-profile: |
103
+ ---
104
+ name: my-guide
105
+ blueprint: dev-knowledge
106
+ domains: [user-info, agent-info, project-analysis, authoring, usage]
107
+ ---
108
+ # my-guide (profile)
109
+ ## 会话背景
110
+ ### Modules
111
+ - Scene
112
+ - User
113
+ - Agent
114
+ ## 触发索引
115
+ ### Modules
116
+ - Trigger
117
+ ## 参考手册
118
+ ### Modules
119
+ - Rules
120
+ - Flows
121
+ - Checklists
122
+ - steps: 放 user-info.md / agent-info.md 到 .pt/assets/domains/,放 my-guide.profile.md 到 .pt/assets/profiles/,/pt-profile my-guide 激活
123
+ - why: 展示最小闭环——两个 Domain 各只写 User/Agent 段(用户身份 + Agent 身份,v9.1+ 重命名),Profile 引内建 blueprint + 选域 + 填 ### Modules 段含 `User` / `Agent` 整段(onboarding 完整模式);激活后 Session Context 即有成对身份
124
+
125
+ ### renderer-registration
126
+ - desc: 加新专用段名(如 `## Audit` / `## Glossary`)的扩展流程——(1) Domain 内用新 H2 段名;(2) `src/parse/profile.ts` 的 `KNOWN_SECTION_NAMES` 集合加新段名一行;(3) `src/compile/agent-context.ts` 的 `moduleRenderers` 注册一行(已有 renderer 复用,如复用 `renderSceneModule` 处理 Term[] 同构);(4) `src/constants.ts` 加 `MOD_XXX = "XXX"` 常量一行(可选,但建议加——模块名常量集中管理便于跨文件引用)。**不需要改主循环**——加新 modName 走 renderer 注册表分发,generic fallback 兜底。
127
+
128
+ ## Flows
129
+
130
+ ### create-domain-procedure
131
+ - argument-hint: <name>
132
+ - intent: 创建新 Pt Domain 资产的步骤指引(LLM 读完后用 write 工具执行,非 Pi 注册命令)
133
+ - vars: [name]
134
+ - step: 用 write 工具创建 .pt/assets/domains/{{name}}.md(多级目录可放 .pt/assets/domains/<subdir>/{{name}}.md)
135
+ - step: 写 frontmatter(name: {{name}}——多级目录用 path 形式如 `workflow/dev-workflow`,无 type 字段)
136
+ - step: 按知识性质选 Module(概念→Scene+Rules,流程→Scene+Flows,规则→Rules,验收→Checklists;身份类→User 或 Agent 专用段)
137
+ - step: 在目标 Profile 的 domains 列表追加 {{name}}(多级目录用 path 形式)
138
+ - step: 删 .pt/cache/agent-contexts/*.agent-context.md + /pt-profile <profile> 验证
139
+
140
+ ### create-profile-procedure
141
+ - argument-hint: <name>
142
+ - intent: 创建新 Pt Profile 的步骤指引(LLM 读完后用 write 工具执行,非 Pi 注册命令)
143
+ - vars: [name]
144
+ - step: 用 write 工具创建 .pt/assets/profiles/{{name}}.profile.md
145
+ - step: 写 frontmatter(name: {{name}} + blueprint: dev-knowledge 优先复用内建 + domains: [按需列,多级目录用 path 形式])
146
+ - step: 为每个 Blueprint 插槽加 H2 段(## 会话背景 / ## 触发索引 / ## 参考手册 等),段下加 `### Modules` 列表(v9.1+)填本插槽的 modName(段名 / 段.项两种形态)
147
+ - step: 角色隔离配置——身份域用专用段名 + 段.项精确选单角色(详见 profile-role-isolation 的 sample-pt-arch / pt-dev / pt-devops)
148
+ - step: 删 .pt/cache/agent-contexts/*.agent-context.md + /pt-profile {{name}} 验证产物 + 检查角色隔离
149
+
150
+ ### create-blueprint-procedure
151
+ - argument-hint: <name>
152
+ - intent: 创建新 Blueprint 的步骤指引(v9.1+ 通常省略——优先复用内建;仅当聚合组需求与内建 dev-knowledge 不同时新建;LLM 读完后用 write 工具执行)
153
+ - vars: [name]
154
+ - step: 确认需要新聚合组——dev-knowledge 有会话背景/触发索引/参考手册三个聚合组(session×2 + turn×1),不够才新建
155
+ - step: 用 write 工具创建 .pt/assets/blueprints/{{name}}.blueprint.yaml
156
+ - step: 写 YAML(name: {{name}},无 agent 字段,**无 modules 字段**——v9.1+ Blueprint 是插槽契约)
157
+ - step: 写 groups(每个聚合组:name + inject: session/turn + mode 可选)——**modules 字段不再存在**
158
+ - step: Profile frontmatter 的 blueprint 字段改为 {{name}} 引用
159
+ - step: Profile H2 段下 ### Modules 列表按需填 modName(段名 / 段.项形态)
160
+ - step: 删 .pt/cache/agent-contexts/*.agent-context.md + /pt-profile <profile> 验证
161
+
162
+ ### modify-asset-procedure
163
+ - argument-hint: (无)
164
+ - intent: 修改已有资产的步骤指引(LLM 读完后用 edit/write 工具执行)
165
+ - vars: []
166
+ - step: 用 read 工具读目标 .md(Pt Domain/Blueprint/Pt Profile)
167
+ - step: 用 edit 工具改内容(或 write 整体重写)—— Profile 改 ### Modules 时保持 modName 2 形态
168
+ - step: 删 .pt/cache/agent-contexts/*.agent-context.md(强制重编译)
169
+ - step: /pt-profile <profile> 重载验证
170
+ - step: 检查产物:/pt raw 看 segment,确认角色隔离生效(pt-dev 不含 architect / devops-engineer,pt-arch 不含 senior+qa+cr+devops 等)
171
+
172
+ ## Rules
173
+
174
+ ### when-new-domain
175
+ - check: 主题聚焦才建新 Domain——一个 Domain 承载一个知识单元;同主题扩内容加 Module,不新建 Domain
176
+
177
+ ### when-new-blueprint
178
+ - check: 聚合组需求不同才建 Blueprint——优先复用内建 dev-knowledge(会话背景/触发索引/参考手册三组);加新聚合组才新建。**v9.1+:Blueprint 不带 modules,创建后无需同步 modules 字段到 Profile——Profile 填 ### Modules 独立维护**
179
+
180
+ ### when-add-module
181
+ - check: 同主题扩内容加 Module(Domain 内加 ## 新 Module 名);不同主题才新建 Domain
182
+
183
+ ### section-name-namespace
184
+ - check: 段名是命名空间(v9.1+)——通用段(Scene/Trigger/Rules/Flows/Checklists)跨 domain 通用;专用段(User/Agent/...)限定到单 domain。加新专用段 = 同时改 Domain + KNOWN_SECTION_NAMES + moduleRenderers(详见 renderer-registration)
185
+
186
+ ### multi-level-dir-no-collision
187
+ - check: 同目录不重名(v9.1+ 多级目录硬约束)——`domains/meta/login.md` 与 `domains/meta/login-other.md` OK(不同名),但 `domains/meta/login.md` 与 `domains/auth/login.md` 也 OK(path 不同),仅 `domains/meta/login.md` 与 `domains/meta/login.md` 冲突(重复)。不同子目录同名用 path 形式引用时不会冲突。
188
+
189
+ ### role-isolation-via-section-name
190
+ - check: 角色隔离通过专用段名实现(v9.1+)——user-info 用 ## User、agent-info 用 ## Agent,Profile 引用 `[User]` 整段或 `[Agent.<role>]` 精确选。**不要在 modName 里加形态 3(domain:段.项)**——会破坏命名空间设计且 profile 配置冗余。
191
+
192
+ ## Checklists
193
+
194
+ ### domain-quality-checklist
195
+ - items: [frontmatter name 对齐加载路径(多级目录用 path 形式), H2 段名是标准段(Scene/Trigger/Rules/Flows/Checklists)或已注册专用段(User/Agent/...), H3 项有 desc 字段, 同段内 H3 项名唯一(跨段可重名靠专用段名避免), 无 type 字段]
196
+
197
+ ### profile-quality-checklist
198
+ - items: [blueprint 引用名存在(优先内建 dev-knowledge), domains 顺序合理(身份类前约束类后), 聚合组段对齐 Blueprint groups(每个 group 一个 H2), ### Modules 段存在且填了 modName(v9.1+ 必填), modName 是合法 2 形态(段名 / 段.项),不含形态 3, 角色隔离正确:专用段(User/Agent)按设计填充,段.项精确选单角色, 无追加时保留 H2 段让配置入口可见, 多级目录引用用 path 形式(如 `workflow/dev-workflow`)]
199
+
200
+ ### role-isolation-checklist
201
+ - items: [4 profile(pt-arch / pt-design / pt-dev / pt-devops)共用同一 agent-info Domain 但各自 ### Modules 列出不同 Agent 角色, pt-dev `### Modules` 含 `Agent.agent-role-senior-developer` + `Agent.agent-role-qa-engineer` + `Agent.agent-role-code-reviewer` + `Agent.active-role-rule`(不含 architect / devops-engineer), pt-arch / pt-design 含 `Agent.agent-role-architect` + `Agent.active-role-rule`(不含 dev / devops 角色), pt-devops 含 `Agent.agent-role-devops-engineer` + `Agent.active-role-rule`(不含其他角色), 跑 transpile 后 /pt raw 检查产物——`### agent-info.senior-developer` 等 H3 粒度输出仅在应见 profile 中出现]
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: pack-repair
3
+ ---
4
+
5
+ # pack-repair
6
+
7
+ v15.x PR1(§6.7.4):project pack 校验失败时的修复引导手册。builtin profile `guide`
8
+ 会引用本 domain——用户 `/manual:pack-repair` 触发 FlowTemplate,按步骤修复。
9
+
10
+ ## Scene
11
+
12
+ ### pack-structure
13
+ - desc: Pt pack 标准目录结构——必须含 domains/ + blueprints/ + profiles/ 三个子目录之一;可选 pt-asset-pack.yaml manifest(PR2 启用)
14
+
15
+ ### pack-sources
16
+ - desc: v15.x Pack 有 4 类来源——project(`<cwd>/.pt/assets/`)/ settings(`.pi/settings.json` 的 `pt.asset-packs[]`,PR4 启用)/ global(`~/.pt/assets/`)/ builtin(`src/builtin/assets/`,随 npm 包发布)
17
+
18
+ ### validation-codes
19
+ - desc: validatePack 返回的错误码——`dir-not-found`(路径不存在)/ `no-asset-subdir`(无 asset 子目录)/ `load-failed`(加载抛异常)
20
+
21
+ ## Flows
22
+
23
+ ### pack-repair
24
+ - argument-hint: (无)
25
+ - intent: project pack 校验失败时引导修复——按错误码分类处置后重启 session 验证
26
+ - vars: []
27
+ - step: /pt status 查看 pack 健康状态(§6.7.6),定位失效 pack + 错误码
28
+ - step: 按 errors[].code 分类处置:
29
+ - dir-not-found:创建 pack 目录(project: mkdir -p .pt/assets/{domains,blueprints,profiles};global: mkdir -p ~/.pt/assets/{domains,blueprints,profiles})
30
+ - no-asset-subdir:至少创建一个 asset 子目录(domains/blueprints/profiles 任选其一)
31
+ - load-failed:检查资产文件格式(.md frontmatter 合法 / .blueprint.yaml 语法正确)
32
+ - step: 修复后重启 pi session(projectPackDegraded 在 session_start 重新校验时清零)
33
+ - step: /pt status 确认 pack 健康(✅,无 DEGRADED 行)
34
+
35
+ ## Rules
36
+
37
+ ### validate-pack-never-throws
38
+ - check: validatePack 失败时返 ValidationResult 对象(ok=false + errors[]),不抛异常——保证加载链不阻断(§6.7.7)
39
+
40
+ ### project-pack-degradation
41
+ - check: project pack 失效时强制激活 builtin guide profile(projectPackDegraded=true),覆盖用户配置的 pt.default-profile——保证 pi 可用让用户修复(§6.7.3)
42
+
43
+ ### restart-after-repair
44
+ - check: 修复 project pack 后必须重启 pi session——projectPackDegraded 标记在 session_start 重新校验时清零,不重启则继续降级
45
+
46
+ ### global-pack-guide-non-interactive
47
+ - check: 全局 Pack 初始化引导仅在 TTY + 非 CI + 无 PT_NO_GUIDE 环境触发(§7.5.1)——避免阻塞 CI / 后台进程