@pennixrv/trellis 0.6.18 → 0.6.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/commands/channel/adapters/codex.d.ts +14 -0
  2. package/dist/commands/channel/adapters/codex.d.ts.map +1 -1
  3. package/dist/commands/channel/adapters/codex.js +37 -0
  4. package/dist/commands/channel/adapters/codex.js.map +1 -1
  5. package/dist/commands/channel/adapters/index.d.ts.map +1 -1
  6. package/dist/commands/channel/adapters/index.js +49 -13
  7. package/dist/commands/channel/adapters/index.js.map +1 -1
  8. package/dist/commands/channel/index.d.ts.map +1 -1
  9. package/dist/commands/channel/index.js +17 -1
  10. package/dist/commands/channel/index.js.map +1 -1
  11. package/dist/commands/channel/wait.d.ts +4 -0
  12. package/dist/commands/channel/wait.d.ts.map +1 -1
  13. package/dist/commands/channel/wait.js +8 -1
  14. package/dist/commands/channel/wait.js.map +1 -1
  15. package/dist/migrations/manifests/0.6.19.json +9 -0
  16. package/dist/migrations/manifests/0.6.20.json +9 -0
  17. package/dist/templates/common/bundled-skills/trellis-channel/SKILL.md +2 -0
  18. package/dist/templates/common/bundled-skills/trellis-channel/references/command-reference.md +35 -5
  19. package/dist/templates/common/bundled-skills/trellis-channel/references/progress-debugging.md +24 -13
  20. package/dist/templates/common/bundled-skills/trellis-channel/references/subnode-work.md +159 -0
  21. package/dist/templates/common/bundled-skills/trellis-channel/references/workflows.md +6 -3
  22. package/dist/templates/shared-hooks/inject-workflow-state.py +17 -16
  23. package/dist/templates/trellis/agents/subnode.md +62 -0
  24. package/dist/templates/trellis/config.yaml +9 -9
  25. package/dist/templates/trellis/index.d.ts +3 -0
  26. package/dist/templates/trellis/index.d.ts.map +1 -1
  27. package/dist/templates/trellis/index.js +6 -0
  28. package/dist/templates/trellis/index.js.map +1 -1
  29. package/dist/templates/trellis/scripts/common/config.py +5 -4
  30. package/dist/templates/trellis/scripts/common/task_store.py +3 -3
  31. package/dist/templates/trellis/scripts/common/workflow_phase.py +1 -1
  32. package/dist/templates/trellis/scripts/subnode_artifact.py +498 -0
  33. package/dist/templates/trellis/scripts/workspace_note.py +126 -0
  34. package/dist/templates/trellis/workflow.md +5 -5
  35. package/package.json +2 -2
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env python3
2
+ """Append one bounded coordinator note to the current developer workspace."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import os
8
+ import re
9
+ import sys
10
+ from datetime import datetime, timezone
11
+ from pathlib import Path
12
+ from typing import NoReturn
13
+
14
+ from common.paths import DIR_WORKFLOW, DIR_WORKSPACE, get_developer, get_repo_root, get_workspace_dir
15
+
16
+
17
+ ALLOWED_KINDS = {"observation", "decision", "open-question", "blocker"}
18
+ MAX_SUMMARY_LENGTH = 600
19
+ MAX_SOURCES = 5
20
+ MAX_SOURCE_LENGTH = 1024
21
+ SECRET_PATTERNS = (
22
+ re.compile(r"-----BEGIN [A-Z ]*PRIVATE KEY-----"),
23
+ re.compile(r"\bsk-[A-Za-z0-9]{20,}\b"),
24
+ re.compile(r"\bgh[pousr]_[A-Za-z0-9]{20,}\b"),
25
+ )
26
+
27
+
28
+ class WorkspaceNoteError(Exception):
29
+ """A user-correctable workspace-note failure."""
30
+
31
+
32
+ def _fail(message: str) -> NoReturn:
33
+ raise WorkspaceNoteError(message)
34
+
35
+
36
+ def _validate_text(value: str, field: str, max_length: int) -> str:
37
+ if not value.strip() or len(value) > max_length:
38
+ _fail(f"{field} must be a non-empty string of at most {max_length} characters")
39
+ if "\n" in value or "\r" in value or "\x00" in value:
40
+ _fail(f"{field} must be a single line without control characters")
41
+ for pattern in SECRET_PATTERNS:
42
+ if pattern.search(value):
43
+ _fail(f"{field} appears to contain a credential")
44
+ return value
45
+
46
+
47
+ def _workspace_path(repo_root: Path) -> Path:
48
+ developer = get_developer(repo_root)
49
+ workspace_dir = get_workspace_dir(repo_root)
50
+ if not developer or workspace_dir is None:
51
+ _fail("developer is not initialized; run init_developer.py first")
52
+ workspace_root = repo_root / DIR_WORKFLOW / DIR_WORKSPACE
53
+ if workspace_dir.is_symlink():
54
+ _fail(f"refusing symlinked developer workspace: {workspace_dir}")
55
+ try:
56
+ workspace_root_resolved = workspace_root.resolve(strict=True)
57
+ workspace_resolved = workspace_dir.resolve(strict=True)
58
+ except (OSError, RuntimeError) as exc:
59
+ _fail(f"could not resolve developer workspace: {exc}")
60
+ if workspace_resolved.parent != workspace_root_resolved:
61
+ _fail("developer workspace is not a direct workspace child")
62
+ if workspace_dir.name != developer:
63
+ _fail("developer identity does not name its workspace directory")
64
+ return workspace_dir / "working-notes.md"
65
+
66
+
67
+ def _append_record(path: Path, record: str) -> None:
68
+ if path.is_symlink():
69
+ _fail(f"refusing symlinked working notes file: {path}")
70
+ flags = os.O_APPEND | os.O_CREAT | os.O_WRONLY
71
+ if hasattr(os, "O_BINARY"):
72
+ flags |= os.O_BINARY
73
+ try:
74
+ descriptor = os.open(path, flags, 0o600)
75
+ try:
76
+ data = record.encode("utf-8")
77
+ written = os.write(descriptor, data)
78
+ if written != len(data):
79
+ _fail("could not append the complete workspace note")
80
+ os.fsync(descriptor)
81
+ finally:
82
+ os.close(descriptor)
83
+ except OSError as exc:
84
+ _fail(f"could not append workspace note {path}: {exc}")
85
+
86
+
87
+ def _main(args: argparse.Namespace) -> None:
88
+ if args.kind not in ALLOWED_KINDS:
89
+ _fail(f"--kind must be one of: {', '.join(sorted(ALLOWED_KINDS))}")
90
+ summary = _validate_text(args.summary, "--summary", MAX_SUMMARY_LENGTH)
91
+ if len(args.source) > MAX_SOURCES:
92
+ _fail(f"at most {MAX_SOURCES} --source values are allowed")
93
+ sources = [
94
+ _validate_text(value, "--source", MAX_SOURCE_LENGTH)
95
+ for value in args.source
96
+ ]
97
+ repo_root = get_repo_root()
98
+ path = _workspace_path(repo_root)
99
+ timestamp = datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
100
+ lines = [f"## {timestamp} | {args.kind}", "", summary]
101
+ if sources:
102
+ lines.extend(["", "Sources:"])
103
+ lines.extend(f"- {source}" for source in sources)
104
+ _append_record(path, "\n".join(lines) + "\n\n")
105
+ print(path.relative_to(repo_root).as_posix())
106
+
107
+
108
+ def _parser() -> argparse.ArgumentParser:
109
+ parser = argparse.ArgumentParser(description=__doc__)
110
+ parser.add_argument("--kind", required=True, choices=sorted(ALLOWED_KINDS))
111
+ parser.add_argument("--summary", required=True)
112
+ parser.add_argument("--source", action="append", default=[])
113
+ return parser
114
+
115
+
116
+ def main() -> int:
117
+ try:
118
+ _main(_parser().parse_args())
119
+ except WorkspaceNoteError as exc:
120
+ print(f"Error: {exc}", file=sys.stderr)
121
+ return 1
122
+ return 0
123
+
124
+
125
+ if __name__ == "__main__":
126
+ sys.exit(main())
@@ -207,8 +207,8 @@ Multi-deliverable scope: consider a parent task plus independently verifiable ch
207
207
  Sub-agent mode: curate `implement.jsonl` and `check.jsonl` as spec/research manifests before start.
208
208
  [/workflow-state:planning]
209
209
 
210
- <!-- Per-turn breadcrumb: shown throughout Phase 1 when codex.dispatch_mode=inline.
211
- Codex-only opt-in alternate to [workflow-state:planning]. The main agent
210
+ <!-- Per-turn breadcrumb: shown throughout Phase 1 when Codex uses its default
211
+ codex.dispatch_mode=inline. Codex-only alternate to [workflow-state:planning]. The main agent
212
212
  edits code directly in Phase 2, so jsonl curation is skipped —
213
213
  the inline workflow loads `trellis-before-dev` instead of injecting JSONL
214
214
  into a sub-agent. -->
@@ -236,12 +236,12 @@ Sub-agent dispatch protocol applies to all platforms and all sub-agents, includi
236
236
  [workflow-state:in_progress]
237
237
  Tools: `trellis-implement` / `trellis-research` are sub-agent types only (Task/Agent tool, NOT Skill; there is no skill by these names). `trellis-update-spec` is a skill. `trellis-check` exists as both; prefer the Agent form when verifying after code changes.
238
238
  Flow: `trellis-implement` -> `trellis-check` -> `trellis-update-spec` -> commit (Phase 3.4) -> `/trellis:finish-work`.
239
- Main-session default: dispatch implement/check sub-agents. Sub-agent self-exemption: if already running as `trellis-implement`, do NOT spawn another `trellis-implement` or `trellis-check`; if already running as `trellis-check`, do NOT spawn another `trellis-check` or `trellis-implement`. Dispatch is main session only.
239
+ Use this block only when `codex.dispatch_mode: auto` is explicitly selected. Sub-agent self-exemption: if already running as `trellis-implement`, do NOT spawn another `trellis-implement` or `trellis-check`; if already running as `trellis-check`, do NOT spawn another `trellis-check` or `trellis-implement`. Dispatch is main session only.
240
240
  Dispatch prompt starts with `Active task: <task path from task.py current>`. Read context: jsonl entries -> `prd.md` -> `design.md if present` -> `implement.md if present`.
241
241
  [/workflow-state:in_progress]
242
242
 
243
- <!-- Per-turn breadcrumb: shown while status='in_progress' when
244
- codex.dispatch_mode=inline. Codex-only opt-in alternate to
243
+ <!-- Per-turn breadcrumb: shown while status='in_progress' when Codex uses its
244
+ default codex.dispatch_mode=inline. Codex-only alternate to
245
245
  [workflow-state:in_progress]. The main session edits code directly
246
246
  instead of dispatching sub-agents. -->
247
247
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pennixrv/trellis",
3
- "version": "0.6.18",
3
+ "version": "0.6.20",
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",
@@ -34,7 +34,7 @@
34
34
  "inquirer": "^9.3.7",
35
35
  "undici": "^6.21.0",
36
36
  "zod": "^4.4.2",
37
- "@pennixrv/trellis-core": "0.6.18"
37
+ "@pennixrv/trellis-core": "0.6.20"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@eslint/js": "^9.18.0",