@pennixrv/trellis 0.7.1-beta.9 → 0.7.2-beta.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/dist/cli/index.js +4 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +39 -26
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/teamwork/adapters/acp.d.ts +20 -0
- package/dist/commands/teamwork/adapters/acp.d.ts.map +1 -0
- package/dist/commands/teamwork/adapters/acp.js +268 -0
- package/dist/commands/teamwork/adapters/acp.js.map +1 -0
- package/dist/commands/teamwork/adapters/claude.d.ts +1 -0
- package/dist/commands/teamwork/adapters/claude.d.ts.map +1 -1
- package/dist/commands/teamwork/adapters/claude.js +5 -0
- package/dist/commands/teamwork/adapters/claude.js.map +1 -1
- package/dist/commands/teamwork/adapters/codex.d.ts +3 -2
- package/dist/commands/teamwork/adapters/codex.d.ts.map +1 -1
- package/dist/commands/teamwork/adapters/codex.js +14 -15
- package/dist/commands/teamwork/adapters/codex.js.map +1 -1
- package/dist/commands/teamwork/adapters/index.d.ts +23 -1
- package/dist/commands/teamwork/adapters/index.d.ts.map +1 -1
- package/dist/commands/teamwork/adapters/index.js +163 -24
- package/dist/commands/teamwork/adapters/index.js.map +1 -1
- package/dist/commands/teamwork/agent-loader.d.ts +2 -1
- package/dist/commands/teamwork/agent-loader.d.ts.map +1 -1
- package/dist/commands/teamwork/agent-loader.js +2 -1
- package/dist/commands/teamwork/agent-loader.js.map +1 -1
- package/dist/commands/teamwork/artifact.d.ts +33 -10
- package/dist/commands/teamwork/artifact.d.ts.map +1 -1
- package/dist/commands/teamwork/artifact.js +182 -50
- package/dist/commands/teamwork/artifact.js.map +1 -1
- package/dist/commands/teamwork/batch-reservation.d.ts +16 -0
- package/dist/commands/teamwork/batch-reservation.d.ts.map +1 -0
- package/dist/commands/teamwork/batch-reservation.js +43 -0
- package/dist/commands/teamwork/batch-reservation.js.map +1 -0
- package/dist/commands/teamwork/batch.d.ts +22 -0
- package/dist/commands/teamwork/batch.d.ts.map +1 -0
- package/dist/commands/teamwork/batch.js +394 -0
- package/dist/commands/teamwork/batch.js.map +1 -0
- package/dist/commands/teamwork/context-loader.d.ts +1 -1
- package/dist/commands/teamwork/context-loader.d.ts.map +1 -1
- package/dist/commands/teamwork/context-loader.js +19 -6
- package/dist/commands/teamwork/context-loader.js.map +1 -1
- package/dist/commands/teamwork/coordination.d.ts +88 -0
- package/dist/commands/teamwork/coordination.d.ts.map +1 -0
- package/dist/commands/teamwork/coordination.js +153 -0
- package/dist/commands/teamwork/coordination.js.map +1 -0
- package/dist/commands/teamwork/coordinator.d.ts +17 -3
- package/dist/commands/teamwork/coordinator.d.ts.map +1 -1
- package/dist/commands/teamwork/coordinator.js +772 -289
- package/dist/commands/teamwork/coordinator.js.map +1 -1
- package/dist/commands/teamwork/create.d.ts +1 -0
- package/dist/commands/teamwork/create.d.ts.map +1 -1
- package/dist/commands/teamwork/create.js +2 -1
- package/dist/commands/teamwork/create.js.map +1 -1
- package/dist/commands/teamwork/dev-parse-trace.d.ts +2 -1
- package/dist/commands/teamwork/dev-parse-trace.d.ts.map +1 -1
- package/dist/commands/teamwork/dev-parse-trace.js +2 -0
- package/dist/commands/teamwork/dev-parse-trace.js.map +1 -1
- package/dist/commands/teamwork/foreground-wait.d.ts +6 -0
- package/dist/commands/teamwork/foreground-wait.d.ts.map +1 -0
- package/dist/commands/teamwork/foreground-wait.js +65 -0
- package/dist/commands/teamwork/foreground-wait.js.map +1 -0
- package/dist/commands/teamwork/guard.d.ts +2 -2
- package/dist/commands/teamwork/guard.d.ts.map +1 -1
- package/dist/commands/teamwork/guard.js +23 -5
- package/dist/commands/teamwork/guard.js.map +1 -1
- package/dist/commands/teamwork/index.d.ts.map +1 -1
- package/dist/commands/teamwork/index.js +139 -10
- package/dist/commands/teamwork/index.js.map +1 -1
- package/dist/commands/teamwork/kill.d.ts +2 -0
- package/dist/commands/teamwork/kill.d.ts.map +1 -1
- package/dist/commands/teamwork/kill.js +79 -38
- package/dist/commands/teamwork/kill.js.map +1 -1
- package/dist/commands/teamwork/messages.d.ts.map +1 -1
- package/dist/commands/teamwork/messages.js +3 -0
- package/dist/commands/teamwork/messages.js.map +1 -1
- package/dist/commands/teamwork/plan.d.ts +22 -0
- package/dist/commands/teamwork/plan.d.ts.map +1 -0
- package/dist/commands/teamwork/plan.js +288 -0
- package/dist/commands/teamwork/plan.js.map +1 -0
- package/dist/commands/teamwork/process-identity.d.ts +3 -0
- package/dist/commands/teamwork/process-identity.d.ts.map +1 -0
- package/dist/commands/teamwork/process-identity.js +24 -0
- package/dist/commands/teamwork/process-identity.js.map +1 -0
- package/dist/commands/teamwork/profiles.d.ts +43 -6
- package/dist/commands/teamwork/profiles.d.ts.map +1 -1
- package/dist/commands/teamwork/profiles.js +138 -110
- package/dist/commands/teamwork/profiles.js.map +1 -1
- package/dist/commands/teamwork/prompt.d.ts +4 -0
- package/dist/commands/teamwork/prompt.d.ts.map +1 -0
- package/dist/commands/teamwork/prompt.js +33 -0
- package/dist/commands/teamwork/prompt.js.map +1 -0
- package/dist/commands/teamwork/result.d.ts +54 -0
- package/dist/commands/teamwork/result.d.ts.map +1 -0
- package/dist/commands/teamwork/result.js +94 -0
- package/dist/commands/teamwork/result.js.map +1 -0
- package/dist/commands/teamwork/rm.d.ts.map +1 -1
- package/dist/commands/teamwork/rm.js +64 -64
- package/dist/commands/teamwork/rm.js.map +1 -1
- package/dist/commands/teamwork/run.d.ts +5 -0
- package/dist/commands/teamwork/run.d.ts.map +1 -1
- package/dist/commands/teamwork/run.js +120 -24
- package/dist/commands/teamwork/run.js.map +1 -1
- package/dist/commands/teamwork/runtime.d.ts +9 -0
- package/dist/commands/teamwork/runtime.d.ts.map +1 -0
- package/dist/commands/teamwork/runtime.js +372 -0
- package/dist/commands/teamwork/runtime.js.map +1 -0
- package/dist/commands/teamwork/send.d.ts +1 -0
- package/dist/commands/teamwork/send.d.ts.map +1 -1
- package/dist/commands/teamwork/send.js +2 -1
- package/dist/commands/teamwork/send.js.map +1 -1
- package/dist/commands/teamwork/spawn.d.ts +10 -3
- package/dist/commands/teamwork/spawn.d.ts.map +1 -1
- package/dist/commands/teamwork/spawn.js +41 -29
- package/dist/commands/teamwork/spawn.js.map +1 -1
- package/dist/commands/teamwork/store/lock.js +28 -4
- package/dist/commands/teamwork/store/lock.js.map +1 -1
- package/dist/commands/teamwork/supervisor/inbox.d.ts +1 -0
- package/dist/commands/teamwork/supervisor/inbox.d.ts.map +1 -1
- package/dist/commands/teamwork/supervisor/inbox.js +28 -9
- package/dist/commands/teamwork/supervisor/inbox.js.map +1 -1
- package/dist/commands/teamwork/supervisor/stdout.d.ts.map +1 -1
- package/dist/commands/teamwork/supervisor/stdout.js +2 -3
- package/dist/commands/teamwork/supervisor/stdout.js.map +1 -1
- package/dist/commands/teamwork/supervisor/warning.d.ts.map +1 -1
- package/dist/commands/teamwork/supervisor/warning.js +2 -3
- package/dist/commands/teamwork/supervisor/warning.js.map +1 -1
- package/dist/commands/teamwork/supervisor.d.ts +5 -0
- package/dist/commands/teamwork/supervisor.d.ts.map +1 -1
- package/dist/commands/teamwork/supervisor.js +21 -12
- package/dist/commands/teamwork/supervisor.js.map +1 -1
- package/dist/commands/teamwork/teammate-adapters.d.ts +0 -3
- package/dist/commands/teamwork/teammate-adapters.d.ts.map +1 -1
- package/dist/commands/teamwork/teammate-adapters.js +9 -54
- package/dist/commands/teamwork/teammate-adapters.js.map +1 -1
- package/dist/commands/teamwork/teammate-config.d.ts +5 -1
- package/dist/commands/teamwork/teammate-config.d.ts.map +1 -1
- package/dist/commands/teamwork/teammate-config.js +62 -19
- package/dist/commands/teamwork/teammate-config.js.map +1 -1
- package/dist/commands/teamwork/teammate-launch.d.ts +14 -4
- package/dist/commands/teamwork/teammate-launch.d.ts.map +1 -1
- package/dist/commands/teamwork/teammate-launch.js +129 -20
- package/dist/commands/teamwork/teammate-launch.js.map +1 -1
- package/dist/commands/teamwork/wait.d.ts +2 -0
- package/dist/commands/teamwork/wait.d.ts.map +1 -1
- package/dist/commands/teamwork/wait.js +44 -3
- package/dist/commands/teamwork/wait.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +4 -3
- package/dist/commands/update.js.map +1 -1
- package/dist/configurators/workflow.d.ts.map +1 -1
- package/dist/configurators/workflow.js +14 -32
- package/dist/configurators/workflow.js.map +1 -1
- package/dist/migrations/manifests/0.7.1-beta.10.json +9 -0
- package/dist/migrations/manifests/0.7.1-beta.11.json +9 -0
- package/dist/migrations/manifests/0.7.1-beta.12.json +9 -0
- package/dist/migrations/manifests/0.7.1-beta.13.json +9 -0
- package/dist/migrations/manifests/0.7.1-beta.14.json +11 -0
- package/dist/migrations/manifests/0.7.1-beta.15.json +9 -0
- package/dist/migrations/manifests/0.7.1-beta.16.json +9 -0
- package/dist/migrations/manifests/0.7.1-beta.17.json +9 -0
- package/dist/migrations/manifests/0.7.1-beta.18.json +9 -0
- package/dist/migrations/manifests/0.7.1-beta.19.json +9 -0
- package/dist/migrations/manifests/0.7.1-beta.6.json +1 -1
- package/dist/migrations/manifests/0.7.2-beta.0.json +11 -0
- package/dist/templates/codex/hooks/session-start.py +14 -11
- package/dist/templates/codex/hooks.json +10 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/multi-agent-teamwork.md +14 -2
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +1 -1
- package/dist/templates/common/bundled-skills/trellis-solution-design-and-convergence/workflow.md +4 -0
- package/dist/templates/common/bundled-skills/trellis-task-implementation/workflow.md +6 -0
- package/dist/templates/common/bundled-skills/trellis-teamwork/SKILL.md +14 -4
- package/dist/templates/common/bundled-skills/trellis-teamwork/references/coordination-modes.md +31 -2
- package/dist/templates/common/bundled-skills/trellis-teamwork/references/teammate-configuration-matrix.md +37 -31
- package/dist/templates/common/bundled-skills/trellis-teamwork/references/teammate-processes.md +94 -24
- package/dist/templates/common/bundled-skills/trellis-teamwork/references/teamwork-plan-construction.md +112 -20
- package/dist/templates/copilot/hooks/session-start.py +14 -11
- package/dist/templates/copilot/index.d.ts +1 -6
- package/dist/templates/copilot/index.d.ts.map +1 -1
- package/dist/templates/copilot/index.js +1 -14
- package/dist/templates/copilot/index.js.map +1 -1
- package/dist/templates/markdown/spec/backend/index.md.txt +4 -35
- package/dist/templates/markdown/spec/frontend/index.md.txt +4 -36
- package/dist/templates/omp/extensions/trellis/index.ts.txt +1 -1
- package/dist/templates/pi/extensions/trellis/index.ts.txt +17 -1
- package/dist/templates/shared-hooks/guard-teamwork-wait.py +53 -0
- package/dist/templates/shared-hooks/index.d.ts +1 -1
- package/dist/templates/shared-hooks/index.d.ts.map +1 -1
- package/dist/templates/shared-hooks/index.js +1 -0
- package/dist/templates/shared-hooks/index.js.map +1 -1
- package/dist/templates/shared-hooks/inject-workflow-state.py +8 -3
- package/dist/templates/shared-hooks/session-start.py +16 -12
- package/dist/templates/trellis/agents/delegated-worktree-primary-agent.md +9 -0
- package/dist/templates/trellis/agents/profiles/architecture.md +9 -0
- package/dist/templates/trellis/agents/profiles/diagnosis.md +9 -0
- package/dist/templates/trellis/agents/profiles/exploration.md +9 -0
- package/dist/templates/trellis/agents/profiles/research.md +9 -0
- package/dist/templates/trellis/agents/profiles/review.md +9 -0
- package/dist/templates/trellis/agents/profiles/verification.md +9 -0
- package/dist/templates/trellis/agents/teammate-profiles.json +56 -4
- package/dist/templates/trellis/agents/teammate.md +4 -63
- package/dist/templates/trellis/config.yaml +2 -5
- package/dist/templates/trellis/index.d.ts +1 -0
- package/dist/templates/trellis/index.d.ts.map +1 -1
- package/dist/templates/trellis/index.js +16 -4
- package/dist/templates/trellis/index.js.map +1 -1
- package/dist/templates/trellis/scripts/common/task_continuity.py +54 -28
- package/dist/templates/trellis/scripts/common/task_store.py +7 -2
- package/dist/templates/trellis/scripts/common/task_workflow.py +270 -18
- package/dist/templates/trellis/scripts/task.py +27 -3
- package/dist/templates/trellis/teamwork.json +10 -0
- package/dist/templates/trellis/workflow.md +7 -0
- package/dist/utils/asset-backup.d.ts.map +1 -1
- package/dist/utils/asset-backup.js +10 -4
- package/dist/utils/asset-backup.js.map +1 -1
- package/dist/utils/template-fetcher.d.ts +4 -19
- package/dist/utils/template-fetcher.d.ts.map +1 -1
- package/dist/utils/template-fetcher.js +9 -45
- package/dist/utils/template-fetcher.js.map +1 -1
- package/package.json +3 -2
- package/dist/templates/copilot/prompts/before-dev.prompt.md +0 -39
- package/dist/templates/copilot/prompts/brainstorm.prompt.md +0 -13
- package/dist/templates/copilot/prompts/break-loop.prompt.md +0 -129
- package/dist/templates/copilot/prompts/check-cross-layer.prompt.md +0 -170
- package/dist/templates/copilot/prompts/check.prompt.md +0 -110
- package/dist/templates/copilot/prompts/create-command.prompt.md +0 -116
- package/dist/templates/copilot/prompts/finish-work.prompt.md +0 -22
- package/dist/templates/copilot/prompts/integrate-skill.prompt.md +0 -223
- package/dist/templates/copilot/prompts/onboard.prompt.md +0 -362
- package/dist/templates/copilot/prompts/record-session.prompt.md +0 -58
- package/dist/templates/copilot/prompts/start.prompt.md +0 -65
- package/dist/templates/copilot/prompts/update-spec.prompt.md +0 -358
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# 已知故障诊断(diagnosis)
|
|
2
|
+
|
|
3
|
+
你负责诊断 brief 中已经发生的故障。共同角色卡规定的范围、结果写入和停止条件始终适用。
|
|
4
|
+
|
|
5
|
+
输入应包含实际症状与完整错误、期望行为、环境与版本、复现条件和近期变更。先建立事实及可重复的最小触发,再提出少量可区分的假设,按信息增益选择已授权的观测或验证,记录支持与反证。每次失败先核对现场,不连续猜测或试改。
|
|
6
|
+
|
|
7
|
+
结果应包含故障链、已排除假设、最可能根因及证据强度、剩余未知、最小修复方向和验证建议。根因证据充分或受限无法继续时停止,不把测试失败本身当作根因。复杂方法按项目技能来源规则使用,不复制用户级 Skill 内容进角色卡。
|
|
8
|
+
|
|
9
|
+
必要输入缺失、角色与 brief 冲突或需要越界操作时,报告阻断。不编写修复或顺带重构,不替协调者接受结果,不继续委派。
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# 本地源码探索(exploration)
|
|
2
|
+
|
|
3
|
+
你负责回答 brief 中的本地源码问题,建立可接续的代码与证据地图。共同角色卡规定的范围、结果写入和停止条件始终适用。
|
|
4
|
+
|
|
5
|
+
输入应包含问题、仓库与基线、主题范围、已有锚点和所需深度。先确定入口、定义和调用路径,按项目来源规则使用有效索引或有界搜索,再阅读支持结论的当前源码。追踪相关数据流、关键条件、异常路径、依赖和测试入口;区分实际源码、文档陈述和推断。
|
|
6
|
+
|
|
7
|
+
结果应直接回答问题,给出文件、符号及适用行号,说明关键路径、关系、影响边界、反例、证据不足处和建议的下一阅读点。必要路径和边界已核对后停止;不要无限扫描全库,不把代码地图写成未经验证的架构推荐或根因定论。
|
|
8
|
+
|
|
9
|
+
必要输入缺失、角色与 brief 冲突或需要越界操作时,报告阻断。不编写产品源码、测试或修复,不替协调者接受结果,不继续委派。
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# 外部资料研究(research)
|
|
2
|
+
|
|
3
|
+
你负责按任务输入核对资料与先例;managed batch 以 brief 为任务依据,交互式任务以当前消息为依据。共同角色卡规定的范围、结果写入和停止条件始终适用。
|
|
4
|
+
|
|
5
|
+
输入应包含研究问题及适用的约束、版本和来源要求。需要外部研究时,先拆出可证伪的问题,再核对官方文档、标准、维护者源码或明确标注的次级材料,记录版本、日期、反证和适用边界。仅处理给定材料的任务不要求检索外部资料。遵循明确分配的检索入口;搜索摘要只是候选,不等于已读全文。
|
|
6
|
+
|
|
7
|
+
结果应包含有出处的结论或比较;使用外部来源时附可核验链接、版本或检索日期。只有任务要求时才分析对当前项目的影响。明确区分已核实、推断、冲突和未知。证据足以支持当前决定后停止;网络或来源访问失败应如实报告,不编造检索结果,不以社区说法代替官方合同。
|
|
8
|
+
|
|
9
|
+
必要输入缺失、角色与任务冲突或需要越界操作时,报告阻断。不编写产品源码、测试或修复,不替协调者接受结果,不继续委派。
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# 变更与设计审查(review)
|
|
2
|
+
|
|
3
|
+
你负责审查 brief 明确指定的候选、差异、提交或设计。共同角色卡规定的范围、结果写入和停止条件始终适用。
|
|
4
|
+
|
|
5
|
+
输入应包含候选、需求基线、本次关注点和适用验收。沿真实调用方和相关上下文核对正确性、需求覆盖、回归、数据或安全风险及测试缺口。不能只看 diff,也不能按检查表制造问题或强加风格偏好。
|
|
6
|
+
|
|
7
|
+
结果按 [严重]、[主要]、[轻微] 排序;每项说明触发条件、实际影响、准确定位与证据和修复方向。无发现时说明检查范围及剩余风险,不能据此宣称没有 bug。默认不运行会修改现场的构建或安装;确需验证时遵守 brief 已有授权,或建议由 verification 执行。
|
|
8
|
+
|
|
9
|
+
候选的相关调用与关键风险已核对后停止。必要输入缺失、角色与 brief 冲突或需要越界操作时,报告阻断。不编写产品源码、测试或修复,不替协调者接受结果,不继续委派。
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# 行为与接受条件验证(verification)
|
|
2
|
+
|
|
3
|
+
你负责检验 brief 中明确的行为声明和接受条件。共同角色卡规定的范围、结果写入和停止条件始终适用。
|
|
4
|
+
|
|
5
|
+
输入应包含待验证声明、期望行为、候选版本与环境、已授权命令,以及产物、临时目录和清理约定。先将声明映射到能够证实或证伪的检查,核对实际版本与环境,再执行适用的已有测试、构建或复现步骤并解释结果。不要无故重复全套检查或添加只镜像实现的断言。
|
|
6
|
+
|
|
7
|
+
结果应将声明、检查和实际结果对应起来,记录退出事实、关键证据、pass/fail/not_run/受限、环境差异、残留资源及不能据此推断的结论。工具输出、缓存和临时复现材料可能产生文件副作用,须遵守 brief 的允许位置及清理约定,不能声称绝无副作用。
|
|
8
|
+
|
|
9
|
+
适用声明已有证据或受限无法继续时停止。缺少账号、环境或授权时停止相关检查并报告,不自行安装、登录、发布或写产品测试。不替协调者接受结果,不继续委派;根因辨析交给 diagnosis。
|
|
@@ -1,8 +1,60 @@
|
|
|
1
1
|
{
|
|
2
|
+
"schema_version": 2,
|
|
3
|
+
"default_profile": "exploration",
|
|
2
4
|
"profiles": {
|
|
3
|
-
"architecture": {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
"architecture": {
|
|
6
|
+
"role": "profiles/architecture.md",
|
|
7
|
+
"default_configuration": "codex-sol",
|
|
8
|
+
"configurations": {
|
|
9
|
+
"codex-sol": { "provider": "codex", "model": "gpt-6.1-sol", "reasoning_effort": "xhigh" },
|
|
10
|
+
"copilot-sol": { "provider": "copilot", "model": "gpt-6.1-sol", "reasoning_effort": "xhigh" },
|
|
11
|
+
"copilot-opus": { "provider": "copilot", "model": "claude-opus-5.5", "reasoning_effort": "xhigh" }
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"review": {
|
|
15
|
+
"role": "profiles/review.md",
|
|
16
|
+
"default_configuration": "codex-sol",
|
|
17
|
+
"configurations": {
|
|
18
|
+
"codex-sol": { "provider": "codex", "model": "gpt-6.1-sol", "reasoning_effort": "high" },
|
|
19
|
+
"copilot-sol": { "provider": "copilot", "model": "gpt-6.1-sol", "reasoning_effort": "high" },
|
|
20
|
+
"copilot-opus": { "provider": "copilot", "model": "claude-opus-5.5", "reasoning_effort": "high" }
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"research": {
|
|
24
|
+
"role": "profiles/research.md",
|
|
25
|
+
"default_configuration": "codex-sol",
|
|
26
|
+
"configurations": {
|
|
27
|
+
"codex-sol": { "provider": "codex", "model": "gpt-6.1-sol", "reasoning_effort": "high" },
|
|
28
|
+
"copilot-sol": { "provider": "copilot", "model": "gpt-6.1-sol", "reasoning_effort": "high" },
|
|
29
|
+
"copilot-sonnet": { "provider": "copilot", "model": "claude-sonnet-5.5", "reasoning_effort": "high" }
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"verification": {
|
|
33
|
+
"role": "profiles/verification.md",
|
|
34
|
+
"default_configuration": "codex-sol",
|
|
35
|
+
"configurations": {
|
|
36
|
+
"codex-sol": { "provider": "codex", "model": "gpt-6.1-sol", "reasoning_effort": "high" },
|
|
37
|
+
"copilot-sol": { "provider": "copilot", "model": "gpt-6.1-sol", "reasoning_effort": "high" },
|
|
38
|
+
"copilot-sonnet": { "provider": "copilot", "model": "claude-sonnet-5.5", "reasoning_effort": "high" }
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"exploration": {
|
|
42
|
+
"role": "profiles/exploration.md",
|
|
43
|
+
"default_configuration": "codex-sol",
|
|
44
|
+
"configurations": {
|
|
45
|
+
"codex-sol": { "provider": "codex", "model": "gpt-6.1-sol", "reasoning_effort": "high" },
|
|
46
|
+
"copilot-sol": { "provider": "copilot", "model": "gpt-6.1-sol", "reasoning_effort": "high" },
|
|
47
|
+
"copilot-sonnet": { "provider": "copilot", "model": "claude-sonnet-5.5", "reasoning_effort": "high" }
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"diagnosis": {
|
|
51
|
+
"role": "profiles/diagnosis.md",
|
|
52
|
+
"default_configuration": "codex-sol",
|
|
53
|
+
"configurations": {
|
|
54
|
+
"codex-sol": { "provider": "codex", "model": "gpt-6.1-sol", "reasoning_effort": "high" },
|
|
55
|
+
"copilot-sol": { "provider": "copilot", "model": "gpt-6.1-sol", "reasoning_effort": "high" },
|
|
56
|
+
"copilot-opus": { "provider": "copilot", "model": "claude-opus-5.5", "reasoning_effort": "high" }
|
|
57
|
+
}
|
|
58
|
+
}
|
|
7
59
|
}
|
|
8
60
|
}
|
|
@@ -6,69 +6,10 @@ labels: [trellis, teammate]
|
|
|
6
6
|
|
|
7
7
|
# Teammate (Teamwork runtime)
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
independently reviewable investigation, research, review, verification, or
|
|
11
|
-
evidence. The coordinator owns dispatch, retry, acceptance, and final
|
|
12
|
-
disposition.
|
|
9
|
+
你只完成协调者分配的研究、审查、验证、证据整理或建议,交付可独立核验的结论、证据、限制和阻断。不要实施产品代码,不修改源码、测试、受保护配置、任务状态或 Git 状态;只写本次明确指定的结果产物。
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
assignment,
|
|
16
|
-
the paths are:
|
|
11
|
+
只使用本次分配的来源和上下文。需要本地探索时,可在指定范围内检索文件;注入的材料是入口,不代表已提供全部来源。不读取或使用环境中的个人、历史会话或跨项目记忆,包括记忆工具;无法将其与必要证据分开时如实报告限制。
|
|
17
12
|
|
|
18
|
-
|
|
19
|
-
.trellis/tasks/<task-dir>/teammates/<batch>/<assignment>/brief.json
|
|
20
|
-
.trellis/tasks/<task-dir>/teammates/<batch>/<assignment>/queue.json
|
|
21
|
-
.trellis/tasks/<task-dir>/teammates/<batch>/<assignment>/attempts/<attempt-id>/claim.json
|
|
22
|
-
.trellis/tasks/<task-dir>/teammates/<batch>/<assignment>/attempts/<attempt-id>/worklog.md
|
|
23
|
-
.trellis/tasks/<task-dir>/teammates/<batch>/<assignment>/attempts/<attempt-id>/report.json
|
|
24
|
-
```
|
|
13
|
+
工具可用和权限自动允许不扩大你的任务职责,也不证明存在文件系统或记忆隔离。不创建任务或 teammate,不通过后端原生能力继续委派,不自行重试,不替主代理接受结果。
|
|
25
14
|
|
|
26
|
-
|
|
27
|
-
and create exactly one pending report for this attempt using this JSON shape:
|
|
28
|
-
|
|
29
|
-
```json
|
|
30
|
-
{
|
|
31
|
-
"schema_version": 1,
|
|
32
|
-
"task_id": "<task-id>",
|
|
33
|
-
"batch_id": "<batch-id>",
|
|
34
|
-
"assignment_id": "<assignment-id>",
|
|
35
|
-
"attempt_id": "<attempt-id>",
|
|
36
|
-
"teammate_id": "<teammate-id>",
|
|
37
|
-
"plan_hash": "<plan_hash from the claim>",
|
|
38
|
-
"phase_id": "<phase_id from the frozen plan>",
|
|
39
|
-
"task_route_revision": "<task_route_revision from the frozen plan>",
|
|
40
|
-
"input_revision": "<input_revision from the frozen plan>",
|
|
41
|
-
"status": "complete",
|
|
42
|
-
"source_digest": "<source_digest from the brief>",
|
|
43
|
-
"evidence": [
|
|
44
|
-
{
|
|
45
|
-
"id": "<evidence-id>",
|
|
46
|
-
"locator": "<path or symbol>",
|
|
47
|
-
"summary": "<finding>"
|
|
48
|
-
}
|
|
49
|
-
]
|
|
50
|
-
}
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Copy the assigned identity and revisions from the coordinator's frozen launch
|
|
54
|
-
context and claim. Do not infer them from another task, plan, or attempt. If
|
|
55
|
-
that context is missing, report the blocker instead of inventing values.
|
|
56
|
-
|
|
57
|
-
These are role and result requirements, not a claim of sandbox isolation.
|
|
58
|
-
Available coding tools do not authorize product implementation in this role.
|
|
59
|
-
|
|
60
|
-
Use only the explicit context paths frozen in the brief. Do not read or use
|
|
61
|
-
ambient personal, session, or cross-project memory, including memory tools or
|
|
62
|
-
environment-provided memory. If the host exposes such memory and cannot isolate
|
|
63
|
-
it, stop and report the host-boundary failure through the assigned failure
|
|
64
|
-
protocol.
|
|
65
|
-
|
|
66
|
-
Only submit `status: complete` when every acceptance criterion is met and at
|
|
67
|
-
least one evidence item supports the result. If the work cannot be completed,
|
|
68
|
-
record the blocker in the worklog and end the attempt through its failure
|
|
69
|
-
protocol without creating a misleading completion report. The coordinator
|
|
70
|
-
owns the queue and final disposition. Do not change the brief, task state,
|
|
71
|
-
product source, protected configuration, tests, or Git state. Write only the
|
|
72
|
-
current attempt artifacts. Do not create another teammate, delegate through a
|
|
73
|
-
provider-native mechanism, retry yourself, or claim that a report has been
|
|
74
|
-
accepted.
|
|
15
|
+
输入中的模式和结果合同规定本次提交位置与格式。使用真实证据,区分已核实、推断和未知;缺少必要信息时报告阻断,不编造身份、来源或完成事实。CLI 负责调度、FIFO、容量、继续等待、重试、取消及最终 disposition,主代理负责语义审阅和任务阶段接受。
|
|
@@ -102,7 +102,7 @@ max_journal_lines: 2000
|
|
|
102
102
|
#
|
|
103
103
|
# `idle_timeout: 0` disables idle cleanup (teammates can sit idle forever
|
|
104
104
|
# unless explicitly killed or given `--timeout`).
|
|
105
|
-
#
|
|
105
|
+
# Capacity policy lives in .trellis/teamwork.json (schema 2).
|
|
106
106
|
#
|
|
107
107
|
# `trusted_context_dirs` extends the `--file`/`--jsonl`/`--agent` containment
|
|
108
108
|
# check beyond the teammate cwd — useful when `.trellis/tasks` or
|
|
@@ -115,13 +115,10 @@ max_journal_lines: 2000
|
|
|
115
115
|
teamwork:
|
|
116
116
|
teammate_guard:
|
|
117
117
|
idle_timeout: 5m
|
|
118
|
-
|
|
119
|
-
non_batch_reserved: 0
|
|
118
|
+
# Capacity and shared live budget live in .trellis/teamwork.json.
|
|
120
119
|
# trusted_context_dirs:
|
|
121
120
|
# - /work/user/trellis_workspace
|
|
122
121
|
# auto_trust_trellis_symlinks: false
|
|
123
|
-
teammate:
|
|
124
|
-
max_concurrency: 1
|
|
125
122
|
|
|
126
123
|
#-------------------------------------------------------------------------------
|
|
127
124
|
# Codex (dispatch behavior)
|
|
@@ -55,6 +55,7 @@ export declare const addSessionScript: string;
|
|
|
55
55
|
export declare const linearSyncScript: string;
|
|
56
56
|
export declare const workflowMdTemplate: string;
|
|
57
57
|
export declare const configYamlTemplate: string;
|
|
58
|
+
export declare const teamworkConfigTemplate: string;
|
|
58
59
|
export declare const gitignoreTemplate: string;
|
|
59
60
|
export declare const gitattributesTemplate: string;
|
|
60
61
|
export declare const teammateAgentTemplate: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/trellis/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAcH,eAAO,MAAM,WAAW,QAAsC,CAAC;AAG/D,eAAO,MAAM,UAAU,QAA6C,CAAC;AACrE,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,eAAe,QAA8C,CAAC;AAC3E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,cAAc,QAA8C,CAAC;AAC1E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,YAAY,QAA2C,CAAC;AACrE,eAAO,MAAM,QAAQ,QAAuC,CAAC;AAC7D,eAAO,MAAM,SAAS,QAAwC,CAAC;AAC/D,eAAO,MAAM,SAAS,QAAwC,CAAC;AAC/D,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,iBAAiB,QAAiD,CAAC;AAChF,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,kBAAkB,QAE9B,CAAC;AACF,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AACF,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AACF,eAAO,MAAM,qBAAqB,QAEjC,CAAC;AACF,eAAO,MAAM,mBAAmB,QAE/B,CAAC;AACF,eAAO,MAAM,uBAAuB,QAEnC,CAAC;AACF,eAAO,MAAM,mBAAmB,QAE/B,CAAC;AACF,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAG9E,eAAO,MAAM,kBAAkB,QAA2C,CAAC;AAC3E,eAAO,MAAM,mBAAmB,QAA4C,CAAC;AAC7E,eAAO,MAAM,UAAU,QAAkC,CAAC;AAC1D,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AACvE,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AACvE,eAAO,MAAM,gBAAgB,QAA+C,CAAC;AAG7E,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAC9D,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAC9D,eAAO,MAAM,iBAAiB,QAAgC,CAAC;AAC/D,eAAO,MAAM,qBAAqB,QAAoC,CAAC;AAGvE,eAAO,MAAM,qBAAqB,QAAqC,CAAC;AACxE,eAAO,MAAM,8BAA8B,QAE1C,CAAC;AACF,eAAO,MAAM,wBAAwB,QAEpC,CAAC;AAEF;;GAEG;AACH,wBAAgB,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CA6CnD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/trellis/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAcH,eAAO,MAAM,WAAW,QAAsC,CAAC;AAG/D,eAAO,MAAM,UAAU,QAA6C,CAAC;AACrE,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,eAAe,QAA8C,CAAC;AAC3E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,cAAc,QAA8C,CAAC;AAC1E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,YAAY,QAA2C,CAAC;AACrE,eAAO,MAAM,QAAQ,QAAuC,CAAC;AAC7D,eAAO,MAAM,SAAS,QAAwC,CAAC;AAC/D,eAAO,MAAM,SAAS,QAAwC,CAAC;AAC/D,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,iBAAiB,QAAiD,CAAC;AAChF,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,kBAAkB,QAE9B,CAAC;AACF,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AACF,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AACF,eAAO,MAAM,qBAAqB,QAEjC,CAAC;AACF,eAAO,MAAM,mBAAmB,QAE/B,CAAC;AACF,eAAO,MAAM,uBAAuB,QAEnC,CAAC;AACF,eAAO,MAAM,mBAAmB,QAE/B,CAAC;AACF,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAG9E,eAAO,MAAM,kBAAkB,QAA2C,CAAC;AAC3E,eAAO,MAAM,mBAAmB,QAA4C,CAAC;AAC7E,eAAO,MAAM,UAAU,QAAkC,CAAC;AAC1D,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AACvE,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AACvE,eAAO,MAAM,gBAAgB,QAA+C,CAAC;AAG7E,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAC9D,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAC9D,eAAO,MAAM,sBAAsB,QAAgC,CAAC;AACpE,eAAO,MAAM,iBAAiB,QAAgC,CAAC;AAC/D,eAAO,MAAM,qBAAqB,QAAoC,CAAC;AAGvE,eAAO,MAAM,qBAAqB,QAAqC,CAAC;AACxE,eAAO,MAAM,8BAA8B,QAE1C,CAAC;AACF,eAAO,MAAM,wBAAwB,QAEpC,CAAC;AAEF;;GAEG;AACH,wBAAgB,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CA6CnD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAelD"}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* ├── gitignore.txt # .gitignore content
|
|
19
19
|
* └── gitattributes.txt # project-root .gitattributes content
|
|
20
20
|
*/
|
|
21
|
-
import { readFileSync } from "node:fs";
|
|
21
|
+
import { readFileSync, readdirSync } from "node:fs";
|
|
22
22
|
import { dirname, join } from "node:path";
|
|
23
23
|
import { fileURLToPath } from "node:url";
|
|
24
24
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -67,6 +67,7 @@ export const linearSyncScript = readTemplate("scripts/hooks/linear_sync.py");
|
|
|
67
67
|
// Configuration files
|
|
68
68
|
export const workflowMdTemplate = readTemplate("workflow.md");
|
|
69
69
|
export const configYamlTemplate = readTemplate("config.yaml");
|
|
70
|
+
export const teamworkConfigTemplate = readTemplate("teamwork.json");
|
|
70
71
|
export const gitignoreTemplate = readTemplate("gitignore.txt");
|
|
71
72
|
export const gitattributesTemplate = readTemplate("gitattributes.txt");
|
|
72
73
|
// Project agent roles loaded from `.trellis/agents/`.
|
|
@@ -128,9 +129,20 @@ export function getAllScripts() {
|
|
|
128
129
|
*/
|
|
129
130
|
export function getAllAgents() {
|
|
130
131
|
const agents = new Map();
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
function collect(directory) {
|
|
133
|
+
for (const entry of readdirSync(join(__dirname, "agents", directory), {
|
|
134
|
+
withFileTypes: true,
|
|
135
|
+
})) {
|
|
136
|
+
const relative = join(directory, entry.name);
|
|
137
|
+
if (entry.isDirectory())
|
|
138
|
+
collect(relative);
|
|
139
|
+
else if (entry.isFile())
|
|
140
|
+
agents.set(relative, readTemplate(join("agents", relative)));
|
|
141
|
+
else
|
|
142
|
+
throw new Error(`unsupported agent template: ${relative}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
collect("");
|
|
134
146
|
return agents;
|
|
135
147
|
}
|
|
136
148
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/trellis/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/trellis/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -298,7 +298,7 @@ def _load_owner(path: Path) -> dict | None:
|
|
|
298
298
|
if record is None:
|
|
299
299
|
return None
|
|
300
300
|
required = {"schema_version", "task_id", "task_path", "package_id", "package_digest", "generation", "status", "source_session_id", "target_session_id", "continuity_digest", "route"}
|
|
301
|
-
if not required.issubset(record) or set(record) - required - {"target_continuity_digest"} or record.get("schema_version") != 1 or not isinstance(record.get("generation"), int):
|
|
301
|
+
if not required.issubset(record) or set(record) - required - {"target_continuity_digest", "recovery_history"} or record.get("schema_version") != 1 or not isinstance(record.get("generation"), int):
|
|
302
302
|
raise ContinuityError("TASK_TRANSFER_WITHHELD", "ownership record has an invalid shape")
|
|
303
303
|
if "target_continuity_digest" in record and (not isinstance(record["target_continuity_digest"], str) or not PACKAGE_DIGEST_RE.fullmatch(record["target_continuity_digest"])):
|
|
304
304
|
raise ContinuityError("TASK_TRANSFER_WITHHELD", "target continuity digest is invalid")
|
|
@@ -313,6 +313,10 @@ def transfer_task_ownership(args: argparse.Namespace) -> int:
|
|
|
313
313
|
root = get_repo_root()
|
|
314
314
|
operation = args.transfer_action
|
|
315
315
|
try:
|
|
316
|
+
package_bound = args.package_id is not None or args.package_digest is not None
|
|
317
|
+
if operation != "status" or package_bound:
|
|
318
|
+
if not isinstance(args.package_id, str) or not PACKAGE_ID_RE.fullmatch(args.package_id) or not isinstance(args.package_digest, str) or not PACKAGE_DIGEST_RE.fullmatch(args.package_digest):
|
|
319
|
+
raise ContinuityError("TASK_TRANSFER_INVALID_INPUT", "session package identity and SHA-256 digest are required")
|
|
316
320
|
task_dir = resolve_task_dir(args.task_path, root)
|
|
317
321
|
if task_dir is None or not is_within_tasks_dir(task_dir, root):
|
|
318
322
|
raise ContinuityError("TASK_TRANSFER_WITHHELD", "task path is unavailable or unsafe")
|
|
@@ -328,8 +332,10 @@ def transfer_task_ownership(args: argparse.Namespace) -> int:
|
|
|
328
332
|
path = _ownership_path(root, task_path)
|
|
329
333
|
with _record_lock(path):
|
|
330
334
|
record = _load_owner(path)
|
|
335
|
+
if record and (record["task_id"] != task_id or record["task_path"] != task_path):
|
|
336
|
+
raise ContinuityError("TASK_TRANSFER_WITHHELD", "ownership record does not match the requested task")
|
|
331
337
|
if operation == "status":
|
|
332
|
-
if record and (record["package_id"] != args.package_id or record["package_digest"] != args.package_digest):
|
|
338
|
+
if record and package_bound and (record["package_id"] != args.package_id or record["package_digest"] != args.package_digest):
|
|
333
339
|
raise ContinuityError("TASK_TRANSFER_STALE_PACKAGE", "session package identity or digest changed")
|
|
334
340
|
result = record or {"status": "absent", "generation": 0, "task_id": task_id}
|
|
335
341
|
if args.include_current:
|
|
@@ -342,8 +348,6 @@ def transfer_task_ownership(args: argparse.Namespace) -> int:
|
|
|
342
348
|
if args.expected_generation is None or args.expected_generation < 0:
|
|
343
349
|
raise ContinuityError("TASK_TRANSFER_INVALID_INPUT", "a non-negative expected generation is required")
|
|
344
350
|
if operation == "quiesce":
|
|
345
|
-
if not PACKAGE_ID_RE.fullmatch(args.package_id) or not PACKAGE_DIGEST_RE.fullmatch(args.package_digest):
|
|
346
|
-
raise ContinuityError("TASK_TRANSFER_INVALID_INPUT", "session package identity or SHA-256 digest is invalid")
|
|
347
351
|
context_key, current_path = _direct_pointer(root, task_path)
|
|
348
352
|
if current_path is None:
|
|
349
353
|
raise ContinuityError("TASK_TRANSFER_WITHHELD", "source session has no current task")
|
|
@@ -360,13 +364,18 @@ def transfer_task_ownership(args: argparse.Namespace) -> int:
|
|
|
360
364
|
result = record
|
|
361
365
|
print(json.dumps(result, ensure_ascii=False, sort_keys=True))
|
|
362
366
|
return 0
|
|
363
|
-
|
|
364
|
-
|
|
367
|
+
if record["status"] != "consumed" or record["generation"] != args.expected_generation:
|
|
368
|
+
raise ContinuityError("TASK_TRANSFER_STALE_GENERATION", "task already has an ownership record at a different state or generation")
|
|
369
|
+
if record["target_session_id"] != context_key:
|
|
370
|
+
raise ContinuityError("TASK_TRANSFER_WITHHELD", "only the consumed target can start another handoff")
|
|
371
|
+
if record["package_id"] == args.package_id:
|
|
372
|
+
raise ContinuityError("TASK_TRANSFER_STALE_PACKAGE", "another handoff requires a new session package")
|
|
373
|
+
elif args.expected_generation != 0:
|
|
365
374
|
raise ContinuityError("TASK_TRANSFER_STALE_GENERATION", "initial ownership generation must be 0")
|
|
366
375
|
record = {
|
|
367
376
|
"schema_version": 1, "task_id": task_id, "task_path": task_path,
|
|
368
377
|
"package_id": args.package_id, "package_digest": args.package_digest,
|
|
369
|
-
"generation": 1, "status": "quiescing", "source_session_id": context_key,
|
|
378
|
+
"generation": args.expected_generation + 1, "status": "quiescing", "source_session_id": context_key,
|
|
370
379
|
"target_session_id": None, "continuity_digest": continuity_digest,
|
|
371
380
|
"route": _route_snapshot(data),
|
|
372
381
|
}
|
|
@@ -385,31 +394,49 @@ def transfer_task_ownership(args: argparse.Namespace) -> int:
|
|
|
385
394
|
if not PACKAGE_DIGEST_RE.fullmatch(args.expected_continuity_digest):
|
|
386
395
|
raise ContinuityError("TASK_TRANSFER_INVALID_INPUT", "expected continuity digest must be a SHA-256 digest")
|
|
387
396
|
if args.expected_continuity_digest != current_digest:
|
|
388
|
-
raise ContinuityError("TASK_TRANSFER_STALE_CONTINUITY", "current task projection differs from the explicitly
|
|
397
|
+
raise ContinuityError("TASK_TRANSFER_STALE_CONTINUITY", "current task projection differs from the explicitly checked snapshot")
|
|
389
398
|
# Recovery acknowledges a live target snapshot without rebasing the source package.
|
|
390
|
-
|
|
399
|
+
recovered_claim = (
|
|
391
400
|
operation == "claim" and record["status"] == "sealed"
|
|
392
401
|
and args.expected_continuity_digest == current_digest
|
|
393
402
|
)
|
|
394
|
-
|
|
395
|
-
operation == "reconcile" and record["status"] == "consumed"
|
|
396
|
-
and args.expected_continuity_digest == current_digest
|
|
397
|
-
)
|
|
398
|
-
if operation != "release" and current_digest != record.get("target_continuity_digest", record["continuity_digest"]) and not (reconciled_claim or reconciled_target):
|
|
403
|
+
if operation not in {"release", "recover"} and current_digest != record.get("target_continuity_digest", record["continuity_digest"]) and not recovered_claim:
|
|
399
404
|
raise ContinuityError("TASK_TRANSFER_STALE_CONTINUITY", "task continuity changed during ownership transfer")
|
|
400
405
|
if operation != "release" and _route_snapshot(data) != record["route"]:
|
|
401
406
|
raise ContinuityError("TASK_TRANSFER_STALE_ROUTE", "task phase, route, input, or implementation authorization changed")
|
|
402
407
|
context_key, current_path = _direct_pointer(root)
|
|
408
|
+
if operation == "recover":
|
|
409
|
+
if record["status"] not in {"claiming", "claimed", "recovery_required"} or not isinstance(args.reason, str) or not args.reason.strip() or args.expected_continuity_digest != current_digest:
|
|
410
|
+
raise ContinuityError("TASK_TRANSFER_INVALID_TRANSITION", "explicit recovery requires a pending target, a reason, and the current projection digest")
|
|
411
|
+
if current_path not in {None, record["task_path"]}:
|
|
412
|
+
raise ContinuityError("TASK_TRANSFER_WITHHELD", "recovery session already has another active task")
|
|
413
|
+
from .task_workflow import _assert_delegated_resources_closed
|
|
414
|
+
try:
|
|
415
|
+
_assert_delegated_resources_closed(task_dir, data)
|
|
416
|
+
except TaskWorkflowError as error:
|
|
417
|
+
raise ContinuityError("TASK_TRANSFER_RECOVERY_REQUIRED", str(error)) from error
|
|
418
|
+
teammates_dir = task_dir / "teammates"
|
|
419
|
+
if any(teammates_dir.rglob("queue.json")) or any(teammates_dir.rglob("claim.json")):
|
|
420
|
+
raise ContinuityError("TASK_TRANSFER_RECOVERY_REQUIRED", "managed teamwork runtime artifacts remain; reconcile the original batch first")
|
|
421
|
+
record.setdefault("recovery_history", []).append({"generation": record["generation"], "status": record["status"], "target_session_id": record["target_session_id"], "requested_by": context_key, "reason": args.reason})
|
|
422
|
+
record.update({"status": "recovery_required", "generation": record["generation"] + 1, "target_continuity_digest": current_digest})
|
|
423
|
+
if not write_json(path, record):
|
|
424
|
+
raise ContinuityError("TASK_TRANSFER_WRITE_FAILED", "could not fence the previous generation before recovery")
|
|
425
|
+
for session in {record["source_session_id"], record["target_session_id"]} - {None}:
|
|
426
|
+
if not clear_active_task_if_matches(root, session, record["task_path"]):
|
|
427
|
+
raise ContinuityError("TASK_TRANSFER_RECOVERY_REQUIRED", "a prior session pointer changed; preserve the current generation")
|
|
428
|
+
record.update({"status": "ready", "target_session_id": None})
|
|
429
|
+
if not write_json(path, record):
|
|
430
|
+
raise ContinuityError("TASK_TRANSFER_WRITE_FAILED", "could not persist explicit recovery")
|
|
431
|
+
print(json.dumps(record, ensure_ascii=False, sort_keys=True))
|
|
432
|
+
return 0
|
|
403
433
|
if operation in {"seal", "retire"}:
|
|
404
434
|
if context_key != record["source_session_id"] or current_path not in {record["task_path"], None}:
|
|
405
435
|
raise ContinuityError("TASK_TRANSFER_WITHHELD", "source session no longer owns the current task")
|
|
406
|
-
elif operation in {"claim", "consume"
|
|
436
|
+
elif operation in {"claim", "consume"}:
|
|
407
437
|
if context_key == record["source_session_id"]:
|
|
408
438
|
raise ContinuityError("TASK_TRANSFER_WITHHELD", "target must be a different direct session")
|
|
409
|
-
if operation == "
|
|
410
|
-
if not reconciled_target or context_key != record["target_session_id"] or current_path != record["task_path"]:
|
|
411
|
-
raise ContinuityError("TASK_TRANSFER_WITHHELD", "only the consumed target may reconcile its explicitly pinned projection")
|
|
412
|
-
elif operation == "release":
|
|
439
|
+
if operation == "release":
|
|
413
440
|
if record["status"] not in {"quiescing", "sealed", "recovery_required"} or record["target_session_id"] is not None:
|
|
414
441
|
raise ContinuityError("TASK_TRANSFER_INVALID_TRANSITION", "ownership can be released only before target claim")
|
|
415
442
|
if context_key != record["source_session_id"] or current_path not in {None, record["task_path"]}:
|
|
@@ -422,9 +449,7 @@ def transfer_task_ownership(args: argparse.Namespace) -> int:
|
|
|
422
449
|
path.unlink(missing_ok=True)
|
|
423
450
|
print(json.dumps({"status": "released", "generation": record["generation"], "task_id": task_id}, ensure_ascii=False, sort_keys=True))
|
|
424
451
|
return 0
|
|
425
|
-
if operation == "
|
|
426
|
-
record.update({"target_continuity_digest": current_digest, "generation": record["generation"] + 1})
|
|
427
|
-
elif operation == "seal" and record["status"] == "quiescing":
|
|
452
|
+
if operation == "seal" and record["status"] == "quiescing":
|
|
428
453
|
record.update({"status": "sealed", "generation": record["generation"] + 1})
|
|
429
454
|
elif operation == "retire" and record["status"] in {"sealed", "retiring", "recovery_required"}:
|
|
430
455
|
if record["status"] == "sealed":
|
|
@@ -440,14 +465,14 @@ def transfer_task_ownership(args: argparse.Namespace) -> int:
|
|
|
440
465
|
write_json(path, record)
|
|
441
466
|
raise ContinuityError("TASK_TRANSFER_RECOVERY_REQUIRED", "source pointer remains after retirement")
|
|
442
467
|
record["status"] = "ready"
|
|
443
|
-
elif operation == "claim" and (record["status"] in {"ready", "claiming", "recovery_required", "claimed"} or
|
|
468
|
+
elif operation == "claim" and (record["status"] in {"ready", "claiming", "recovery_required", "claimed"} or recovered_claim):
|
|
444
469
|
if record["status"] in {"claiming", "recovery_required"} and record["target_session_id"] != context_key:
|
|
445
470
|
raise ContinuityError("TASK_TRANSFER_WITHHELD", "only the recorded target session can recover a claim")
|
|
446
471
|
if current_path not in {None, record["task_path"]}:
|
|
447
472
|
raise ContinuityError("TASK_TRANSFER_WITHHELD", "target session already has a current task")
|
|
448
473
|
if record["status"] in {"ready", "sealed"}:
|
|
449
474
|
record.update({"status": "claiming", "generation": record["generation"] + 1, "target_session_id": context_key})
|
|
450
|
-
if
|
|
475
|
+
if recovered_claim:
|
|
451
476
|
record["target_continuity_digest"] = current_digest
|
|
452
477
|
if not write_json(path, record):
|
|
453
478
|
raise ContinuityError("TASK_TRANSFER_WRITE_FAILED", "could not record target claim")
|
|
@@ -497,12 +522,13 @@ def add_continuity_commands(subparsers) -> None:
|
|
|
497
522
|
capture.add_argument("--expected-source-digest", required=True, help="Current captured digest, or absent")
|
|
498
523
|
|
|
499
524
|
transfer = subparsers.add_parser("transfer", help="Transfer task ownership between direct sessions")
|
|
500
|
-
transfer.add_argument("transfer_action", choices=("status", "quiesce", "seal", "retire", "claim", "consume", "release", "
|
|
525
|
+
transfer.add_argument("transfer_action", choices=("status", "quiesce", "seal", "retire", "claim", "consume", "release", "recover"))
|
|
526
|
+
transfer.add_argument("--reason", help="Explicit recovery reason")
|
|
501
527
|
transfer.add_argument("--task-id", required=True)
|
|
502
528
|
transfer.add_argument("--task-path", required=True)
|
|
503
|
-
transfer.add_argument("--package-id",
|
|
504
|
-
transfer.add_argument("--package-digest",
|
|
505
|
-
transfer.add_argument("--expected-continuity-digest", help="Expected live projection
|
|
529
|
+
transfer.add_argument("--package-id", help="Required with --package-digest for mutations or package-bound status")
|
|
530
|
+
transfer.add_argument("--package-digest", help="Required with --package-id for mutations or package-bound status")
|
|
531
|
+
transfer.add_argument("--expected-continuity-digest", help="Expected live projection for sealed-source claim recovery")
|
|
506
532
|
transfer.add_argument("--expected-generation", type=int)
|
|
507
533
|
transfer.add_argument("--include-current", action="store_true", help="Include the live task projection and its digest in transfer status")
|
|
508
534
|
transfer.add_argument("--explicit-user-request", action="store_true")
|
|
@@ -17,6 +17,7 @@ Provides:
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
19
|
import argparse
|
|
20
|
+
import json
|
|
20
21
|
import re
|
|
21
22
|
import sys
|
|
22
23
|
from dataclasses import dataclass, field
|
|
@@ -1244,6 +1245,10 @@ def cmd_remove_subtask(args: argparse.Namespace) -> int:
|
|
|
1244
1245
|
print("Error: A cancelled parent can unlink only a child recorded as independently continuing in its accepted closeout.", file=sys.stderr)
|
|
1245
1246
|
return 1
|
|
1246
1247
|
|
|
1248
|
+
if parent_data.get("status") != "cancelled":
|
|
1249
|
+
from .task_workflow import _assert_delegated_record_closed
|
|
1250
|
+
_assert_delegated_record_closed(child_dir.name, child_data.get("meta", {}).get("delegated_worktree_execution_record"))
|
|
1251
|
+
original_parent = json.loads(json.dumps(parent_data))
|
|
1247
1252
|
# Remove child from parent's children list
|
|
1248
1253
|
parent_children = _ensure_children_list(parent_data)
|
|
1249
1254
|
child_dir_name = child_dir.name
|
|
@@ -1263,8 +1268,8 @@ def cmd_remove_subtask(args: argparse.Namespace) -> int:
|
|
|
1263
1268
|
if not write_json(child_json_path, child_data):
|
|
1264
1269
|
print(colored(f"Error: Failed to write child task.json: {child_json_path}", Colors.RED), file=sys.stderr)
|
|
1265
1270
|
print(
|
|
1266
|
-
|
|
1267
|
-
f"
|
|
1271
|
+
"Parent link restored." if write_json(parent_json_path, original_parent) else
|
|
1272
|
+
f"Recovery required: could not restore the parent link in {parent_json_path}.",
|
|
1268
1273
|
file=sys.stderr,
|
|
1269
1274
|
)
|
|
1270
1275
|
return 1
|