@pennixrv/trellis 0.7.1-beta.16 → 0.7.1-beta.18
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/commands/teamwork/adapters/acp.d.ts +5 -0
- package/dist/commands/teamwork/adapters/acp.d.ts.map +1 -1
- package/dist/commands/teamwork/adapters/acp.js +19 -12
- package/dist/commands/teamwork/adapters/acp.js.map +1 -1
- package/dist/commands/teamwork/adapters/codex.d.ts +1 -1
- package/dist/commands/teamwork/adapters/codex.d.ts.map +1 -1
- package/dist/commands/teamwork/adapters/codex.js +4 -13
- package/dist/commands/teamwork/adapters/codex.js.map +1 -1
- package/dist/commands/teamwork/artifact.d.ts +4 -1
- package/dist/commands/teamwork/artifact.d.ts.map +1 -1
- package/dist/commands/teamwork/artifact.js +35 -4
- package/dist/commands/teamwork/artifact.js.map +1 -1
- package/dist/commands/teamwork/batch.d.ts +6 -0
- package/dist/commands/teamwork/batch.d.ts.map +1 -1
- package/dist/commands/teamwork/batch.js +114 -2
- package/dist/commands/teamwork/batch.js.map +1 -1
- package/dist/commands/teamwork/context-loader.d.ts.map +1 -1
- package/dist/commands/teamwork/context-loader.js +15 -3
- package/dist/commands/teamwork/context-loader.js.map +1 -1
- package/dist/commands/teamwork/coordinator.d.ts.map +1 -1
- package/dist/commands/teamwork/coordinator.js +4 -0
- 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/index.d.ts.map +1 -1
- package/dist/commands/teamwork/index.js +25 -4
- package/dist/commands/teamwork/index.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 +52 -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/run.d.ts +1 -0
- package/dist/commands/teamwork/run.d.ts.map +1 -1
- package/dist/commands/teamwork/run.js +111 -21
- package/dist/commands/teamwork/run.js.map +1 -1
- package/dist/commands/teamwork/runtime.d.ts.map +1 -1
- package/dist/commands/teamwork/runtime.js +49 -2
- package/dist/commands/teamwork/runtime.js.map +1 -1
- 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 +6 -3
- package/dist/commands/teamwork/spawn.d.ts.map +1 -1
- package/dist/commands/teamwork/spawn.js +12 -28
- package/dist/commands/teamwork/spawn.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 +25 -9
- package/dist/commands/teamwork/supervisor/inbox.js.map +1 -1
- package/dist/commands/teamwork/supervisor.d.ts +2 -0
- package/dist/commands/teamwork/supervisor.d.ts.map +1 -1
- package/dist/commands/teamwork/supervisor.js +1 -0
- package/dist/commands/teamwork/supervisor.js.map +1 -1
- package/dist/commands/teamwork/teammate-launch.d.ts +6 -0
- package/dist/commands/teamwork/teammate-launch.d.ts.map +1 -1
- package/dist/commands/teamwork/teammate-launch.js +24 -3
- 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/migrations/manifests/0.7.1-beta.17.json +9 -0
- package/dist/migrations/manifests/0.7.1-beta.18.json +9 -0
- package/dist/templates/common/bundled-skills/trellis-solution-design-and-convergence/workflow.md +2 -0
- package/dist/templates/common/bundled-skills/trellis-task-implementation/workflow.md +2 -0
- package/dist/templates/common/bundled-skills/trellis-teamwork/SKILL.md +5 -2
- package/dist/templates/common/bundled-skills/trellis-teamwork/references/coordination-modes.md +4 -0
- package/dist/templates/common/bundled-skills/trellis-teamwork/references/teammate-configuration-matrix.md +4 -2
- package/dist/templates/common/bundled-skills/trellis-teamwork/references/teammate-processes.md +31 -6
- package/dist/templates/common/bundled-skills/trellis-teamwork/references/teamwork-plan-construction.md +28 -3
- package/dist/templates/trellis/agents/profiles/research.md +4 -4
- package/dist/templates/trellis/agents/teammate.md +4 -75
- package/dist/templates/trellis/scripts/common/task_workflow.py +102 -2
- package/dist/templates/trellis/scripts/task.py +9 -0
- package/dist/templates/trellis/workflow.md +7 -0
- package/package.json +2 -2
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import argparse
|
|
6
6
|
import contextlib
|
|
7
|
+
import copy
|
|
7
8
|
from datetime import datetime, timezone
|
|
8
9
|
import hashlib
|
|
9
10
|
import json
|
|
@@ -445,6 +446,31 @@ def _show(state: dict) -> int:
|
|
|
445
446
|
return 0
|
|
446
447
|
|
|
447
448
|
|
|
449
|
+
def _require_acceptance_coverage(task_dir: Path, contract_ref: str) -> None:
|
|
450
|
+
_artifact_digest(task_dir, [contract_ref])
|
|
451
|
+
lines = (task_dir / contract_ref).read_text(encoding="utf-8").splitlines()
|
|
452
|
+
heading = next((index for index, line in enumerate(lines) if line.strip() == "## 验收覆盖"), None)
|
|
453
|
+
headers = ["接受条件", "工作包", "Owner", "验证入口", "交付证据", "停止条件"]
|
|
454
|
+
if heading is not None:
|
|
455
|
+
section = []
|
|
456
|
+
for line in lines[heading + 1:]:
|
|
457
|
+
if line.startswith("#"):
|
|
458
|
+
break
|
|
459
|
+
if line.strip():
|
|
460
|
+
section.append(line.strip())
|
|
461
|
+
rows = [line.strip("|").split("|") for line in section if line.startswith("|") and line.endswith("|")]
|
|
462
|
+
rows = [[cell.strip() for cell in row] for row in rows]
|
|
463
|
+
if (
|
|
464
|
+
len(rows) >= 3
|
|
465
|
+
and rows[0] == headers
|
|
466
|
+
and len(rows[1]) == len(headers)
|
|
467
|
+
and all(re.fullmatch(r":?-{3,}:?", cell) for cell in rows[1])
|
|
468
|
+
and all(len(row) == len(headers) and all(row) for row in rows[2:])
|
|
469
|
+
):
|
|
470
|
+
return
|
|
471
|
+
raise TaskWorkflowError("TASK_PHASE_COVERAGE_REQUIRED", "implementation contract requires ## 验收覆盖 with nonempty rows: " + " | ".join(headers))
|
|
472
|
+
|
|
473
|
+
|
|
448
474
|
def _update(args: argparse.Namespace, task_dir: Path, data: dict, state: dict) -> int:
|
|
449
475
|
action = args.phase_action
|
|
450
476
|
child_dispositions: dict[str, str] = {}
|
|
@@ -531,6 +557,8 @@ def _update(args: argparse.Namespace, task_dir: Path, data: dict, state: dict) -
|
|
|
531
557
|
raise TaskWorkflowError("TASK_PHASE_INVALID_TRANSITION", "Solution Design and Convergence Phase must remain active for pending_user_decision or deferred; accept implementation_contract, analysis_conclusion, or no_go")
|
|
532
558
|
if result_ref not in record["artifact_refs"]:
|
|
533
559
|
raise TaskWorkflowError("TASK_PHASE_RESULT_NOT_BOUND", "--result-ref must be included in the current phase artifact refs")
|
|
560
|
+
if current == PHASE_IDS[2] and outcome == "implementation_contract":
|
|
561
|
+
_require_acceptance_coverage(task_dir, result_ref)
|
|
534
562
|
if current == PHASE_IDS[3]:
|
|
535
563
|
authorization = state.get("implementation_authorization")
|
|
536
564
|
if not isinstance(authorization, dict) or authorization.get("task_route_revision") != state["task_route_revision"]:
|
|
@@ -568,17 +596,38 @@ def _update(args: argparse.Namespace, task_dir: Path, data: dict, state: dict) -
|
|
|
568
596
|
_advance(state, current)
|
|
569
597
|
elif action == "return":
|
|
570
598
|
target = _required_text(args.target_phase, "--target-phase")
|
|
599
|
+
return_kind = args.return_kind
|
|
600
|
+
execution_rework = return_kind == "execution_rework"
|
|
571
601
|
if target not in state["phase_ids"] or (
|
|
572
602
|
state["phase_ids"].index(target) >= state["phase_ids"].index(current)
|
|
573
|
-
and not ((reviewed_delivery or accepted_design_return) and target == current)
|
|
603
|
+
and not ((reviewed_delivery or accepted_design_return or execution_rework) and target == current)
|
|
574
604
|
):
|
|
575
605
|
raise TaskWorkflowError("TASK_PHASE_INVALID_TRANSITION", "return target must be an earlier phase in the current route")
|
|
576
606
|
reason = _required_text(args.reason, "--reason")
|
|
577
607
|
evidence = _refs(args.evidence_ref, "--evidence-ref", required=True)
|
|
608
|
+
authorization = state.get("implementation_authorization")
|
|
609
|
+
admission = state.get("route_dependency_admission")
|
|
610
|
+
if execution_rework:
|
|
611
|
+
if current not in PHASE_IDS[3:] or target not in PHASE_IDS[3:]:
|
|
612
|
+
raise TaskWorkflowError("TASK_PHASE_INVALID_TRANSITION", "execution_rework is limited to implementation and delivery phases")
|
|
613
|
+
candidate = copy.deepcopy(data)
|
|
614
|
+
candidate_state = candidate["meta"]["task_workflow"]
|
|
615
|
+
_invalidate_from(candidate_state, target, keep_first=True)
|
|
616
|
+
candidate_state["implementation_authorization"] = authorization
|
|
617
|
+
_require_current_accepted_artifacts(task_dir, candidate_state)
|
|
618
|
+
candidate_state["current_phase_id"] = PHASE_IDS[3]
|
|
619
|
+
candidate_state["phases"][PHASE_IDS[3]]["status"] = "active"
|
|
620
|
+
if not implementation_start_ready(candidate, task_dir):
|
|
621
|
+
raise TaskWorkflowError("TASK_PHASE_IMPLEMENTATION_NOT_AUTHORIZED", "execution_rework requires the unchanged authorized implementation contract")
|
|
622
|
+
if admission is not None and (admission.get("admission_state") != "ready" or admission.get("task_route_revision") != state["task_route_revision"]):
|
|
623
|
+
raise TaskWorkflowError("TASK_PHASE_ADMISSION_REQUIRED", "execution_rework requires current ready dependency admission")
|
|
578
624
|
state["input_revision"] = _increment(state["input_revision"])
|
|
579
625
|
_invalidate_from(state, target, keep_first=True)
|
|
626
|
+
if execution_rework:
|
|
627
|
+
state["implementation_authorization"] = authorization
|
|
628
|
+
state["route_dependency_admission"] = admission
|
|
580
629
|
state["phases"][target]["input_revision"] = state["input_revision"]
|
|
581
|
-
state["return_record"] = {"from": current, "to": target, "reason": reason, "evidence_refs": evidence, "task_route_revision": state["task_route_revision"]}
|
|
630
|
+
state["return_record"] = {"from": current, "to": target, "return_kind": return_kind, "authorization_retained": execution_rework, "reason": reason, "evidence_refs": evidence, "task_route_revision": state["task_route_revision"]}
|
|
582
631
|
elif action == "route":
|
|
583
632
|
phases = _validate_route(args.phase_ids)
|
|
584
633
|
task_kind = args.task_kind if args.task_kind is not None else state["task_kind"]
|
|
@@ -690,6 +739,7 @@ def _update(args: argparse.Namespace, task_dir: Path, data: dict, state: dict) -
|
|
|
690
739
|
raise TaskWorkflowError("TASK_PHASE_STALE_ARTIFACT", "Solution Design and Convergence Phase implementation contract changed after acceptance; refresh and accept the current artifact before authorization")
|
|
691
740
|
elif contract_ref not in state.get("skip_records", {}).get(PHASE_IDS[2], {}).get("evidence_refs", []):
|
|
692
741
|
raise TaskWorkflowError("TASK_PHASE_CONTRACT_NOT_ACCEPTED", "when Solution Design and Convergence Phase is omitted, the implementation contract must be among its route evidence")
|
|
742
|
+
_require_acceptance_coverage(task_dir, contract_ref)
|
|
693
743
|
state["implementation_authorization"] = {"contract_ref": contract_ref, "contract_revision": _artifact_digest(task_dir, [contract_ref]), "approval_ref": approval_ref, "task_route_revision": state["task_route_revision"]}
|
|
694
744
|
if current == PHASE_IDS[2]:
|
|
695
745
|
_advance(state, current)
|
|
@@ -1011,6 +1061,56 @@ def cmd_cancel_task(args: argparse.Namespace) -> int:
|
|
|
1011
1061
|
return 1
|
|
1012
1062
|
|
|
1013
1063
|
|
|
1064
|
+
def cmd_reopen_task(args: argparse.Namespace) -> int:
|
|
1065
|
+
try:
|
|
1066
|
+
task_dir = _task_dir(args.task_dir)
|
|
1067
|
+
with _task_lock(task_dir):
|
|
1068
|
+
data, meta = _load(task_dir)
|
|
1069
|
+
previous_status = data.get("status")
|
|
1070
|
+
if previous_status not in {"completed", "cancelled"}:
|
|
1071
|
+
raise TaskWorkflowError("TASK_PHASE_REOPEN_INVALID_STATUS", "only completed or cancelled tasks can be reopened")
|
|
1072
|
+
reason = _required_text(args.reason, "--reason")
|
|
1073
|
+
evidence = _refs(args.evidence_ref, "--evidence-ref", required=True)
|
|
1074
|
+
_assert_delegated_resources_closed(task_dir, data)
|
|
1075
|
+
recoveries = meta.setdefault("task_lifecycle_recoveries", [])
|
|
1076
|
+
if not isinstance(recoveries, list) or any(not isinstance(record, dict) for record in recoveries):
|
|
1077
|
+
raise TaskWorkflowError("TASK_PHASE_TASK_INVALID", "task lifecycle recovery history is malformed")
|
|
1078
|
+
recovery = {
|
|
1079
|
+
"from_status": previous_status,
|
|
1080
|
+
"to_status": "planning",
|
|
1081
|
+
"reason": reason,
|
|
1082
|
+
"evidence_refs": evidence,
|
|
1083
|
+
"reopened_at": datetime.now(timezone.utc).isoformat(),
|
|
1084
|
+
"terminal_completed_at": data.get("completedAt"),
|
|
1085
|
+
"terminal_cancellation": copy.deepcopy(meta.get("task_cancellation")),
|
|
1086
|
+
}
|
|
1087
|
+
state = meta.get("task_workflow")
|
|
1088
|
+
if state is not None:
|
|
1089
|
+
state = _state(meta)
|
|
1090
|
+
state["implementation_authorization"] = None
|
|
1091
|
+
state["route_dependency_admission"] = None
|
|
1092
|
+
state["closeout_disposition"] = None
|
|
1093
|
+
recoveries.append(recovery)
|
|
1094
|
+
data["status"] = "planning"
|
|
1095
|
+
data["completedAt"] = None
|
|
1096
|
+
from .task_move import relocate_task
|
|
1097
|
+
from .active_task import clear_task_from_sessions
|
|
1098
|
+
from .task_continuity import clear_task_runtime_records
|
|
1099
|
+
|
|
1100
|
+
repo_root = get_repo_root()
|
|
1101
|
+
# Relocation rewrites runtime paths; terminal runtime must be discarded first.
|
|
1102
|
+
for runtime_dir in (task_dir, repo_root / ".trellis/tasks/planning" / task_dir.name):
|
|
1103
|
+
clear_task_from_sessions(str(runtime_dir), repo_root)
|
|
1104
|
+
if not clear_task_runtime_records(repo_root, runtime_dir.relative_to(repo_root).as_posix()):
|
|
1105
|
+
raise TaskWorkflowError("TASK_PHASE_RUNTIME_CLEANUP_FAILED", "could not discard terminal task runtime; task remains terminal")
|
|
1106
|
+
task_dir = relocate_task(repo_root, task_dir, data)
|
|
1107
|
+
print(json.dumps({"status": "planning", "task_lifecycle_recovery": recovery, "runtime_records_cleared": True}, ensure_ascii=False))
|
|
1108
|
+
return 0
|
|
1109
|
+
except TaskWorkflowError as error:
|
|
1110
|
+
print(f"{error.code}: {error}", file=sys.stderr)
|
|
1111
|
+
return 1
|
|
1112
|
+
|
|
1113
|
+
|
|
1014
1114
|
def task_closeout_readiness(data: dict, disposition: str) -> str | None:
|
|
1015
1115
|
if "meta" in data and not isinstance(data["meta"], dict):
|
|
1016
1116
|
return "task metadata is malformed"
|
|
@@ -14,6 +14,7 @@ Usage:
|
|
|
14
14
|
python3 task.py workflow <id>|--clear # Set/clear per-task workflow selection
|
|
15
15
|
python3 task.py phase <action> <task-dir> # Read/update task phase workflow state
|
|
16
16
|
python3 task.py cancel <task-dir> --reason <text> --evidence-ref <ref> # Cancel task lifecycle
|
|
17
|
+
python3 task.py reopen <task-dir> --reason <text> --evidence-ref <ref> # Restore terminal task to planning
|
|
17
18
|
python3 task.py set-branch <dir> <branch> # Set git branch
|
|
18
19
|
python3 task.py set-base-branch <dir> <branch> # Set PR target branch
|
|
19
20
|
python3 task.py set-scope <dir> <scope> # Set scope for PR title
|
|
@@ -79,6 +80,7 @@ from common.task_context import (
|
|
|
79
80
|
from common.task_workflow import (
|
|
80
81
|
TaskWorkflowError,
|
|
81
82
|
cmd_cancel_task,
|
|
83
|
+
cmd_reopen_task,
|
|
82
84
|
cmd_complete_task,
|
|
83
85
|
cmd_delegate_start,
|
|
84
86
|
cmd_phase,
|
|
@@ -779,6 +781,7 @@ def main() -> int:
|
|
|
779
781
|
p_phase.add_argument("--route-reason", help="Reason when initialization omits one or more phases")
|
|
780
782
|
p_phase.add_argument("--route-evidence-ref", action="append", help="Evidence supporting an abbreviated initial route")
|
|
781
783
|
p_phase.add_argument("--target-phase", help="Earlier phase to revisit, or first affected phase for route change")
|
|
784
|
+
p_phase.add_argument("--return-kind", choices=("contract_change", "execution_rework"), default="contract_change", help="Contract change invalidates authorization; execution rework retains a verified unchanged contract")
|
|
782
785
|
p_phase.add_argument("--artifact-ref", action="append", help="Task-relative file in the current phase output")
|
|
783
786
|
p_phase.add_argument("--artifact-revision", help="Current artifact_revision required for acceptance")
|
|
784
787
|
p_phase.add_argument("--result-ref", help="Task result artifact reference")
|
|
@@ -803,6 +806,11 @@ def main() -> int:
|
|
|
803
806
|
p_cancel.add_argument("--reason", required=True, help="Why the task is cancelled")
|
|
804
807
|
p_cancel.add_argument("--evidence-ref", action="append", required=True, help="Task-relative cancellation evidence")
|
|
805
808
|
|
|
809
|
+
p_reopen = subparsers.add_parser("reopen", help="Recover a terminal task to planning without implementation authorization")
|
|
810
|
+
p_reopen.add_argument("task_dir", help="Task directory or task name")
|
|
811
|
+
p_reopen.add_argument("--reason", required=True, help="Why the same task must continue")
|
|
812
|
+
p_reopen.add_argument("--evidence-ref", action="append", required=True, help="Recovery decision evidence")
|
|
813
|
+
|
|
806
814
|
# set-branch
|
|
807
815
|
p_branch = subparsers.add_parser("set-branch", help="Set git branch")
|
|
808
816
|
p_branch.add_argument("dir", help="Task directory")
|
|
@@ -880,6 +888,7 @@ def main() -> int:
|
|
|
880
888
|
"delegate-start": cmd_delegate_start,
|
|
881
889
|
"complete": cmd_complete_task,
|
|
882
890
|
"cancel": cmd_cancel_task,
|
|
891
|
+
"reopen": cmd_reopen_task,
|
|
883
892
|
"set-branch": cmd_set_branch,
|
|
884
893
|
"set-base-branch": cmd_set_base_branch,
|
|
885
894
|
"set-scope": cmd_set_scope,
|
|
@@ -30,12 +30,19 @@ python3 ./.trellis/scripts/task.py validate <task>
|
|
|
30
30
|
python3 ./.trellis/scripts/task.py start <task>
|
|
31
31
|
python3 ./.trellis/scripts/task.py complete <task>
|
|
32
32
|
python3 ./.trellis/scripts/task.py cancel <task> --reason "<reason>" --evidence-ref <reference>
|
|
33
|
+
python3 ./.trellis/scripts/task.py reopen <task> --reason "<reason>" --evidence-ref <reference>
|
|
33
34
|
```
|
|
34
35
|
|
|
35
36
|
使用 `phase artifact`、`accept`、`skip`、`wait`、`block`、`resume`、`return`、`route` 和 `authorize` 执行对应的阶段操作。准确参数以 `task.py --help` 为准。跳过阶段必须提供理由和证据;目标探索与需求核对阶段不可省略。
|
|
36
37
|
|
|
37
38
|
只有阶段路线已到达获准的实施入口时,`task.py start` 才会将任务从 `planning` 改为 `in_progress`。分析任务可在交付审查与现场收尾阶段后仍处于 `planning` 时完成。`complete` 将任务移入 `completed/YYYY-MM/<task>`,`cancel` 将任务移入 `cancelled/<task>`,并在同一事务中清除任务的运行时会话指针。
|
|
38
39
|
|
|
40
|
+
工作流阶段回流与原生任务生命周期恢复分别操作。`completed` 或 `cancelled` 任务需要在原线程继续时,先用 `reopen` 恢复到 `planning`,保留终态事实、取消原因和恢复证据,清除旧运行态、实施授权和依赖准入;工作流阶段保持原记录。随后用 `phase return` 回到最早受影响阶段。实现任务重新接受合同、取得新的实施授权并核验准入后,才由 `start` 进入 `in_progress`。`phase return` 不能直接修改终态任务。
|
|
41
|
+
|
|
42
|
+
`phase return` 默认采用 `contract_change`,使受影响阶段接受和实施授权失效。合同不变的局部实施或证据返工可显式使用 `--return-kind execution_rework`,目标限于实施或交付阶段,可重入当前阶段;CLI 核验需求、已接受合同、授权摘要、路线 revision 和已声明依赖准入仍有效后,保留授权,清理目标阶段及下游的接受事实。不能以此修改目标、合同或绕过待决依赖。普通局部修复可直接在当前活动阶段完成,无需为了记录进展而回流。
|
|
43
|
+
|
|
44
|
+
新接受的 `implementation_contract`(以及省略设计阶段时新授权的合同)必须包含 `## 验收覆盖` 表,表头固定为 `接受条件 | 工作包 | Owner | 验证入口 | 交付证据 | 停止条件`,至少一行且各单元格非空。CLI 负责结构检查,阶段 Skill 负责逐条核对已接受条件的语义覆盖。既有接受和授权不会因本次升级自动失效;再次接受或授权时执行新检查。
|
|
45
|
+
|
|
39
46
|
旧布局须先预览 `task.py migrate-layout`,核对后执行 `task.py migrate-layout --apply`;旧 `archive/YYYY-MM` 中已完成的任务保留原月份,其他任务按真实状态放置。迁移会同步 JSON/JSONL 机器引用、会话指针和运行态索引,保留任务身份与父子关系,不重授历史授权。未完成事务会阻止普通任务命令,须用 `task.py migrate-layout --recover` 恢复;输入被外部改动时停止并保留现场。路径或产物内容改变导致接受证据失效时,须经原生阶段接受或 continuity 核对重新收敛。
|
|
40
47
|
|
|
41
48
|
在支持原生实施或检查 agent 的平台上,任务上下文清单(`implement.jsonl`、`check.jsonl`)用于提供相关规范和研究资料。只有这些 agent 会读取清单时才需要维护;清单不能替代任务资产或阶段证据。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pennixrv/trellis",
|
|
3
|
-
"version": "0.7.1-beta.
|
|
3
|
+
"version": "0.7.1-beta.18",
|
|
4
4
|
"description": "AI capabilities grow like ivy — Trellis provides the structure to guide them along a disciplined path",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"inquirer": "^9.3.7",
|
|
36
36
|
"undici": "^6.21.0",
|
|
37
37
|
"zod": "^4.4.2",
|
|
38
|
-
"@pennixrv/trellis-core": "0.7.1-beta.
|
|
38
|
+
"@pennixrv/trellis-core": "0.7.1-beta.18"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@eslint/js": "^9.18.0",
|