@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.
- package/LICENSE +21 -0
- package/README.md +219 -0
- package/dist/agent/api-bridge.d.ts +8 -0
- package/dist/agent/api-bridge.js +83 -0
- package/dist/agent/index.d.ts +2 -0
- package/dist/agent/index.js +3 -0
- package/dist/agent/pi-adapter.d.ts +35 -0
- package/dist/agent/pi-adapter.js +251 -0
- package/dist/agent/registry.d.ts +4 -0
- package/dist/agent/registry.js +40 -0
- package/dist/asset-health.d.ts +50 -0
- package/dist/asset-health.js +267 -0
- package/dist/asset-pack/loader.d.ts +47 -0
- package/dist/asset-pack/loader.js +121 -0
- package/dist/asset-pack/manifest.d.ts +23 -0
- package/dist/asset-pack/manifest.js +96 -0
- package/dist/asset-pack/md-file-pack.d.ts +41 -0
- package/dist/asset-pack/md-file-pack.js +153 -0
- package/dist/asset-pack/validate.d.ts +55 -0
- package/dist/asset-pack/validate.js +131 -0
- package/dist/builtin/assets/blueprints/dev-knowledge.blueprint.yaml +13 -0
- package/dist/builtin/assets/domains/agent-info.md +15 -0
- package/dist/builtin/assets/domains/authoring.md +201 -0
- package/dist/builtin/assets/domains/pack-repair.md +47 -0
- package/dist/builtin/assets/domains/project-analysis.md +52 -0
- package/dist/builtin/assets/domains/usage.md +81 -0
- package/dist/builtin/assets/domains/user-info.md +15 -0
- package/dist/builtin/assets/profiles/guide.profile.md +28 -0
- package/dist/commands.d.ts +69 -0
- package/dist/commands.js +344 -0
- package/dist/compile/agent-context.d.ts +48 -0
- package/dist/compile/agent-context.js +423 -0
- package/dist/compile/index.d.ts +1 -0
- package/dist/compile/index.js +5 -0
- package/dist/compile/resolve-use.d.ts +36 -0
- package/dist/compile/resolve-use.js +171 -0
- package/dist/compile/type-guards.d.ts +29 -0
- package/dist/compile/type-guards.js +107 -0
- package/dist/config.d.ts +31 -0
- package/dist/config.js +133 -0
- package/dist/constants.d.ts +52 -0
- package/dist/constants.js +81 -0
- package/dist/diagnostics.d.ts +14 -0
- package/dist/diagnostics.js +29 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +838 -0
- package/dist/injection-status.d.ts +45 -0
- package/dist/injection-status.js +134 -0
- package/dist/log.d.ts +64 -0
- package/dist/log.js +139 -0
- package/dist/manual-session.d.ts +24 -0
- package/dist/manual-session.js +152 -0
- package/dist/manual-track.d.ts +35 -0
- package/dist/manual-track.js +107 -0
- package/dist/parse/blueprint.d.ts +5 -0
- package/dist/parse/blueprint.js +59 -0
- package/dist/parse/domain-renderers.d.ts +8 -0
- package/dist/parse/domain-renderers.js +115 -0
- package/dist/parse/domain.d.ts +7 -0
- package/dist/parse/domain.js +69 -0
- package/dist/parse/index.d.ts +9 -0
- package/dist/parse/index.js +223 -0
- package/dist/parse/profile.d.ts +18 -0
- package/dist/parse/profile.js +117 -0
- package/dist/parse/ref-resolver.d.ts +63 -0
- package/dist/parse/ref-resolver.js +174 -0
- package/dist/parse/shared.d.ts +76 -0
- package/dist/parse/shared.js +273 -0
- package/dist/profile-persist.d.ts +22 -0
- package/dist/profile-persist.js +53 -0
- package/dist/render/cache.d.ts +15 -0
- package/dist/render/cache.js +135 -0
- package/dist/render/index.d.ts +3 -0
- package/dist/render/index.js +14 -0
- package/dist/render/session-inject.d.ts +5 -0
- package/dist/render/session-inject.js +24 -0
- package/dist/render/turn-inject.d.ts +36 -0
- package/dist/render/turn-inject.js +248 -0
- package/dist/schema.d.ts +448 -0
- package/dist/schema.js +45 -0
- package/dist/session.d.ts +82 -0
- package/dist/session.js +102 -0
- package/dist/slog.d.ts +3 -0
- package/dist/slog.js +27 -0
- package/dist/transpile.d.ts +34 -0
- package/dist/transpile.js +220 -0
- package/dist/verify/file-hash.d.ts +2 -0
- package/dist/verify/file-hash.js +30 -0
- package/dist/verify/fs-content-match.d.ts +2 -0
- package/dist/verify/fs-content-match.js +26 -0
- package/dist/verify/fs-exists.d.ts +2 -0
- package/dist/verify/fs-exists.js +13 -0
- package/dist/verify/fs-not-exists.d.ts +2 -0
- package/dist/verify/fs-not-exists.js +13 -0
- package/dist/verify/git-status-clean.d.ts +2 -0
- package/dist/verify/git-status-clean.js +19 -0
- package/dist/verify/index.d.ts +7 -0
- package/dist/verify/index.js +46 -0
- package/dist/verify/lint-check.d.ts +2 -0
- package/dist/verify/lint-check.js +17 -0
- package/dist/verify/read-stderr.d.ts +5 -0
- package/dist/verify/read-stderr.js +20 -0
- package/dist/verify/ref-check.d.ts +13 -0
- package/dist/verify/ref-check.js +88 -0
- package/dist/verify/test-pass.d.ts +2 -0
- package/dist/verify/test-pass.js +17 -0
- package/dist/verify/ts-compiles.d.ts +2 -0
- package/dist/verify/ts-compiles.js +17 -0
- package/package.json +62 -0
- package/src/agent/api-bridge.ts +105 -0
- package/src/agent/index.ts +4 -0
- package/src/agent/pi-adapter.ts +326 -0
- package/src/agent/registry.ts +44 -0
- package/src/asset-health.ts +327 -0
- package/src/asset-pack/loader.ts +141 -0
- package/src/asset-pack/manifest.ts +118 -0
- package/src/asset-pack/md-file-pack.ts +202 -0
- package/src/asset-pack/validate.ts +186 -0
- package/src/builtin/assets/blueprints/dev-knowledge.blueprint.yaml +13 -0
- package/src/builtin/assets/domains/agent-info.md +15 -0
- package/src/builtin/assets/domains/authoring.md +201 -0
- package/src/builtin/assets/domains/pack-repair.md +47 -0
- package/src/builtin/assets/domains/project-analysis.md +52 -0
- package/src/builtin/assets/domains/usage.md +81 -0
- package/src/builtin/assets/domains/user-info.md +15 -0
- package/src/builtin/assets/profiles/guide.profile.md +28 -0
- package/src/commands.ts +405 -0
- package/src/compile/agent-context.ts +487 -0
- package/src/compile/index.ts +5 -0
- package/src/compile/resolve-use.ts +208 -0
- package/src/compile/type-guards.ts +132 -0
- package/src/config.ts +154 -0
- package/src/constants.ts +104 -0
- package/src/diagnostics.ts +36 -0
- package/src/index.ts +1028 -0
- package/src/injection-status.ts +155 -0
- package/src/log.ts +173 -0
- package/src/manual-session.ts +190 -0
- package/src/manual-track.ts +127 -0
- package/src/parse/blueprint.ts +82 -0
- package/src/parse/domain-renderers.ts +120 -0
- package/src/parse/domain.ts +78 -0
- package/src/parse/index.ts +266 -0
- package/src/parse/profile.ts +139 -0
- package/src/parse/ref-resolver.ts +198 -0
- package/src/parse/shared.ts +331 -0
- package/src/profile-persist.ts +60 -0
- package/src/render/cache.ts +150 -0
- package/src/render/index.ts +14 -0
- package/src/render/session-inject.ts +26 -0
- package/src/render/turn-inject.ts +278 -0
- package/src/schema.ts +542 -0
- package/src/session.ts +190 -0
- package/src/slog.ts +32 -0
- package/src/transpile.ts +302 -0
- package/src/verify/file-hash.ts +29 -0
- package/src/verify/fs-content-match.ts +28 -0
- package/src/verify/fs-exists.ts +14 -0
- package/src/verify/fs-not-exists.ts +17 -0
- package/src/verify/git-status-clean.ts +23 -0
- package/src/verify/index.ts +57 -0
- package/src/verify/lint-check.ts +21 -0
- package/src/verify/read-stderr.ts +24 -0
- package/src/verify/ref-check.ts +118 -0
- package/src/verify/test-pass.ts +18 -0
- package/src/verify/ts-compiles.ts +21 -0
|
@@ -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 / 后台进程
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: project-analysis
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# project-analysis
|
|
6
|
+
|
|
7
|
+
## Scene
|
|
8
|
+
|
|
9
|
+
### what-is-pt
|
|
10
|
+
- desc: Pt 是异构上下文编译器——把领域知识按配置编译成 Agent 上下文并注入。你写 .pt/assets/ 下的 Pt Domain(知识原料)和 Pt Profile(配置),Pt 编译成 Agent Context(Session Context 固定注入面 + Turn Context 按需触发面),注入 Agent。
|
|
11
|
+
|
|
12
|
+
### four-layer-model
|
|
13
|
+
- desc: Pt Domain(内容层——一个 md = 一个知识单元,Module/H2 段名即 schema 选择器)+ Blueprint(结构层——聚合组插槽契约 name + inject + mode,跨项目复用,YAML 载体)+ Pt Profile(配置层——引用 Blueprint + 选 Domains + 填 modules,项目级)+ Agent Context(产物层——编译输出,Session Context + Turn Context 两面,带 sourceHash 缓存)。**v9.1+:Blueprint 不带 modules(退化为插槽契约)——modules 由 Profile 的 H2 段下 ### Modules 列表提供。**
|
|
14
|
+
|
|
15
|
+
### analyze-steps
|
|
16
|
+
- desc: 识别项目知识结构的三步法:(1)列举项目里的领域概念/术语 → Domain 用 Scene + Rules Module;(2)列举项目里的操作流程/开发手册 → Domain 用 Scene + Flows Module;(3)列举项目用的技术栈/工具 → Domain 用 Scene Module(带 path 字段引用外部资源)。一个 Domain 可混装多种 Module,不必按类型拆分。
|
|
17
|
+
|
|
18
|
+
### aggregation-group
|
|
19
|
+
- desc: Blueprint 的 groups 定义聚合组(语义名,如"会话背景"/"触发索引"/"参考手册"),inject 字段映射到注入位置(session = 每轮固定 / turn = 轮次级按需触发)。**v9.1+**:Blueprint groups 不带 modules(插槽契约),modules 由 Profile H2 段下 ### Modules 列表填——Profile 通过 H2 名匹配 Blueprint 插槽,每 H2 下的 ### Modules 列本插槽的 modules 列表(段名 / 段.项 两种形态)。AgentAdapter 内部映射 session/turn 到 Pi API(system_prompt/context_message)。
|
|
20
|
+
|
|
21
|
+
### modname-2-forms
|
|
22
|
+
- desc: modName 2 形态(v9.1+)——(1) 段名(`Scene` / `User` / `Agent` / `Trigger` / `Rules` / `Flows` / `Checklists`):跨所有引用域该段整段聚合;(2) 段.项(`Agent.senior-developer` / `User.user-profile`):跨所有引用域该段下 H3 项精确选。**不引入形态 3(domain:段.项)**——限定到单 domain 通过专用段名(`User` / `Agent`)实现,避免 profile 重复写引用。
|
|
23
|
+
|
|
24
|
+
### section-as-namespace
|
|
25
|
+
- desc: 段名 = 命名空间(v9.1+)——通用段(Scene / Participant / Trigger / Rules / Flows / Checklists)跨 domain 通用;专用段(User / agent-info 用 / Agent / agent-info 用 / ...)限定到单 domain。加新专用段 = Domain 用新 H2 段名 + `KNOWN_SECTION_NAMES` 集合加一行 + `moduleRenderers` 注册一行(详见 authoring 的 renderer-registration)。
|
|
26
|
+
|
|
27
|
+
### multi-level-dir
|
|
28
|
+
- desc: 多级目录支持(v9.1+)——`.pt/assets/domains/<subdir>/<name>.md` 用子目录归类相关 Domain。`loadAllDomains` 自动递归扫描;Domain.name = POSIX 相对路径去 .md(`workflow/dev-workflow`)。Profile 的 `domains:` 列表用 path 形式引用——`[user-info, agent-info, workflow/dev-workflow, ...]`。**同目录不重名**(硬约束,文件系统约束);不同子目录可同名(path 天然区分)。
|
|
29
|
+
|
|
30
|
+
### role-isolation
|
|
31
|
+
- desc: 角色隔离(v9.1+ 核心承诺)——通过专用段名 + 段.项粒度实现 Profile 间的角色隔离。例:pt-dev profile 用 `[Scene, User, Agent.agent-role-senior-developer, Agent.agent-role-qa-engineer, Agent.agent-role-code-reviewer, Agent.active-role-rule]`——只看 dev 3 角色 + active-role-rule,不看 architect / devops-engineer;pt-arch 用 `[Scene, User, Agent.agent-role-architect, Agent.active-role-rule]`;pt-devops 用 `[Scene, User, Agent.agent-role-devops-engineer, Agent.active-role-rule]`。**4 profile 共享同一 Blueprint(dev-knowledge)+ 同一 Domain 集合(user-info + agent-info + ...),差异全在 ### Modules 段——真正的隔离**。
|
|
32
|
+
|
|
33
|
+
### h3-name-uniqueness
|
|
34
|
+
- desc: H3 项名唯一约束(v9.1+)——同段内 H3 重名 parse 时**后覆盖前**(保持 IR 唯一性);跨段同名 H3 由段名命名空间避免(`Scene.x` 不匹配 `User` 段下同名 x,要跨段匹配必须改段名)。**`### <domain>.<item>` 渲染形式**——H3 项粒度产物输出形式(如 `### agent-info.senior-developer`)。
|
|
35
|
+
|
|
36
|
+
### inv-domain-granularity
|
|
37
|
+
- desc: 一个 Domain 承载一个知识单元——可以混装多种 Module(Scene + Rules + Flows),但语义上聚焦一个主题。按主题拆分 Domain,不按 Module 类型拆分。
|
|
38
|
+
|
|
39
|
+
### inv-blueprint-reuse
|
|
40
|
+
- desc: Blueprint 是跨项目复用的结构层——不要为单个项目定制 Blueprint;优先复用内建 Blueprint(dev-knowledge,含会话背景/触发索引/参考手册三个聚合组),只在聚合组需求不同时新建。**v9.1+**:Blueprint 是插槽契约(name + inject + mode),不带 modules——modules 来自 Provider。
|
|
41
|
+
|
|
42
|
+
## Flows
|
|
43
|
+
|
|
44
|
+
### quickstart-flow
|
|
45
|
+
- argument-hint: (无)
|
|
46
|
+
- intent: 新手 5 步上手引导
|
|
47
|
+
- vars: []
|
|
48
|
+
- step: npm install @issac/pi-pt + 配置 pi.extensions(见 README)
|
|
49
|
+
- step: 激活内建 guide Profile——pi --pt-profile guide,或不设配置装包即自动激活
|
|
50
|
+
- step: /pt 查看当前编译状态(profile + segment 长度 + cache hit)
|
|
51
|
+
- step: 读 project-analysis 的 analyze-steps + section-as-namespace + role-isolation 分析自己项目的知识结构
|
|
52
|
+
- step: /pt flows 列出可触发手册,试 /manual:authoring 查看创作手册
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: usage
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# usage
|
|
6
|
+
|
|
7
|
+
## Trigger
|
|
8
|
+
### usage-trigger
|
|
9
|
+
- desc: 操作 Pt 时参考;含 /pt 命令族(含 /pt manual 实例化手册)+ --pt-profile flag(--pt-context 为旧 flag,backward-compat 保留)+ /pt-profile 切换
|
|
10
|
+
- hint: /manual:usage 查看完整命令列表
|
|
11
|
+
|
|
12
|
+
## Scene
|
|
13
|
+
|
|
14
|
+
### pt-commands
|
|
15
|
+
- desc: /pt(查看当前状态)+ /pt status(profile + segment 长度 + cache hit)+ /pt flows(列出可触发手册,即 Turn Context 内容索引)+ /pt raw(dump segment 到 .pt/cache/raws/)+ /pt full(dump 完整 Session Inject 到 .pt/cache/fulls/)
|
|
16
|
+
|
|
17
|
+
### pt-profile-command
|
|
18
|
+
- desc: /pt-profile(列出所有可用 Profile)+ /pt-profile <name>(切换到指定 Profile,下一轮生效)。旧命令 /pt-context 保留为 backward-compat fallback。
|
|
19
|
+
|
|
20
|
+
### manual-trigger
|
|
21
|
+
- desc: /manual:<domain-name>(注入该 Domain 的 Rules/Flows/Checklists 段到 Turn Inject)+ /<flow-name> <args>(触发 Domain 的 FlowTemplate)
|
|
22
|
+
|
|
23
|
+
### pt-profile-flag
|
|
24
|
+
- desc: --pt-profile <name>(Pi 启动时激活指定 Profile,CLI 优先级高于 session_start 默认逻辑)。旧 flag --pt-context 保留为 backward-compat fallback。
|
|
25
|
+
|
|
26
|
+
### pt-manual-command
|
|
27
|
+
- desc: /pt manual <procedure-name> [args...](创建手册实例文档到 .pt/manuals/,含 checklist + 产物区,用于跟踪执行)。与 /manual:<domain>(ephemeral 参考)互补——前者持久化,后者即时注入。
|
|
28
|
+
|
|
29
|
+
### pt-tools-llm
|
|
30
|
+
- desc: pt_status / pt_flows / pt_manual 三个 LLM tool(pi.registerTool)。与 /pt 命令族共享纯函数内核——人类打 /pt status,LLM 调 pt_status,结果一致。/pt-profile 不做 tool(切换 Profile 改 Session Context 不该让 LLM 触发,见 .pt/docs/designs/pt-command-tool-dual-registration.md §2.4)。
|
|
31
|
+
|
|
32
|
+
### global-pack
|
|
33
|
+
- desc: v15.x 全局 Pack(~/.pt/assets/,寻址 @gbl)——用户跨项目共用资产放这里,Pt 自动加载(优先级低于 project/settings,高于 builtin)。首次启动如目录不存在会提示创建(TTY + 非 CI + 无 PT_NO_GUIDE 时)。复用方式:把通用 Domain/Blueprint/Profile 放 ~/.pt/assets/{domains,blueprints,profiles}/
|
|
34
|
+
|
|
35
|
+
### settings-pack
|
|
36
|
+
- desc: v15.x settings 声明 Pack——在 .pi/settings.json 的 pt.asset-packs[] 声明第三方 / 团队 Pack(只 path 字段,name 从 manifest 读)。路径支持 ~(home dir)/ 绝对 / 相对 cwd。多个 settings pack 按声明顺序后者赢(npm 风格)。pt.project-pack-dir 可改 project pack 路径(默认 .pt/assets,支持项目外路径)
|
|
37
|
+
|
|
38
|
+
### use-profile
|
|
39
|
+
- desc: v15.x Profile use 单继承——use: @pack/name 引用另一 Profile 作为基础增量覆盖。blueprint 覆盖 / tagline 覆盖 / domains 追加去重 / groups 同名替换。循环检测报错含链;菱形不误报。不写 use = 独立 Profile。示例:use: @pt-internal/pt-dev + blueprint: @team-stdlib/minimal + domains: [my-domain]
|
|
40
|
+
|
|
41
|
+
### frontmatter-parser-limit
|
|
42
|
+
- desc: Profile / Domain 的 frontmatter 是简易 parser(src/parse/shared.ts:parseFrontmatter)——支持单行 key: value,不支持复杂 YAML 结构(多行字符串 / 嵌套 / 注释)。复杂结构走 Blueprint 的 .blueprint.yaml(用 yaml 库完整解析)。v15.x use 字段保持单行 string 形态以兼容(M7)——如 `use: @pt-internal/pt-dev`,不写多行
|
|
43
|
+
|
|
44
|
+
## Flows
|
|
45
|
+
|
|
46
|
+
### list-profiles
|
|
47
|
+
- argument-hint: (无)
|
|
48
|
+
- intent: 列出当前项目所有可用 Profile 名(含内建 fallback)
|
|
49
|
+
- vars: []
|
|
50
|
+
- step: 读 .pt/assets/profiles/ 下所有 .profile.md 的 frontmatter.name
|
|
51
|
+
- step: 合并内建 src/builtin/assets/profiles/(同名时项目优先)
|
|
52
|
+
- step: 去重排序后输出
|
|
53
|
+
|
|
54
|
+
### switch_profile
|
|
55
|
+
- argument-hint: <profile-name>
|
|
56
|
+
- intent: 切换到指定 Profile 并重编译
|
|
57
|
+
- vars: [profile-name]
|
|
58
|
+
- step: /pt-profile {{profile-name}}
|
|
59
|
+
- step: Pt 删该 profile 的 cache(强制重编译)
|
|
60
|
+
- step: 下一轮 Pi 事件自动加载新 profile 的 segment
|
|
61
|
+
|
|
62
|
+
### dump_segment
|
|
63
|
+
- argument-hint: (无)
|
|
64
|
+
- intent: 把当前 session 的 segment(Pt 注入的 Session Context)dump 到文件
|
|
65
|
+
- vars: []
|
|
66
|
+
- step: /pt raw → 写入 .pt/cache/raws/segment-<timestamp>.md
|
|
67
|
+
- step: 用于检查 Pt 编译产物是否正确
|
|
68
|
+
|
|
69
|
+
## Rules
|
|
70
|
+
|
|
71
|
+
### cache-invalidation-rule
|
|
72
|
+
- check: 改资产后必删 .pt/cache/agent-contexts/*.agent-context.md 强制重编译;sourceHash 会自动失效,但手动删 cache 是最直接的验证方式
|
|
73
|
+
|
|
74
|
+
### profile-switch-next-turn
|
|
75
|
+
- check: /pt-profile <name> 切换后下一轮才生效(before_agent_start 事件重注入);当前轮不受影响
|
|
76
|
+
|
|
77
|
+
### module-fallback-warning
|
|
78
|
+
- check: Domain Module 名拼错(如 ## Scenr)会走 generic fallback 静默聚合,不报错;用 /pt raw 检查 segment 确认 Module 是否正确贡献
|
|
79
|
+
|
|
80
|
+
### builtin-override
|
|
81
|
+
- check: 项目 .pt/assets/ 下同名资产覆盖内建(dedupByName 项目优先);内建 guide 被项目 guide 覆盖时 /pt status 仍显示 guide 名但内容是项目版
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: guide
|
|
3
|
+
blueprint: dev-knowledge
|
|
4
|
+
domains: [user-info, agent-info, project-analysis, authoring, usage, pack-repair]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# guide (profile)
|
|
8
|
+
|
|
9
|
+
<!--
|
|
10
|
+
v9.1+(modules-to-profile-complete):见 pt-arch.profile.md 头注释。
|
|
11
|
+
guide 是 onboarding——会话背景含 Scene + User 整段 + Agent 整段,展示完整信息。
|
|
12
|
+
-->
|
|
13
|
+
|
|
14
|
+
## 会话背景
|
|
15
|
+
### Modules
|
|
16
|
+
- Scene
|
|
17
|
+
- User
|
|
18
|
+
- Agent
|
|
19
|
+
|
|
20
|
+
## 触发索引
|
|
21
|
+
### Modules
|
|
22
|
+
- Trigger
|
|
23
|
+
|
|
24
|
+
## 参考手册
|
|
25
|
+
### Modules
|
|
26
|
+
- Rules
|
|
27
|
+
- Flows
|
|
28
|
+
- Checklists
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { SessionState } from "./session.js";
|
|
2
|
+
/** /pt status 内核:返回状态摘要文本(单行 | 分隔)。 */
|
|
3
|
+
export declare function statusText(session: SessionState): string;
|
|
4
|
+
/** v15.x §4.4.4(缺口 5):/pt packs 详情命令——pack 诊断信息落点。
|
|
5
|
+
* pack.name/version/desc/asset 计数走这里,status 单行不再塞 desc。
|
|
6
|
+
* asset 计数:从 active bundle 的 workingSet.identity 索引按 pack.name 前缀过滤。 */
|
|
7
|
+
export declare function packsText(session: SessionState): string;
|
|
8
|
+
/** /pt flows 内核:返回可用手册列表文本。无激活 Profile 返回提示串。
|
|
9
|
+
*
|
|
10
|
+
* v13.x(issue pt-turn-inject-not-profile-scoped):不再预过滤——传全集 domains 给 listManuals,
|
|
11
|
+
* adapter 内部用 setAgentContext 时存下的 profile 自行 filterDomainsByProfile 过滤。 */
|
|
12
|
+
export declare function flowsText(session: SessionState): string;
|
|
13
|
+
/** /pt full 内核:构建写入 .pt/cache/fulls/ 的完整 systemPrompt 字符串(v10.x 修复 pt-full-duplicate-segment)。
|
|
14
|
+
*
|
|
15
|
+
* 设计动机:消除 `/pt full` 与 PiAdapter `before_agent_start` 的双重拼接路径——
|
|
16
|
+
* - PiAdapter 每轮把 segment 拼到 base,写回 `agent.state.systemPrompt`(= `ctx.getSystemPrompt()`)
|
|
17
|
+
* - 第一轮 prompt 之后,`ctx.getSystemPrompt()` 已含 segment;旧版 `/pt full` 再拼一次 → 2× 重复
|
|
18
|
+
* - 根因:两份拼接实现通过隐式时序耦合,缺乏单一信息源
|
|
19
|
+
*
|
|
20
|
+
* 修复:把 `lastBuiltPrompt`(由 PiAdapter 的 `onInjected` 回调写入,正是 LLM 实际看到的 systemPrompt)
|
|
21
|
+
* 作为 canonical source。第一轮之前的 fallback:模拟下一次 LLM 会看到的注入(保留旧版语义)。
|
|
22
|
+
*
|
|
23
|
+
* 边界纪律:
|
|
24
|
+
* - 不动 PiAdapter(PiAdapter 行为正确,不重复注入)
|
|
25
|
+
* - 不动 Pi 上游 API(`getSystemPrompt` 语义不变)
|
|
26
|
+
* - 只动这一个函数体,外加调用方 `src/index.ts`
|
|
27
|
+
*/
|
|
28
|
+
export declare function buildFullPrompt(baseSystemPrompt: string, cachedSegment: string | null, lastBuiltPrompt: string | null): string;
|
|
29
|
+
/** /pt manual 内核:构建手册实例文档内容 + 目标文件路径。不写文件(写文件由壳负责)。 */
|
|
30
|
+
export interface ManualDocResult {
|
|
31
|
+
content: string;
|
|
32
|
+
filePath: string;
|
|
33
|
+
error?: string;
|
|
34
|
+
}
|
|
35
|
+
export declare function buildManualDoc(cwd: string, session: SessionState, procedure: string, args: string): ManualDocResult;
|
|
36
|
+
/** /pt check 选项(issue pt-asset-migration-visibility Layer 3)。
|
|
37
|
+
* - profileName:单 profile 体检(v1 范围;--all 全集是默认)
|
|
38
|
+
* - fix:v2 范围(v1 不实现;只输出"运行 `/pt check --fix`"提示)
|
|
39
|
+
* v1:format = "biome"(仅一种风格;预留给未来 tsc/eslint 切换)。 */
|
|
40
|
+
export interface CheckOptions {
|
|
41
|
+
profileName?: string;
|
|
42
|
+
fix?: boolean;
|
|
43
|
+
format?: "biome";
|
|
44
|
+
}
|
|
45
|
+
/** /pt check 输出结果(供 shell 检查输出与是否 issues)。 */
|
|
46
|
+
export interface CheckResult {
|
|
47
|
+
/** 格式化后的多行文本(biome 风格)。 */
|
|
48
|
+
output: string;
|
|
49
|
+
/** issue 数(errors + warnings)。 */
|
|
50
|
+
issueCount: number;
|
|
51
|
+
errors: number;
|
|
52
|
+
warnings: number;
|
|
53
|
+
}
|
|
54
|
+
/** /pt check 内核:从 session.assetHealthIssues(已扫)格式化输出。
|
|
55
|
+
* v14.x(issue §Layer 3):session_start 已扫,/pt check 直接格式化——不重复扫描。
|
|
56
|
+
* 未扫(null)→ 返回提示串 + 0 issue。
|
|
57
|
+
*
|
|
58
|
+
* 输出风格(biome/tsc 同源):
|
|
59
|
+
*
|
|
60
|
+
* ysl-developer.profile.md
|
|
61
|
+
* × [error] ## 会话背景 缺 ### Modules
|
|
62
|
+
* hint: 在 H2 段下加 `### Modules: [Scene, ...]`
|
|
63
|
+
*
|
|
64
|
+
* × 6 errors, 0 warnings
|
|
65
|
+
* hint: 运行 `/pt check --fix` 自动应用已知 migration
|
|
66
|
+
*
|
|
67
|
+
* --profile X:只列该 profile 的 issue;其它 profile 的忽略(v1 简化)。
|
|
68
|
+
*/
|
|
69
|
+
export declare function checkText(session: SessionState, opts?: CheckOptions): CheckResult;
|
package/dist/commands.js
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
// src/commands.ts — pt 命令纯函数内核(v10.x:command + tool 双注册架构)
|
|
2
|
+
//
|
|
3
|
+
// 设计动机(.pt/docs/designs/pt-command-tool-dual-registration.md):
|
|
4
|
+
// - 人类(command) + LLM(tool)共享同一组纯函数内核,零逻辑重复
|
|
5
|
+
// - command 壳:ctx.ui.notify 呈现(src/index.ts)
|
|
6
|
+
// - tool 壳:return { content: [{ text }] } 呈现(src/index.ts)
|
|
7
|
+
// - 纪律:内核不依赖 ExtensionAPI / ExtensionCommandContext,只读 session + 调内部模块
|
|
8
|
+
//
|
|
9
|
+
// v12.x(issue pt-session-singleton-pi-web-pollution 修复):
|
|
10
|
+
// - 内核函数签名加 `session: SessionState` 参数,调用方传 per-session state
|
|
11
|
+
// - 不再 import module-level `session` 单例(已删除)
|
|
12
|
+
//
|
|
13
|
+
// v14.x(issue pt-asset-migration-visibility Layer 3):
|
|
14
|
+
// - 加 checkText() 内核 + CheckOptions:/pt check + pt_check tool 共享
|
|
15
|
+
// - 同步格式化 6 列 biome/tsc 风格 + hint/fix 展示
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { MANUAL_DIR, MOD_FLOWS } from "./constants.js";
|
|
18
|
+
import { bindFlowTemplate, findFlowInBlueprint } from "./render/turn-inject.js";
|
|
19
|
+
import { filterDomainsByProfile } from "./schema.js";
|
|
20
|
+
import { isFlowTemplateLike } from "./compile/type-guards.js";
|
|
21
|
+
/** /pt status 内核:返回状态摘要文本(单行 | 分隔)。 */
|
|
22
|
+
export function statusText(session) {
|
|
23
|
+
const flowCount = session.cachedBundles?.reduce((acc, b) => {
|
|
24
|
+
let n = 0;
|
|
25
|
+
// Phase term-P9.2:FlowTemplate 在 ## Flows 段(不再是 ## Manual)。仍只看 workflow 类型 Domain。
|
|
26
|
+
for (const d of b.domains) {
|
|
27
|
+
const flows = d.modules[MOD_FLOWS];
|
|
28
|
+
if (Array.isArray(flows))
|
|
29
|
+
n += flows.length;
|
|
30
|
+
}
|
|
31
|
+
return acc + n;
|
|
32
|
+
}, 0) ?? 0;
|
|
33
|
+
const domainCount = session.cachedBundles?.reduce((acc, b) => acc + b.domains.length, 0) ?? 0;
|
|
34
|
+
const blueprintCount = session.cachedBundles?.reduce((acc, b) => acc + b.blueprints.length, 0) ?? 0;
|
|
35
|
+
const profileCount = session.cachedBundles?.reduce((acc, b) => acc + b.profiles.length, 0) ?? 0;
|
|
36
|
+
// v14.x(issue pt-asset-migration-visibility Layer 2):暴露 session_start 健康扫描结果
|
|
37
|
+
const healthIssues = session.assetHealthIssues;
|
|
38
|
+
const healthLine = healthIssues === null
|
|
39
|
+
? "pt health: (not scanned)"
|
|
40
|
+
: healthIssues.length === 0
|
|
41
|
+
? "pt health: ok"
|
|
42
|
+
: `pt health: ${healthIssues.length} issue${healthIssues.length > 1 ? "s" : ""} (${healthIssues.filter((i) => i.severity === "error").length} errors, ${healthIssues.filter((i) => i.severity === "warning").length} warnings)`;
|
|
43
|
+
// v15.x PR1(§6.7.6):暴露 session_start pack 校验结果——每个 pack ✅ / ⚠ DEGRADED + 原因。
|
|
44
|
+
// pack 健康区别于 healthLine 的 profile 配置体检:pack 健康是"加载层健康",profile 健康是"资产内容健康"。
|
|
45
|
+
const packValidation = session.packValidation;
|
|
46
|
+
const packLine = formatPackHealthLine(packValidation);
|
|
47
|
+
// v14.x(tagline):statusText 显式展开 tagline(不受 footer 35 字符限制)
|
|
48
|
+
const tagline = session.cachedProfile?.tagline;
|
|
49
|
+
const taglineLine = tagline ? `pt tagline: ${tagline}` : "pt tagline: (none)";
|
|
50
|
+
return [
|
|
51
|
+
`pt profile: ${session.activeProfile ?? "(未激活)"}`,
|
|
52
|
+
`pt loadedFrom: ${session.loadedFrom ?? "(none)"}`, // v10.x:可观测性(issue pt-context-persist-lost)
|
|
53
|
+
`pt agent: ${session.activeAdapter?.name ?? "(none)"}`,
|
|
54
|
+
taglineLine,
|
|
55
|
+
`pt domains: ${domainCount}, blueprints: ${blueprintCount}, profiles: ${profileCount}, flows: ${flowCount}`,
|
|
56
|
+
`pt segment length: ${session.cachedSegment?.length ?? 0} chars`,
|
|
57
|
+
`pt cache hit: ${session.lastCacheHit ? "yes" : "no"}`,
|
|
58
|
+
`pt last built prompt: ${session.lastBuiltPrompt ? `${session.lastBuiltPrompt.length} chars` : "(未跑过 turn)"}`,
|
|
59
|
+
// issue pt-status-no-injection-state:暴露 4 态自报状态
|
|
60
|
+
`pt state: ${session.injectionState}${session.injectionError ? `: ${session.injectionError.slice(0, 40)}` : ""}`,
|
|
61
|
+
healthLine,
|
|
62
|
+
packLine,
|
|
63
|
+
`pt cwd: ${session.lastCwd}`,
|
|
64
|
+
].join(" | ");
|
|
65
|
+
}
|
|
66
|
+
/** v15.x PR1(§6.7.6)— /pt status 暴露 pack 健康。
|
|
67
|
+
* 单行格式:`pt packs: N/M ok | [@prj] ✅ | [@gbl] ✅ | [@pt] ✅`
|
|
68
|
+
* 降级时附加原因:`[@prj] ⚠ DEGRADED — <errors[0].msg 截断 60 字符>`。
|
|
69
|
+
* packValidation=null → `pt packs: (not validated)`(尚未 session_start)。
|
|
70
|
+
* packValidation=[] → `pt packs: (none loaded)`(不应出现——session_start 总构造 3 个 pack)。 */
|
|
71
|
+
function formatPackHealthLine(packValidation) {
|
|
72
|
+
if (packValidation === null)
|
|
73
|
+
return "pt packs: (not validated)";
|
|
74
|
+
if (packValidation.length === 0)
|
|
75
|
+
return "pt packs: (none loaded)";
|
|
76
|
+
const items = packValidation.map((r) => {
|
|
77
|
+
// v15.x §4.4.4(缺口 4):reserved 显位置别名(reservedAlias),非 reserved 显 pack(manifest.name)
|
|
78
|
+
// 砍 desc——pack 详情走 /pt packs(缺口 5)
|
|
79
|
+
const label = r.reservedAlias ?? r.pack;
|
|
80
|
+
const version = r.version ? ` v${r.version}` : "";
|
|
81
|
+
if (r.ok) {
|
|
82
|
+
return `[@${label}]${version} ✅`;
|
|
83
|
+
}
|
|
84
|
+
const reason = r.errors[0]?.msg ?? "unknown";
|
|
85
|
+
return `[@${label}]${version} ⚠ DEGRADED — ${truncate(reason, 60)}`;
|
|
86
|
+
});
|
|
87
|
+
const okCount = packValidation.filter((r) => r.ok).length;
|
|
88
|
+
const summary = okCount === packValidation.length
|
|
89
|
+
? `${okCount}/${packValidation.length} ok`
|
|
90
|
+
: `${okCount}/${packValidation.length} degraded`;
|
|
91
|
+
return `pt packs: ${summary} | ${items.join(" | ")}`;
|
|
92
|
+
}
|
|
93
|
+
/** v15.x PR2(§6.7.6):description / error msg 截断辅助——单行 status 不被撑爆。 */
|
|
94
|
+
function truncate(s, max) {
|
|
95
|
+
return s.length > max ? `${s.slice(0, max - 3)}...` : s;
|
|
96
|
+
}
|
|
97
|
+
/** v15.x §4.4.4(缺口 5):/pt packs 详情命令——pack 诊断信息落点。
|
|
98
|
+
* pack.name/version/desc/asset 计数走这里,status 单行不再塞 desc。
|
|
99
|
+
* asset 计数:从 active bundle 的 workingSet.identity 索引按 pack.name 前缀过滤。 */
|
|
100
|
+
export function packsText(session) {
|
|
101
|
+
const pv = session.packValidation;
|
|
102
|
+
if (!pv || pv.length === 0) {
|
|
103
|
+
return "pt packs: (none loaded)";
|
|
104
|
+
}
|
|
105
|
+
const bundle = session.cachedBundles?.[0];
|
|
106
|
+
const ws = bundle?.workingSet;
|
|
107
|
+
const lines = [`pt packs (${pv.length} loaded):`];
|
|
108
|
+
for (const r of pv) {
|
|
109
|
+
// v15.x §4.4.4(缺口 4):reserved 显位置别名,settings 显 pack 名
|
|
110
|
+
const label = r.reservedAlias ?? r.pack;
|
|
111
|
+
const status = r.ok ? "✅" : "⚠ DEGRADED";
|
|
112
|
+
lines.push(` [@${label}] v${r.version} ${status} (${r.source})`);
|
|
113
|
+
// reserved 退化场景:pack.name=位置别名,不显 name 行
|
|
114
|
+
if (r.pack !== label) {
|
|
115
|
+
lines.push(` name: ${r.pack}`);
|
|
116
|
+
}
|
|
117
|
+
if (r.description) {
|
|
118
|
+
lines.push(` ${r.description}`);
|
|
119
|
+
}
|
|
120
|
+
// asset 计数(从 workingSet.identity 按 pack.name 前缀统计)
|
|
121
|
+
if (ws) {
|
|
122
|
+
const prefix = `${r.pack}/`;
|
|
123
|
+
const domains = countByPrefix(ws.domains.identity, prefix);
|
|
124
|
+
const blueprints = countByPrefix(ws.blueprints.identity, prefix);
|
|
125
|
+
const profiles = countByPrefix(ws.profiles.identity, prefix);
|
|
126
|
+
lines.push(` ${domains} domains, ${blueprints} blueprints, ${profiles} profiles`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return lines.join("\n");
|
|
130
|
+
}
|
|
131
|
+
/** 按 key 前缀计数(§4.4.4 packsText 辅助)。 */
|
|
132
|
+
function countByPrefix(map, prefix) {
|
|
133
|
+
if (typeof prefix !== "string")
|
|
134
|
+
return 0;
|
|
135
|
+
let n = 0;
|
|
136
|
+
for (const k of map.keys()) {
|
|
137
|
+
if (typeof k === "string" && k.startsWith(prefix))
|
|
138
|
+
n++;
|
|
139
|
+
}
|
|
140
|
+
return n;
|
|
141
|
+
}
|
|
142
|
+
/** /pt flows 内核:返回可用手册列表文本。无激活 Profile 返回提示串。
|
|
143
|
+
*
|
|
144
|
+
* v13.x(issue pt-turn-inject-not-profile-scoped):不再预过滤——传全集 domains 给 listManuals,
|
|
145
|
+
* adapter 内部用 setAgentContext 时存下的 profile 自行 filterDomainsByProfile 过滤。 */
|
|
146
|
+
export function flowsText(session) {
|
|
147
|
+
if (!session.cachedBundles || session.cachedBundles.length === 0 || !session.activeAdapter) {
|
|
148
|
+
return "无激活 Profile,先用 /pt-profile <name> 激活";
|
|
149
|
+
}
|
|
150
|
+
if (!session.cachedAgentContext || !session.cachedBlueprint) {
|
|
151
|
+
return "无激活 Profile,先用 /pt-profile <name> 激活";
|
|
152
|
+
}
|
|
153
|
+
const flows = session.activeAdapter.listManuals?.(session.cachedAgentContext, session.cachedBlueprint, session.cachedBundles[0].domains) ?? [];
|
|
154
|
+
if (flows.length === 0) {
|
|
155
|
+
return "当前 Profile 无可触发手册(turn 聚合组无含 Flows 段的 Domain)";
|
|
156
|
+
}
|
|
157
|
+
const lines = flows.map((f) => ` ${f.name} ${f.hint ?? ""} ← ${f.domain}`);
|
|
158
|
+
return `可用手册(输入 /手册名 参数 或 /manual:<domain-name> 触发 Turn Inject):\n${lines.join("\n")}`;
|
|
159
|
+
}
|
|
160
|
+
/** /pt full 内核:构建写入 .pt/cache/fulls/ 的完整 systemPrompt 字符串(v10.x 修复 pt-full-duplicate-segment)。
|
|
161
|
+
*
|
|
162
|
+
* 设计动机:消除 `/pt full` 与 PiAdapter `before_agent_start` 的双重拼接路径——
|
|
163
|
+
* - PiAdapter 每轮把 segment 拼到 base,写回 `agent.state.systemPrompt`(= `ctx.getSystemPrompt()`)
|
|
164
|
+
* - 第一轮 prompt 之后,`ctx.getSystemPrompt()` 已含 segment;旧版 `/pt full` 再拼一次 → 2× 重复
|
|
165
|
+
* - 根因:两份拼接实现通过隐式时序耦合,缺乏单一信息源
|
|
166
|
+
*
|
|
167
|
+
* 修复:把 `lastBuiltPrompt`(由 PiAdapter 的 `onInjected` 回调写入,正是 LLM 实际看到的 systemPrompt)
|
|
168
|
+
* 作为 canonical source。第一轮之前的 fallback:模拟下一次 LLM 会看到的注入(保留旧版语义)。
|
|
169
|
+
*
|
|
170
|
+
* 边界纪律:
|
|
171
|
+
* - 不动 PiAdapter(PiAdapter 行为正确,不重复注入)
|
|
172
|
+
* - 不动 Pi 上游 API(`getSystemPrompt` 语义不变)
|
|
173
|
+
* - 只动这一个函数体,外加调用方 `src/index.ts`
|
|
174
|
+
*/
|
|
175
|
+
export function buildFullPrompt(baseSystemPrompt, cachedSegment, lastBuiltPrompt) {
|
|
176
|
+
if (lastBuiltPrompt !== null) {
|
|
177
|
+
// 第一轮 prompt 之后:canonical source(= LLM 实际收到的 systemPrompt)
|
|
178
|
+
return lastBuiltPrompt;
|
|
179
|
+
}
|
|
180
|
+
if (cachedSegment) {
|
|
181
|
+
// 第一轮之前:模拟下一次 LLM 会看到的注入
|
|
182
|
+
return `${baseSystemPrompt}\n\n## 当前任务上下文\n\n${cachedSegment}`;
|
|
183
|
+
}
|
|
184
|
+
// 无 cachedSegment(未加载 Profile)
|
|
185
|
+
return baseSystemPrompt;
|
|
186
|
+
}
|
|
187
|
+
export function buildManualDoc(cwd, session, procedure, args) {
|
|
188
|
+
if (!procedure) {
|
|
189
|
+
return { content: "", filePath: "", error: "用法: /pt manual <procedure-name> [args...]" };
|
|
190
|
+
}
|
|
191
|
+
if (!session.cachedBundles || session.cachedBundles.length === 0 || !session.cachedBlueprint) {
|
|
192
|
+
return { content: "", filePath: "", error: "无激活 Profile,先用 /pt-profile <name> 激活" };
|
|
193
|
+
}
|
|
194
|
+
// v13.x(issue pt-turn-inject-not-profile-scoped):按 Profile scope 过滤 + 传 profile
|
|
195
|
+
// 让 /pt manual 在未引用该 domain 的 Profile 下找不到手册(与 /pt flows 一致)
|
|
196
|
+
const scoped = filterDomainsByProfile(session.cachedBundles[0].domains, session.cachedProfile);
|
|
197
|
+
const tpl = findFlowInBlueprint(session.cachedBlueprint, scoped, procedure, session.cachedProfile);
|
|
198
|
+
if (!tpl) {
|
|
199
|
+
return {
|
|
200
|
+
content: "",
|
|
201
|
+
filePath: "",
|
|
202
|
+
error: `未找到手册: ${procedure}(用 /pt flows 查可用手册)`,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const bound = bindFlowTemplate(tpl, args);
|
|
206
|
+
const domainName = session.cachedBundles[0].domains.find((d) => {
|
|
207
|
+
// Phase term-P9.2:FlowTemplate 存 ## Flows 段(不是 ## Manual)。
|
|
208
|
+
const flows = d.modules[MOD_FLOWS];
|
|
209
|
+
return (Array.isArray(flows) &&
|
|
210
|
+
flows.some((t) => isFlowTemplateLike(t) && t.name === procedure));
|
|
211
|
+
})?.name ?? "";
|
|
212
|
+
const now = new Date().toISOString();
|
|
213
|
+
const ts = Date.now();
|
|
214
|
+
const lines = [];
|
|
215
|
+
lines.push("---");
|
|
216
|
+
lines.push(`procedure: ${procedure}`);
|
|
217
|
+
lines.push(`domain: ${domainName}`);
|
|
218
|
+
lines.push(`created: ${now}`);
|
|
219
|
+
lines.push("status: in-progress");
|
|
220
|
+
lines.push(`args: ${args || "(无)"}`);
|
|
221
|
+
lines.push("---");
|
|
222
|
+
lines.push("");
|
|
223
|
+
lines.push(`# ${procedure} 实例`);
|
|
224
|
+
lines.push("");
|
|
225
|
+
const boundLines = bound.split("\n");
|
|
226
|
+
let stepCount = 0;
|
|
227
|
+
for (const line of boundLines) {
|
|
228
|
+
if (line.startsWith("#"))
|
|
229
|
+
continue;
|
|
230
|
+
if (line.startsWith("_"))
|
|
231
|
+
continue;
|
|
232
|
+
const stepMatch = line.match(/^(\d+)\.\s+(.*)$/);
|
|
233
|
+
if (stepMatch) {
|
|
234
|
+
stepCount++;
|
|
235
|
+
lines.push(`- [ ] ${stepMatch[2]}`);
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
// observe 行(bindFlowTemplate 渲染的 " - 验证参照:xxx")→ checklist 子项
|
|
239
|
+
if (line.includes("验证参照:")) {
|
|
240
|
+
lines.push(` ${line.trim()}`);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
lines.push(line);
|
|
244
|
+
}
|
|
245
|
+
lines.push("");
|
|
246
|
+
lines.push("## 执行状态");
|
|
247
|
+
lines.push("| Step | Outcome | Message |");
|
|
248
|
+
lines.push("|---|---|---|");
|
|
249
|
+
for (let i = 1; i <= stepCount; i++) {
|
|
250
|
+
lines.push(`| ${i} | — | |`);
|
|
251
|
+
}
|
|
252
|
+
lines.push("");
|
|
253
|
+
lines.push("## 产物");
|
|
254
|
+
lines.push("<!-- 执行后用 edit 在此追加:路径 + 动作(created/modified) + 日期 -->");
|
|
255
|
+
lines.push("");
|
|
256
|
+
lines.push("## 更新指引");
|
|
257
|
+
lines.push("执行完每个 step 后:用 edit 把对应 `- [ ]` 改成 `- [x]`。");
|
|
258
|
+
lines.push("验证后:用 edit 把 ## 执行状态表 对应行的 `—` 改为 COMPLETED / DEVIATED / INCONCLUSIVE + Message。");
|
|
259
|
+
lines.push("全部完成后:用 edit 在 ## 产物 下追加创建/修改的文件路径(每行一条)。");
|
|
260
|
+
lines.push("status 全部完成后可改为 completed。");
|
|
261
|
+
const content = lines.join("\n");
|
|
262
|
+
const filePath = join(cwd, MANUAL_DIR, `${procedure}-${ts}.md`);
|
|
263
|
+
return { content, filePath };
|
|
264
|
+
}
|
|
265
|
+
/** /pt check 内核:从 session.assetHealthIssues(已扫)格式化输出。
|
|
266
|
+
* v14.x(issue §Layer 3):session_start 已扫,/pt check 直接格式化——不重复扫描。
|
|
267
|
+
* 未扫(null)→ 返回提示串 + 0 issue。
|
|
268
|
+
*
|
|
269
|
+
* 输出风格(biome/tsc 同源):
|
|
270
|
+
*
|
|
271
|
+
* ysl-developer.profile.md
|
|
272
|
+
* × [error] ## 会话背景 缺 ### Modules
|
|
273
|
+
* hint: 在 H2 段下加 `### Modules: [Scene, ...]`
|
|
274
|
+
*
|
|
275
|
+
* × 6 errors, 0 warnings
|
|
276
|
+
* hint: 运行 `/pt check --fix` 自动应用已知 migration
|
|
277
|
+
*
|
|
278
|
+
* --profile X:只列该 profile 的 issue;其它 profile 的忽略(v1 简化)。
|
|
279
|
+
*/
|
|
280
|
+
export function checkText(session, opts = {}) {
|
|
281
|
+
const allIssues = session.assetHealthIssues;
|
|
282
|
+
if (allIssues === null) {
|
|
283
|
+
return {
|
|
284
|
+
output: "未扫描。重启 session 或运行 scanProjectHealth。",
|
|
285
|
+
issueCount: 0,
|
|
286
|
+
errors: 0,
|
|
287
|
+
warnings: 0,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
// 过滤
|
|
291
|
+
let issues;
|
|
292
|
+
if (opts.profileName) {
|
|
293
|
+
issues = allIssues.filter((i) => i.name === opts.profileName);
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
issues = allIssues;
|
|
297
|
+
}
|
|
298
|
+
if (issues.length === 0) {
|
|
299
|
+
const okMsg = opts.profileName
|
|
300
|
+
? `✓ Profile「${opts.profileName}」配置正常`
|
|
301
|
+
: "✓ 项目所有 Profile 配置正常";
|
|
302
|
+
return { output: okMsg, issueCount: 0, errors: 0, warnings: 0 };
|
|
303
|
+
}
|
|
304
|
+
// 按 profile 分组(biome 风格:file → issues 列表)
|
|
305
|
+
const byProfile = new Map();
|
|
306
|
+
for (const i of issues) {
|
|
307
|
+
const arr = byProfile.get(i.name) ?? [];
|
|
308
|
+
arr.push(i);
|
|
309
|
+
byProfile.set(i.name, arr);
|
|
310
|
+
}
|
|
311
|
+
const lines = [];
|
|
312
|
+
for (const [profileName, profIssues] of byProfile) {
|
|
313
|
+
lines.push(`${profileName}.profile.md`);
|
|
314
|
+
for (const i of profIssues) {
|
|
315
|
+
const mark = i.severity === "error" ? "×" : "⚠";
|
|
316
|
+
const sev = i.severity === "error" ? "error" : "warning";
|
|
317
|
+
const where = i.field ? ` ${i.field}` : "";
|
|
318
|
+
lines.push(` ${mark} [${sev}]${where} ${i.msg}`);
|
|
319
|
+
if (i.hint)
|
|
320
|
+
lines.push(` hint: ${i.hint}`);
|
|
321
|
+
if (i.fix && !opts.fix)
|
|
322
|
+
lines.push(` fix: ${i.fix}`);
|
|
323
|
+
}
|
|
324
|
+
lines.push("");
|
|
325
|
+
}
|
|
326
|
+
// trim trailing blank
|
|
327
|
+
if (lines.length > 0 && lines[lines.length - 1] === "")
|
|
328
|
+
lines.pop();
|
|
329
|
+
// summary
|
|
330
|
+
const errorCount = issues.filter((i) => i.severity === "error").length;
|
|
331
|
+
const warningCount = issues.filter((i) => i.severity === "warning").length;
|
|
332
|
+
lines.push("");
|
|
333
|
+
lines.push(`× ${errorCount} error${errorCount > 1 ? "s" : ""}, ${warningCount} warning${warningCount > 1 ? "s" : ""}`);
|
|
334
|
+
lines.push(` hint: 查看 .pt/docs/migrations/v9.0-to-v9.1-modules.md 修复指南`);
|
|
335
|
+
if (errorCount > 0 && !opts.fix) {
|
|
336
|
+
lines.push(` hint: 运行 \`/pt check --fix\` 自动应用已知 migration(v2 范围)`);
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
output: lines.join("\n"),
|
|
340
|
+
issueCount: issues.length,
|
|
341
|
+
errors: errorCount,
|
|
342
|
+
warnings: warningCount,
|
|
343
|
+
};
|
|
344
|
+
}
|