@pennixrv/trellis 0.6.40 → 0.6.41
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.
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.6.41",
|
|
3
|
+
"description": "Restores active-task visibility when a host context key has no persisted session file.",
|
|
4
|
+
"breaking": false,
|
|
5
|
+
"recommendMigrate": false,
|
|
6
|
+
"changelog": "**Fix:**\n- Projects one unique developer-owned resumable task as read-only workflow context when the host provides a context key whose session file is missing, while still refusing to guess when another session pointer exists.",
|
|
7
|
+
"migrations": [],
|
|
8
|
+
"notes": "No project migration is required. Existing projects can run the normal trellis update flow."
|
|
9
|
+
}
|
|
@@ -373,7 +373,8 @@ export class TrellisContext {
|
|
|
373
373
|
*
|
|
374
374
|
* Resolution order (mirrors Python `active_task.resolve_active_task`):
|
|
375
375
|
* 1. Lookup the runtime file for the input-derived context key. A known
|
|
376
|
-
* key is authoritative
|
|
376
|
+
* key is authoritative when it contains a task; a missing or empty
|
|
377
|
+
* context may use the guarded unbound-task projection.
|
|
377
378
|
* 2. If no context key is available and exactly one session runtime file
|
|
378
379
|
* exists locally, use it (`_resolveSingleSessionFallback`). Refuses to
|
|
379
380
|
* guess when 0 or ≥2 files exist so multi-window isolation holds.
|
|
@@ -393,6 +394,10 @@ export class TrellisContext {
|
|
|
393
394
|
stale: !taskDir || !existsSync(taskDir),
|
|
394
395
|
}
|
|
395
396
|
}
|
|
397
|
+
const unbound = this._resolveUnboundTask()
|
|
398
|
+
if (unbound) {
|
|
399
|
+
return unbound
|
|
400
|
+
}
|
|
396
401
|
return { taskPath: null, source: "none", stale: false }
|
|
397
402
|
}
|
|
398
403
|
|
|
@@ -456,7 +461,14 @@ export class TrellisContext {
|
|
|
456
461
|
} catch {
|
|
457
462
|
return null
|
|
458
463
|
}
|
|
459
|
-
if (sessionFiles.
|
|
464
|
+
if (sessionFiles.some(file => {
|
|
465
|
+
try {
|
|
466
|
+
const context = JSON.parse(readFileSync(join(sessionsDir, file), "utf-8"))
|
|
467
|
+
return Boolean(this.normalizeTaskRef(context?.current_task || ""))
|
|
468
|
+
} catch {
|
|
469
|
+
return false
|
|
470
|
+
}
|
|
471
|
+
})) return null
|
|
460
472
|
}
|
|
461
473
|
|
|
462
474
|
const developer = (process.env.TRELLIS_DEVELOPER || "").trim() || (() => {
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"""Session-scoped active task resolution.
|
|
3
3
|
|
|
4
4
|
The user-facing concept is a single "active task". Trellis stores that pointer
|
|
5
|
-
per AI session/window under `.trellis/.runtime/sessions/`;
|
|
6
|
-
|
|
5
|
+
per AI session/window under `.trellis/.runtime/sessions/`; when the pointer is
|
|
6
|
+
missing, a unique developer-owned resumable task may be exposed read-only.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
from __future__ import annotations
|
|
@@ -654,9 +654,10 @@ def resolve_active_task(
|
|
|
654
654
|
"""Resolve the active task from session runtime state only.
|
|
655
655
|
|
|
656
656
|
A stale session task is returned as stale. A known context identity is
|
|
657
|
-
authoritative
|
|
658
|
-
task. When context identity
|
|
659
|
-
|
|
657
|
+
authoritative when it contains a task reference; a missing or empty
|
|
658
|
+
context may use the guarded unbound-task projection. When context identity
|
|
659
|
+
is unavailable, single-session inference may cover pull-based platform
|
|
660
|
+
sub-agents (copilot, gemini, qoder) that don't
|
|
660
661
|
inherit the parent's session id. ≥2 files or 0 files yield
|
|
661
662
|
ActiveTask(None) — refuses to guess across windows.
|
|
662
663
|
"""
|
|
@@ -671,6 +672,10 @@ def resolve_active_task(
|
|
|
671
672
|
active = _active_from_ref(task_ref, repo_root, "session", context_key)
|
|
672
673
|
if active:
|
|
673
674
|
return active
|
|
675
|
+
if allow_single_session_fallback:
|
|
676
|
+
unbound = _resolve_unbound_task(repo_root)
|
|
677
|
+
if unbound is not None:
|
|
678
|
+
return unbound
|
|
674
679
|
return ActiveTask(None, "none", context_key)
|
|
675
680
|
|
|
676
681
|
if allow_single_session_fallback:
|
|
@@ -713,8 +718,10 @@ def _resolve_single_session_fallback(repo_root: Path) -> ActiveTask | None:
|
|
|
713
718
|
def _resolve_unbound_task(repo_root: Path) -> ActiveTask | None:
|
|
714
719
|
"""Expose one developer-owned task when no session pointer exists."""
|
|
715
720
|
sessions_dir = _runtime_sessions_dir(repo_root)
|
|
716
|
-
if sessions_dir.is_dir()
|
|
717
|
-
|
|
721
|
+
if sessions_dir.is_dir():
|
|
722
|
+
session_files = sorted(sessions_dir.glob("*.json"))
|
|
723
|
+
if any(_string_value((_read_json(session) or {}).get("current_task")) for session in session_files):
|
|
724
|
+
return None
|
|
718
725
|
|
|
719
726
|
from .paths import get_developer, get_tasks_dir
|
|
720
727
|
from .tasks import iter_active_tasks
|
|
@@ -76,7 +76,7 @@ python3 ./.trellis/scripts/task.py create-pr [name] [--dry-run]
|
|
|
76
76
|
|
|
77
77
|
> Run `python3 ./.trellis/scripts/task.py --help` to see the authoritative, up-to-date list.
|
|
78
78
|
|
|
79
|
-
**Current-task mechanism**: `task.py create` creates the task directory and (when session identity is available) auto-sets the per-session active-task pointer so the planning breadcrumb fires immediately. `task.py start` writes the same pointer (idempotent if already set) and flips `task.json.status` from `planning` to `in_progress`. State is stored under `.trellis/.runtime/sessions/`. If no context key is available from hook input, `TRELLIS_CONTEXT_ID`, or a platform-native session environment variable,
|
|
79
|
+
**Current-task mechanism**: `task.py create` creates the task directory and (when session identity is available) auto-sets the per-session active-task pointer so the planning breadcrumb fires immediately. `task.py start` writes the same pointer (idempotent if already set) and flips `task.json.status` from `planning` to `in_progress`. State is stored under `.trellis/.runtime/sessions/`. If no context key is available from hook input, `TRELLIS_CONTEXT_ID`, or a platform-native session environment variable, `task.py start` fails with a session identity hint because it cannot persist a session pointer; read-only context may still project one unique developer-owned resumable task. `task.py finish` deletes the current session file (status unchanged). `task.py archive <task>` writes `status=completed`, moves the directory to `archive/`, and deletes any runtime session files that still point at the archived task.
|
|
80
80
|
|
|
81
81
|
### Workspace System
|
|
82
82
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pennixrv/trellis",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.41",
|
|
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.
|
|
37
|
+
"@pennixrv/trellis-core": "0.6.41"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@eslint/js": "^9.18.0",
|