@pennixrv/trellis 0.7.0-beta.5 → 0.7.0-beta.50
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.d.ts.map +1 -1
- package/dist/cli/index.js +47 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/backup.d.ts +25 -0
- package/dist/commands/backup.d.ts.map +1 -0
- package/dist/commands/backup.js +152 -0
- package/dist/commands/backup.js.map +1 -0
- package/dist/commands/channel/adapters/claude.d.ts.map +1 -1
- package/dist/commands/channel/adapters/claude.js +2 -0
- package/dist/commands/channel/adapters/claude.js.map +1 -1
- package/dist/commands/channel/adapters/codex.d.ts +5 -1
- package/dist/commands/channel/adapters/codex.d.ts.map +1 -1
- package/dist/commands/channel/adapters/codex.js +19 -9
- package/dist/commands/channel/adapters/codex.js.map +1 -1
- package/dist/commands/channel/adapters/index.d.ts +3 -0
- package/dist/commands/channel/adapters/index.d.ts.map +1 -1
- package/dist/commands/channel/adapters/index.js +3 -3
- package/dist/commands/channel/adapters/index.js.map +1 -1
- package/dist/commands/channel/adapters/types.d.ts +2 -0
- package/dist/commands/channel/adapters/types.d.ts.map +1 -1
- package/dist/commands/channel/guard.d.ts.map +1 -1
- package/dist/commands/channel/guard.js +38 -29
- package/dist/commands/channel/guard.js.map +1 -1
- package/dist/commands/channel/index.d.ts.map +1 -1
- package/dist/commands/channel/index.js +52 -16
- package/dist/commands/channel/index.js.map +1 -1
- package/dist/commands/channel/kill.d.ts.map +1 -1
- package/dist/commands/channel/kill.js +37 -15
- package/dist/commands/channel/kill.js.map +1 -1
- package/dist/commands/channel/messages.d.ts.map +1 -1
- package/dist/commands/channel/messages.js +3 -2
- package/dist/commands/channel/messages.js.map +1 -1
- package/dist/commands/channel/process-identity.d.ts +3 -0
- package/dist/commands/channel/process-identity.d.ts.map +1 -0
- package/dist/commands/channel/process-identity.js +24 -0
- package/dist/commands/channel/process-identity.js.map +1 -0
- package/dist/commands/channel/profiles.d.ts +26 -0
- package/dist/commands/channel/profiles.d.ts.map +1 -0
- package/dist/commands/channel/profiles.js +186 -0
- package/dist/commands/channel/profiles.js.map +1 -0
- package/dist/commands/channel/rm.d.ts +0 -1
- package/dist/commands/channel/rm.d.ts.map +1 -1
- package/dist/commands/channel/rm.js +203 -96
- package/dist/commands/channel/rm.js.map +1 -1
- package/dist/commands/channel/spawn.d.ts +3 -0
- package/dist/commands/channel/spawn.d.ts.map +1 -1
- package/dist/commands/channel/spawn.js +43 -15
- package/dist/commands/channel/spawn.js.map +1 -1
- package/dist/commands/channel/supervisor/idle.d.ts +2 -0
- package/dist/commands/channel/supervisor/idle.d.ts.map +1 -1
- package/dist/commands/channel/supervisor/idle.js +15 -7
- package/dist/commands/channel/supervisor/idle.js.map +1 -1
- package/dist/commands/channel/supervisor/inbox.d.ts.map +1 -1
- package/dist/commands/channel/supervisor/inbox.js +48 -33
- package/dist/commands/channel/supervisor/inbox.js.map +1 -1
- package/dist/commands/channel/supervisor/stdout.d.ts.map +1 -1
- package/dist/commands/channel/supervisor/stdout.js +6 -3
- package/dist/commands/channel/supervisor/stdout.js.map +1 -1
- package/dist/commands/channel/supervisor/warning.d.ts.map +1 -1
- package/dist/commands/channel/supervisor/warning.js +2 -3
- package/dist/commands/channel/supervisor/warning.js.map +1 -1
- package/dist/commands/channel/supervisor.d.ts +12 -0
- package/dist/commands/channel/supervisor.d.ts.map +1 -1
- package/dist/commands/channel/supervisor.js +88 -16
- package/dist/commands/channel/supervisor.js.map +1 -1
- package/dist/commands/channel/wait.d.ts +3 -1
- package/dist/commands/channel/wait.d.ts.map +1 -1
- package/dist/commands/channel/wait.js +59 -14
- package/dist/commands/channel/wait.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +23 -10
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +446 -333
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/workflow.d.ts +1 -0
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +56 -1
- package/dist/commands/workflow.js.map +1 -1
- package/dist/configurators/codex.d.ts +6 -0
- package/dist/configurators/codex.d.ts.map +1 -1
- package/dist/configurators/codex.js +93 -0
- package/dist/configurators/codex.js.map +1 -1
- package/dist/configurators/shared.js +2 -2
- package/dist/configurators/shared.js.map +1 -1
- package/dist/constants/paths.d.ts +2 -0
- package/dist/constants/paths.d.ts.map +1 -1
- package/dist/constants/paths.js +2 -0
- package/dist/constants/paths.js.map +1 -1
- package/dist/migrations/manifests/0.7.0-beta.10.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.11.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.12.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.13.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.14.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.15.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.16.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.17.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.18.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.19.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.20.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.21.json +17 -0
- package/dist/migrations/manifests/0.7.0-beta.22.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.23.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.24.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.25.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.26.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.27.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.28.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.29.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.30.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.31.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.32.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.33.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.34.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.35.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.36.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.37.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.38.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.39.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.40.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.41.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.42.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.43.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.44.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.45.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.46.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.47.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.48.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.49.json +13 -0
- package/dist/migrations/manifests/0.7.0-beta.50.json +12 -0
- package/dist/migrations/manifests/0.7.0-beta.6.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.7.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.8.json +9 -0
- package/dist/migrations/manifests/0.7.0-beta.9.json +9 -0
- package/dist/templates/codex/hooks/session-start.py +21 -17
- package/dist/templates/common/bundled-skills/trellis-channel/SKILL.md +3 -1
- package/dist/templates/common/bundled-skills/trellis-channel/references/command-reference.md +24 -16
- package/dist/templates/common/bundled-skills/trellis-channel/references/forum.md +4 -12
- package/dist/templates/common/bundled-skills/trellis-channel/references/multi-target-dispatch.md +139 -0
- package/dist/templates/common/bundled-skills/trellis-channel/references/progress-debugging.md +9 -5
- package/dist/templates/common/bundled-skills/trellis-channel/references/subnode-work.md +84 -14
- package/dist/templates/common/bundled-skills/trellis-channel/references/workers.md +9 -11
- package/dist/templates/common/bundled-skills/trellis-channel/references/workflows.md +25 -14
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-skills-or-commands.md +13 -11
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-task-lifecycle.md +7 -2
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +6 -1
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/workflow.md +6 -4
- package/dist/templates/common/bundled-skills/trellis-session-insight/SKILL.md +42 -3
- package/dist/templates/common/bundled-skills/trellis-session-insight/references/cli-quick-reference.md +1 -1
- package/dist/templates/common/bundled-skills/trellis-session-insight/references/triggering-patterns.md +10 -2
- package/dist/templates/common/commands/continue.md +36 -8
- package/dist/templates/common/commands/finish-work.md +17 -2
- package/dist/templates/common/commands/start.md +8 -1
- package/dist/templates/common/skills/brainstorm.md +49 -22
- package/dist/templates/common/skills/break-loop.md +6 -10
- package/dist/templates/common/skills/check.md +34 -5
- package/dist/templates/copilot/hooks/session-start.py +19 -15
- package/dist/templates/copilot/prompts/brainstorm.prompt.md +27 -21
- package/dist/templates/markdown/spec/backend/database-guidelines.md.txt +22 -22
- package/dist/templates/markdown/spec/backend/directory-structure.md.txt +20 -20
- package/dist/templates/markdown/spec/backend/error-handling.md.txt +22 -22
- package/dist/templates/markdown/spec/backend/index.md.txt +19 -19
- package/dist/templates/markdown/spec/backend/logging-guidelines.md.txt +22 -22
- package/dist/templates/markdown/spec/backend/quality-guidelines.md.txt +22 -22
- package/dist/templates/markdown/spec/frontend/component-guidelines.md.txt +25 -25
- package/dist/templates/markdown/spec/frontend/directory-structure.md.txt +20 -20
- package/dist/templates/markdown/spec/frontend/hook-guidelines.md.txt +22 -22
- package/dist/templates/markdown/spec/frontend/index.md.txt +20 -20
- package/dist/templates/markdown/spec/frontend/quality-guidelines.md.txt +22 -22
- package/dist/templates/markdown/spec/frontend/state-management.md.txt +22 -22
- package/dist/templates/markdown/spec/frontend/type-safety.md.txt +22 -22
- package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +80 -85
- package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +164 -209
- package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +161 -185
- package/dist/templates/markdown/spec/guides/index.md.txt +51 -51
- package/dist/templates/markdown/workspace-index.md +44 -44
- package/dist/templates/opencode/lib/session-utils.js +2 -2
- package/dist/templates/shared-hooks/inject-shell-session-context.py +3 -6
- package/dist/templates/shared-hooks/inject-workflow-state.py +3 -2
- package/dist/templates/shared-hooks/session-start.py +23 -18
- package/dist/templates/trellis/agents/subnode-profiles.json +13 -0
- package/dist/templates/trellis/agents/subnode.md +11 -5
- package/dist/templates/trellis/config.yaml +2 -0
- package/dist/templates/trellis/index.d.ts +2 -1
- package/dist/templates/trellis/index.d.ts.map +1 -1
- package/dist/templates/trellis/index.js +4 -2
- package/dist/templates/trellis/index.js.map +1 -1
- package/dist/templates/trellis/scripts/add_session.py +35 -32
- package/dist/templates/trellis/scripts/common/active_task.py +8 -8
- package/dist/templates/trellis/scripts/common/developer.py +18 -18
- package/dist/templates/trellis/scripts/common/ownership_record.py +13 -8
- package/dist/templates/trellis/scripts/common/safe_commit.py +38 -9
- package/dist/templates/trellis/scripts/common/task_planning.py +137 -0
- package/dist/templates/trellis/scripts/common/task_store.py +46 -14
- package/dist/templates/trellis/scripts/common/workflow_phase.py +4 -3
- package/dist/templates/trellis/scripts/subnode_artifact.py +470 -21
- package/dist/templates/trellis/scripts/task.py +175 -2
- package/dist/templates/trellis/workflow.md +407 -388
- package/dist/utils/managed-paths.d.ts +2 -0
- package/dist/utils/managed-paths.d.ts.map +1 -1
- package/dist/utils/managed-paths.js +24 -2
- package/dist/utils/managed-paths.js.map +1 -1
- package/dist/utils/template-fetcher.d.ts +1 -0
- package/dist/utils/template-fetcher.d.ts.map +1 -1
- package/dist/utils/template-fetcher.js +2 -1
- package/dist/utils/template-fetcher.js.map +1 -1
- package/dist/utils/uninstall-scrubbers.d.ts.map +1 -1
- package/dist/utils/uninstall-scrubbers.js +5 -0
- package/dist/utils/uninstall-scrubbers.js.map +1 -1
- package/dist/utils/workflow-provenance.d.ts +24 -0
- package/dist/utils/workflow-provenance.d.ts.map +1 -0
- package/dist/utils/workflow-provenance.js +71 -0
- package/dist/utils/workflow-provenance.js.map +1 -0
- package/dist/utils/workflow-resolver.d.ts +9 -2
- package/dist/utils/workflow-resolver.d.ts.map +1 -1
- package/dist/utils/workflow-resolver.js +33 -7
- package/dist/utils/workflow-resolver.js.map +1 -1
- package/package.json +2 -2
- package/dist/templates/trellis/agents/subnode.env +0 -4
|
@@ -8,7 +8,11 @@ Usage:
|
|
|
8
8
|
python3 task.py add-context <dir> <file> <path> [reason] # Add jsonl entry
|
|
9
9
|
python3 task.py validate <dir> # Validate jsonl files
|
|
10
10
|
python3 task.py list-context <dir> # List jsonl entries
|
|
11
|
-
python3 task.py
|
|
11
|
+
python3 task.py select <dir> # Select an existing task without starting it
|
|
12
|
+
python3 task.py plan seal <dir> # Seal the current material plan
|
|
13
|
+
python3 task.py plan approve <dir> --revision N --basis "approval"
|
|
14
|
+
python3 task.py start <dir> # Start an approved task, record current branch
|
|
15
|
+
python3 task.py replan <dir> "<reason>" # Return an in-progress task to planning
|
|
12
16
|
python3 task.py current [--source] [--json] # Show active task
|
|
13
17
|
python3 task.py ownership <operation> ... # Manage formal handoff task ownership
|
|
14
18
|
python3 task.py finish # Clear active task
|
|
@@ -29,7 +33,9 @@ from __future__ import annotations
|
|
|
29
33
|
|
|
30
34
|
import argparse
|
|
31
35
|
import json
|
|
36
|
+
import os
|
|
32
37
|
import sys
|
|
38
|
+
from datetime import datetime, timezone
|
|
33
39
|
from pathlib import Path
|
|
34
40
|
|
|
35
41
|
from common.log import Colors, colored
|
|
@@ -56,7 +62,10 @@ from common.io import (
|
|
|
56
62
|
read_json_checked,
|
|
57
63
|
write_json,
|
|
58
64
|
)
|
|
59
|
-
from common.task_utils import resolve_task_dir, run_task_hooks
|
|
65
|
+
from common.task_utils import is_within_tasks_dir, resolve_task_dir, run_task_hooks
|
|
66
|
+
from common.task_planning import (
|
|
67
|
+
PlanningError, approve_plan, invalidate_plan, require_start_approval, seal_plan,
|
|
68
|
+
)
|
|
60
69
|
from common.tasks import iter_active_tasks, children_progress
|
|
61
70
|
from common.workflow_selection import WORKFLOW_ID_RE, workflow_md_for_task
|
|
62
71
|
|
|
@@ -191,6 +200,58 @@ def _record_start_state(
|
|
|
191
200
|
)
|
|
192
201
|
|
|
193
202
|
|
|
203
|
+
def _active_task_target(task_input: str, repo_root: Path) -> tuple[Path, dict]:
|
|
204
|
+
"""Resolve a live task and enforce the native mutation boundary."""
|
|
205
|
+
target = resolve_task_dir(task_input, repo_root)
|
|
206
|
+
if target is None or not is_within_tasks_dir(target, repo_root):
|
|
207
|
+
raise PlanningError("target must be a direct active task directory")
|
|
208
|
+
task_json = target / FILE_TASK_JSON
|
|
209
|
+
if task_json.is_symlink():
|
|
210
|
+
raise PlanningError("refusing symlinked task.json")
|
|
211
|
+
data, reason = read_json_checked(task_json)
|
|
212
|
+
if data is None:
|
|
213
|
+
raise PlanningError(describe_json_read_failure(task_json, reason)[0])
|
|
214
|
+
if data.get("status") not in {"planning", "in_progress"}:
|
|
215
|
+
raise PlanningError("target task must be planning or in_progress")
|
|
216
|
+
assert_task_mutation_allowed(repo_root, target)
|
|
217
|
+
return target, data
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def cmd_select(args: argparse.Namespace) -> int:
|
|
221
|
+
"""Bind context only; Channel drain is owned by the coordinator procedure."""
|
|
222
|
+
repo_root = get_repo_root()
|
|
223
|
+
try:
|
|
224
|
+
target, _data = _active_task_target(args.dir, repo_root)
|
|
225
|
+
active = set_active_task(target.relative_to(repo_root.resolve()).as_posix(), repo_root)
|
|
226
|
+
if not active:
|
|
227
|
+
raise PlanningError("failed to select current task")
|
|
228
|
+
except (PlanningError, OwnershipError, OSError, ValueError) as exc:
|
|
229
|
+
print(colored(f"Error: {exc}", Colors.RED), file=sys.stderr)
|
|
230
|
+
return 1
|
|
231
|
+
print(colored(f"✓ Task selected without starting: {active.task_path}", Colors.GREEN))
|
|
232
|
+
return 0
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def cmd_plan(args: argparse.Namespace) -> int:
|
|
236
|
+
repo_root = get_repo_root()
|
|
237
|
+
try:
|
|
238
|
+
target, data = _active_task_target(args.dir, repo_root)
|
|
239
|
+
if data.get("status") != "planning":
|
|
240
|
+
raise PlanningError("plan seal/approve requires planning; use replan for a material change")
|
|
241
|
+
if args.plan_command == "seal":
|
|
242
|
+
revision = seal_plan(data, target)
|
|
243
|
+
else:
|
|
244
|
+
approve_plan(data, target, args.revision, args.basis)
|
|
245
|
+
revision = args.revision
|
|
246
|
+
if not write_json(target / FILE_TASK_JSON, data):
|
|
247
|
+
raise PlanningError("could not write planning record")
|
|
248
|
+
except (PlanningError, OwnershipError, OSError, ValueError) as exc:
|
|
249
|
+
print(colored(f"Error: {exc}", Colors.RED), file=sys.stderr)
|
|
250
|
+
return 1
|
|
251
|
+
print(colored(f"✓ Plan {args.plan_command}: revision {revision}", Colors.GREEN))
|
|
252
|
+
return 0
|
|
253
|
+
|
|
254
|
+
|
|
194
255
|
def cmd_start(args: argparse.Namespace) -> int:
|
|
195
256
|
"""Set active task."""
|
|
196
257
|
repo_root = get_repo_root()
|
|
@@ -220,6 +281,19 @@ def cmd_start(args: argparse.Namespace) -> int:
|
|
|
220
281
|
print(colored(f"Error: {exc}", Colors.RED), file=sys.stderr)
|
|
221
282
|
return 2
|
|
222
283
|
|
|
284
|
+
# Reject before writing either the session pointer or task status. The
|
|
285
|
+
# manifest override below never supplies implementation authorization.
|
|
286
|
+
try:
|
|
287
|
+
if not is_within_tasks_dir(full_path, repo_root) or (full_path / FILE_TASK_JSON).is_symlink():
|
|
288
|
+
raise PlanningError("start requires a direct active task with regular task.json")
|
|
289
|
+
task_data, reason = read_json_checked(full_path / FILE_TASK_JSON)
|
|
290
|
+
if task_data is None:
|
|
291
|
+
raise PlanningError(describe_json_read_failure(full_path / FILE_TASK_JSON, reason)[0])
|
|
292
|
+
require_start_approval(task_data, full_path)
|
|
293
|
+
except (PlanningError, OSError, ValueError) as exc:
|
|
294
|
+
print(colored(f"Error: {exc}", Colors.RED), file=sys.stderr)
|
|
295
|
+
return 1
|
|
296
|
+
|
|
223
297
|
# Context-manifest gate (#573): a seeded-but-uncurated implement/check
|
|
224
298
|
# manifest means every sub-agent dispatched for this task runs with zero
|
|
225
299
|
# spec context, and nothing downstream surfaces that to the main session.
|
|
@@ -301,6 +375,80 @@ def cmd_start(args: argparse.Namespace) -> int:
|
|
|
301
375
|
return 1
|
|
302
376
|
|
|
303
377
|
|
|
378
|
+
def cmd_replan(args: argparse.Namespace) -> int:
|
|
379
|
+
"""Return an in-progress task to planning without losing its binding."""
|
|
380
|
+
repo_root = get_repo_root()
|
|
381
|
+
full_path = resolve_task_dir(args.dir, repo_root)
|
|
382
|
+
if full_path is None or not full_path.is_dir():
|
|
383
|
+
print(colored(f"Error: Task not found: {args.dir}", Colors.RED), file=sys.stderr)
|
|
384
|
+
return 1
|
|
385
|
+
|
|
386
|
+
try:
|
|
387
|
+
assert_task_mutation_allowed(repo_root, full_path)
|
|
388
|
+
except (OwnershipError, OSError) as exc:
|
|
389
|
+
print(colored(f"Error: {exc}", Colors.RED), file=sys.stderr)
|
|
390
|
+
return 2
|
|
391
|
+
|
|
392
|
+
reason = " ".join(args.reason).strip()
|
|
393
|
+
if not reason:
|
|
394
|
+
print(colored("Error: replan reason must not be empty", Colors.RED), file=sys.stderr)
|
|
395
|
+
return 1
|
|
396
|
+
|
|
397
|
+
task_json_path = full_path / FILE_TASK_JSON
|
|
398
|
+
data, read_reason = read_json_checked(task_json_path)
|
|
399
|
+
if data is None:
|
|
400
|
+
problem, hint = describe_json_read_failure(task_json_path, read_reason)
|
|
401
|
+
print(colored(f"Error: {problem}", Colors.RED), file=sys.stderr)
|
|
402
|
+
print(hint, file=sys.stderr)
|
|
403
|
+
return 1
|
|
404
|
+
if data.get("status") != "in_progress":
|
|
405
|
+
print(
|
|
406
|
+
colored(
|
|
407
|
+
f"Error: replan requires status=in_progress (found {data.get('status')!r})",
|
|
408
|
+
Colors.RED,
|
|
409
|
+
),
|
|
410
|
+
file=sys.stderr,
|
|
411
|
+
)
|
|
412
|
+
return 1
|
|
413
|
+
|
|
414
|
+
try:
|
|
415
|
+
invalidate_plan(data)
|
|
416
|
+
except PlanningError as exc:
|
|
417
|
+
print(colored(f"Error: {exc}", Colors.RED), file=sys.stderr)
|
|
418
|
+
return 1
|
|
419
|
+
|
|
420
|
+
event = {
|
|
421
|
+
"timestamp": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
|
|
422
|
+
"task": full_path.relative_to(repo_root).as_posix(),
|
|
423
|
+
"from_status": "in_progress",
|
|
424
|
+
"reason": reason,
|
|
425
|
+
"branch": data.get("branch"),
|
|
426
|
+
}
|
|
427
|
+
context_key = resolve_context_key()
|
|
428
|
+
if context_key:
|
|
429
|
+
event["session"] = context_key
|
|
430
|
+
|
|
431
|
+
replans_path = full_path / "replans.jsonl"
|
|
432
|
+
try:
|
|
433
|
+
with replans_path.open("a", encoding="utf-8") as handle:
|
|
434
|
+
handle.write(json.dumps(event, ensure_ascii=False) + "\n")
|
|
435
|
+
handle.flush()
|
|
436
|
+
os.fsync(handle.fileno())
|
|
437
|
+
except OSError as exc:
|
|
438
|
+
print(colored(f"Error: could not record replan: {exc}", Colors.RED), file=sys.stderr)
|
|
439
|
+
return 1
|
|
440
|
+
|
|
441
|
+
data["status"] = "planning"
|
|
442
|
+
if not write_json(task_json_path, data):
|
|
443
|
+
print(colored("Error: replan event recorded but task status was not changed", Colors.RED), file=sys.stderr)
|
|
444
|
+
return 1
|
|
445
|
+
|
|
446
|
+
print(colored(f"✓ Task returned to planning: {full_path.relative_to(repo_root)}", Colors.GREEN))
|
|
447
|
+
print("Reason:", reason)
|
|
448
|
+
run_task_hooks("after_replan", task_json_path, repo_root)
|
|
449
|
+
return 0
|
|
450
|
+
|
|
451
|
+
|
|
304
452
|
def cmd_finish(args: argparse.Namespace) -> int:
|
|
305
453
|
"""Clear active task."""
|
|
306
454
|
repo_root = get_repo_root()
|
|
@@ -373,6 +521,7 @@ def cmd_current(args: argparse.Namespace) -> int:
|
|
|
373
521
|
payload = {
|
|
374
522
|
"current_task": task_obj,
|
|
375
523
|
"source": active.source,
|
|
524
|
+
"session_source": f"session:{active.context_key}" if active.context_key else None,
|
|
376
525
|
"stale": active.stale,
|
|
377
526
|
}
|
|
378
527
|
if active.candidate_paths:
|
|
@@ -731,6 +880,9 @@ def show_usage() -> None:
|
|
|
731
880
|
|
|
732
881
|
Usage:
|
|
733
882
|
python3 task.py create <title> --description <desc> Create new task directory (both required, non-empty)
|
|
883
|
+
python3 task.py select <dir> Select context without starting
|
|
884
|
+
python3 task.py plan seal <dir> Seal the current material plan
|
|
885
|
+
python3 task.py plan approve <dir> --revision N --basis "approval"
|
|
734
886
|
python3 task.py create <title> --description <desc> --package <pkg> Create task for a specific package
|
|
735
887
|
python3 task.py create <title> --description <desc> --parent <dir> Create task as child of parent
|
|
736
888
|
python3 task.py create <title> --description <desc> --no-start Create without making it active in this session
|
|
@@ -739,6 +891,7 @@ Usage:
|
|
|
739
891
|
python3 task.py validate <dir> Validate jsonl files
|
|
740
892
|
python3 task.py list-context <dir> List jsonl entries
|
|
741
893
|
python3 task.py start <dir> Set active task; records the checked-out branch when unset
|
|
894
|
+
python3 task.py replan <dir> "<reason>" Return an in-progress task to planning
|
|
742
895
|
python3 task.py current [--source] Show active task
|
|
743
896
|
python3 task.py finish Clear active task
|
|
744
897
|
python3 task.py workflow <id> Select workflow variant for active task
|
|
@@ -891,6 +1044,18 @@ def main() -> int:
|
|
|
891
1044
|
p_listctx = subparsers.add_parser("list-context", help="List context entries")
|
|
892
1045
|
p_listctx.add_argument("dir", help="Task directory")
|
|
893
1046
|
|
|
1047
|
+
p_select = subparsers.add_parser("select", help="Select a task without changing its phase")
|
|
1048
|
+
p_select.add_argument("dir", help="Existing active task directory")
|
|
1049
|
+
|
|
1050
|
+
p_plan = subparsers.add_parser("plan", help="Seal or record later approval of a material plan")
|
|
1051
|
+
plan_sub = p_plan.add_subparsers(dest="plan_command", required=True)
|
|
1052
|
+
p_seal = plan_sub.add_parser("seal", help="Seal the current material plan revision")
|
|
1053
|
+
p_seal.add_argument("dir", help="Planning task directory")
|
|
1054
|
+
p_approve = plan_sub.add_parser("approve", help="Record actual later user approval")
|
|
1055
|
+
p_approve.add_argument("dir", help="Planning task directory")
|
|
1056
|
+
p_approve.add_argument("--revision", type=int, required=True)
|
|
1057
|
+
p_approve.add_argument("--basis", required=True, help="Short non-sensitive basis for real approval")
|
|
1058
|
+
|
|
894
1059
|
# start
|
|
895
1060
|
p_start = subparsers.add_parser("start", help="Set active task")
|
|
896
1061
|
p_start.add_argument("dir", help="Task directory")
|
|
@@ -900,6 +1065,11 @@ def main() -> int:
|
|
|
900
1065
|
help="Start even when implement.jsonl / check.jsonl have no curated entries",
|
|
901
1066
|
)
|
|
902
1067
|
|
|
1068
|
+
# replan
|
|
1069
|
+
p_replan = subparsers.add_parser("replan", help="Return an in-progress task to planning")
|
|
1070
|
+
p_replan.add_argument("dir", help="Task directory")
|
|
1071
|
+
p_replan.add_argument("reason", nargs="+", help="Material reason for returning to planning")
|
|
1072
|
+
|
|
903
1073
|
# current
|
|
904
1074
|
p_current = subparsers.add_parser("current", help="Show active task")
|
|
905
1075
|
p_current.add_argument("--source", action="store_true",
|
|
@@ -1046,7 +1216,10 @@ def main() -> int:
|
|
|
1046
1216
|
"add-context": cmd_add_context,
|
|
1047
1217
|
"validate": cmd_validate,
|
|
1048
1218
|
"list-context": cmd_list_context,
|
|
1219
|
+
"select": cmd_select,
|
|
1220
|
+
"plan": cmd_plan,
|
|
1049
1221
|
"start": cmd_start,
|
|
1222
|
+
"replan": cmd_replan,
|
|
1050
1223
|
"current": cmd_current,
|
|
1051
1224
|
"continuity": cmd_continuity,
|
|
1052
1225
|
"ownership": cmd_ownership,
|