@sienklogic/plan-build-run 2.51.0 → 2.53.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/CHANGELOG.md +28 -0
- package/package.json +4 -2
- package/plugins/copilot-pbr/agents/audit.agent.md +2 -5
- package/plugins/copilot-pbr/agents/codebase-mapper.agent.md +1 -4
- package/plugins/copilot-pbr/agents/debugger.agent.md +1 -4
- package/plugins/copilot-pbr/agents/dev-sync.agent.md +6 -9
- package/plugins/copilot-pbr/agents/executor.agent.md +1 -6
- package/plugins/copilot-pbr/agents/general.agent.md +1 -4
- package/plugins/copilot-pbr/agents/integration-checker.agent.md +1 -4
- package/plugins/copilot-pbr/agents/plan-checker.agent.md +1 -4
- package/plugins/copilot-pbr/agents/planner.agent.md +1 -4
- package/plugins/copilot-pbr/agents/researcher.agent.md +1 -4
- package/plugins/copilot-pbr/agents/synthesizer.agent.md +1 -4
- package/plugins/copilot-pbr/agents/verifier.agent.md +2 -4
- package/plugins/copilot-pbr/commands/audit.md +5 -0
- package/plugins/copilot-pbr/commands/begin.md +5 -0
- package/plugins/copilot-pbr/commands/build.md +5 -0
- package/plugins/copilot-pbr/commands/config.md +5 -0
- package/plugins/copilot-pbr/commands/continue.md +5 -0
- package/plugins/copilot-pbr/commands/dashboard.md +5 -0
- package/plugins/copilot-pbr/commands/debug.md +5 -0
- package/plugins/copilot-pbr/commands/discuss.md +5 -0
- package/plugins/copilot-pbr/commands/do.md +5 -0
- package/plugins/copilot-pbr/commands/explore.md +5 -0
- package/plugins/copilot-pbr/commands/health.md +5 -0
- package/plugins/copilot-pbr/commands/help.md +5 -0
- package/plugins/copilot-pbr/commands/import.md +5 -0
- package/plugins/copilot-pbr/commands/milestone.md +5 -0
- package/plugins/copilot-pbr/commands/note.md +5 -0
- package/plugins/copilot-pbr/commands/pause.md +5 -0
- package/plugins/copilot-pbr/commands/plan.md +5 -0
- package/plugins/copilot-pbr/commands/quick.md +5 -0
- package/plugins/copilot-pbr/commands/resume.md +5 -0
- package/plugins/copilot-pbr/commands/review.md +5 -0
- package/plugins/copilot-pbr/commands/scan.md +5 -0
- package/plugins/copilot-pbr/commands/setup.md +5 -0
- package/plugins/copilot-pbr/commands/status.md +5 -0
- package/plugins/copilot-pbr/commands/statusline.md +5 -0
- package/plugins/copilot-pbr/commands/todo.md +5 -0
- package/plugins/copilot-pbr/plugin.json +1 -1
- package/plugins/copilot-pbr/references/agent-teams.md +0 -1
- package/plugins/copilot-pbr/references/common-bug-patterns.md +0 -1
- package/plugins/copilot-pbr/references/config-reference.md +0 -1
- package/plugins/copilot-pbr/references/continuation-format.md +0 -1
- package/plugins/copilot-pbr/references/deviation-rules.md +0 -1
- package/plugins/copilot-pbr/references/git-integration.md +0 -1
- package/plugins/copilot-pbr/references/integration-patterns.md +0 -1
- package/plugins/copilot-pbr/references/model-profiles.md +0 -1
- package/plugins/copilot-pbr/references/model-selection.md +0 -1
- package/plugins/copilot-pbr/references/plan-authoring.md +0 -1
- package/plugins/copilot-pbr/references/plan-format.md +0 -1
- package/plugins/copilot-pbr/references/reading-verification.md +0 -1
- package/plugins/copilot-pbr/references/signal-files.md +41 -0
- package/plugins/copilot-pbr/references/stub-patterns.md +0 -1
- package/plugins/copilot-pbr/references/wave-execution.md +0 -1
- package/plugins/copilot-pbr/skills/begin/SKILL.md +74 -52
- package/plugins/copilot-pbr/skills/build/SKILL.md +55 -69
- package/plugins/copilot-pbr/skills/config/SKILL.md +7 -0
- package/plugins/copilot-pbr/skills/continue/SKILL.md +31 -24
- package/plugins/copilot-pbr/skills/dashboard/SKILL.md +8 -7
- package/plugins/copilot-pbr/skills/debug/SKILL.md +11 -0
- package/plugins/copilot-pbr/skills/discuss/SKILL.md +2 -0
- package/plugins/copilot-pbr/skills/do/SKILL.md +2 -0
- package/plugins/copilot-pbr/skills/explore/SKILL.md +7 -1
- package/plugins/copilot-pbr/skills/health/SKILL.md +2 -0
- package/plugins/copilot-pbr/skills/help/SKILL.md +6 -0
- package/plugins/copilot-pbr/skills/import/SKILL.md +9 -0
- package/plugins/copilot-pbr/skills/milestone/SKILL.md +20 -196
- package/plugins/copilot-pbr/skills/note/SKILL.md +2 -0
- package/plugins/copilot-pbr/skills/pause/SKILL.md +5 -0
- package/plugins/copilot-pbr/skills/plan/SKILL.md +87 -119
- package/plugins/copilot-pbr/skills/quick/SKILL.md +13 -8
- package/plugins/copilot-pbr/skills/resume/SKILL.md +4 -0
- package/plugins/copilot-pbr/skills/review/SKILL.md +85 -47
- package/plugins/copilot-pbr/skills/scan/SKILL.md +6 -0
- package/plugins/copilot-pbr/skills/setup/SKILL.md +2 -0
- package/plugins/copilot-pbr/skills/shared/commit-planning-docs.md +0 -1
- package/plugins/copilot-pbr/skills/shared/config-loading.md +0 -1
- package/plugins/copilot-pbr/skills/shared/context-budget.md +0 -1
- package/plugins/copilot-pbr/skills/shared/context-loader-task.md +0 -1
- package/plugins/copilot-pbr/skills/shared/digest-select.md +0 -1
- package/plugins/copilot-pbr/skills/shared/domain-probes.md +0 -1
- package/plugins/copilot-pbr/skills/shared/gate-prompts.md +0 -1
- package/plugins/copilot-pbr/skills/shared/phase-argument-parsing.md +0 -1
- package/plugins/copilot-pbr/skills/shared/revision-loop.md +0 -1
- package/plugins/copilot-pbr/skills/shared/state-update.md +0 -1
- package/plugins/copilot-pbr/skills/shared/universal-anti-patterns.md +1 -2
- package/plugins/copilot-pbr/skills/status/SKILL.md +35 -26
- package/plugins/copilot-pbr/skills/test/SKILL.md +2 -2
- package/plugins/copilot-pbr/skills/todo/SKILL.md +2 -0
- package/plugins/copilot-pbr/templates/CONTEXT.md.tmpl +0 -1
- package/plugins/copilot-pbr/templates/INTEGRATION-REPORT.md.tmpl +0 -1
- package/plugins/copilot-pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -1
- package/plugins/copilot-pbr/templates/ROADMAP.md.tmpl +0 -1
- package/plugins/copilot-pbr/templates/SUMMARY.md.tmpl +0 -1
- package/plugins/copilot-pbr/templates/VERIFICATION-DETAIL.md.tmpl +0 -1
- package/plugins/copilot-pbr/templates/continue-here.md.tmpl +0 -1
- package/plugins/copilot-pbr/templates/prompt-partials/phase-project-context.md.tmpl +0 -1
- package/plugins/cursor-pbr/.cursor-plugin/plugin.json +1 -1
- package/plugins/cursor-pbr/agents/audit.md +1 -1
- package/plugins/cursor-pbr/agents/codebase-mapper.md +1 -1
- package/plugins/cursor-pbr/agents/debugger.md +1 -1
- package/plugins/cursor-pbr/agents/dev-sync.md +6 -6
- package/plugins/cursor-pbr/agents/executor.md +1 -3
- package/plugins/cursor-pbr/agents/general.md +1 -1
- package/plugins/cursor-pbr/agents/integration-checker.md +2 -2
- package/plugins/cursor-pbr/agents/plan-checker.md +2 -2
- package/plugins/cursor-pbr/agents/planner.md +1 -1
- package/plugins/cursor-pbr/agents/researcher.md +2 -2
- package/plugins/cursor-pbr/agents/synthesizer.md +1 -1
- package/plugins/cursor-pbr/agents/verifier.md +3 -2
- package/plugins/cursor-pbr/commands/audit.md +5 -0
- package/plugins/cursor-pbr/commands/begin.md +5 -0
- package/plugins/cursor-pbr/commands/build.md +5 -0
- package/plugins/cursor-pbr/commands/config.md +5 -0
- package/plugins/cursor-pbr/commands/continue.md +5 -0
- package/plugins/cursor-pbr/commands/dashboard.md +5 -0
- package/plugins/cursor-pbr/commands/debug.md +5 -0
- package/plugins/cursor-pbr/commands/discuss.md +5 -0
- package/plugins/cursor-pbr/commands/do.md +5 -0
- package/plugins/cursor-pbr/commands/explore.md +5 -0
- package/plugins/cursor-pbr/commands/health.md +5 -0
- package/plugins/cursor-pbr/commands/help.md +5 -0
- package/plugins/cursor-pbr/commands/import.md +5 -0
- package/plugins/cursor-pbr/commands/milestone.md +5 -0
- package/plugins/cursor-pbr/commands/note.md +5 -0
- package/plugins/cursor-pbr/commands/pause.md +5 -0
- package/plugins/cursor-pbr/commands/plan.md +5 -0
- package/plugins/cursor-pbr/commands/quick.md +5 -0
- package/plugins/cursor-pbr/commands/resume.md +5 -0
- package/plugins/cursor-pbr/commands/review.md +5 -0
- package/plugins/cursor-pbr/commands/scan.md +5 -0
- package/plugins/cursor-pbr/commands/setup.md +5 -0
- package/plugins/cursor-pbr/commands/status.md +5 -0
- package/plugins/cursor-pbr/commands/statusline.md +5 -0
- package/plugins/cursor-pbr/commands/todo.md +5 -0
- package/plugins/cursor-pbr/hooks/hooks.json +4 -10
- package/plugins/cursor-pbr/references/agent-teams.md +0 -1
- package/plugins/{copilot-pbr/references → cursor-pbr/references/archive}/agent-anti-patterns.md +0 -1
- package/plugins/cursor-pbr/references/{pbr-rules.md → archive/pbr-rules.md} +0 -1
- package/plugins/cursor-pbr/references/common-bug-patterns.md +0 -1
- package/plugins/cursor-pbr/references/config-reference.md +0 -1
- package/plugins/cursor-pbr/references/continuation-format.md +0 -1
- package/plugins/cursor-pbr/references/deviation-rules.md +0 -1
- package/plugins/cursor-pbr/references/git-integration.md +0 -1
- package/plugins/cursor-pbr/references/integration-patterns.md +0 -1
- package/plugins/cursor-pbr/references/model-profiles.md +0 -1
- package/plugins/cursor-pbr/references/model-selection.md +0 -1
- package/plugins/cursor-pbr/references/plan-authoring.md +0 -1
- package/plugins/cursor-pbr/references/plan-format.md +0 -1
- package/plugins/cursor-pbr/references/reading-verification.md +0 -1
- package/plugins/cursor-pbr/references/signal-files.md +41 -0
- package/plugins/cursor-pbr/references/stub-patterns.md +0 -1
- package/plugins/cursor-pbr/references/wave-execution.md +0 -1
- package/plugins/cursor-pbr/skills/begin/SKILL.md +74 -52
- package/plugins/cursor-pbr/skills/build/SKILL.md +58 -70
- package/plugins/cursor-pbr/skills/config/SKILL.md +5 -0
- package/plugins/cursor-pbr/skills/continue/SKILL.md +31 -24
- package/plugins/cursor-pbr/skills/dashboard/SKILL.md +8 -7
- package/plugins/cursor-pbr/skills/debug/SKILL.md +8 -0
- package/plugins/cursor-pbr/skills/discuss/SKILL.md +2 -0
- package/plugins/cursor-pbr/skills/do/SKILL.md +2 -0
- package/plugins/cursor-pbr/skills/explore/SKILL.md +5 -1
- package/plugins/cursor-pbr/skills/health/SKILL.md +2 -0
- package/plugins/cursor-pbr/skills/help/SKILL.md +6 -0
- package/plugins/cursor-pbr/skills/import/SKILL.md +7 -0
- package/plugins/cursor-pbr/skills/milestone/SKILL.md +20 -196
- package/plugins/cursor-pbr/skills/note/SKILL.md +2 -0
- package/plugins/cursor-pbr/skills/pause/SKILL.md +4 -0
- package/plugins/cursor-pbr/skills/plan/SKILL.md +87 -119
- package/plugins/cursor-pbr/skills/quick/SKILL.md +13 -8
- package/plugins/cursor-pbr/skills/resume/SKILL.md +4 -0
- package/plugins/cursor-pbr/skills/review/SKILL.md +85 -47
- package/plugins/cursor-pbr/skills/scan/SKILL.md +5 -0
- package/plugins/cursor-pbr/skills/setup/SKILL.md +2 -0
- package/plugins/cursor-pbr/skills/shared/commit-planning-docs.md +0 -1
- package/plugins/cursor-pbr/skills/shared/config-loading.md +0 -1
- package/plugins/cursor-pbr/skills/shared/context-budget.md +0 -1
- package/plugins/cursor-pbr/skills/shared/context-loader-task.md +0 -1
- package/plugins/cursor-pbr/skills/shared/digest-select.md +0 -1
- package/plugins/cursor-pbr/skills/shared/domain-probes.md +0 -1
- package/plugins/cursor-pbr/skills/shared/gate-prompts.md +0 -1
- package/plugins/cursor-pbr/skills/shared/phase-argument-parsing.md +0 -1
- package/plugins/cursor-pbr/skills/shared/revision-loop.md +0 -1
- package/plugins/cursor-pbr/skills/shared/state-update.md +0 -1
- package/plugins/cursor-pbr/skills/shared/universal-anti-patterns.md +1 -2
- package/plugins/cursor-pbr/skills/status/SKILL.md +35 -26
- package/plugins/cursor-pbr/skills/test/SKILL.md +2 -2
- package/plugins/cursor-pbr/skills/todo/SKILL.md +2 -0
- package/plugins/cursor-pbr/templates/CONTEXT.md.tmpl +0 -1
- package/plugins/cursor-pbr/templates/INTEGRATION-REPORT.md.tmpl +0 -1
- package/plugins/cursor-pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -1
- package/plugins/cursor-pbr/templates/ROADMAP.md.tmpl +0 -1
- package/plugins/cursor-pbr/templates/SUMMARY.md.tmpl +0 -1
- package/plugins/cursor-pbr/templates/VERIFICATION-DETAIL.md.tmpl +0 -1
- package/plugins/cursor-pbr/templates/continue-here.md.tmpl +0 -1
- package/plugins/cursor-pbr/templates/prompt-partials/phase-project-context.md.tmpl +0 -1
- package/plugins/pbr/.claude-plugin/plugin.json +1 -1
- package/plugins/pbr/agents/executor.md +0 -2
- package/plugins/{cursor-pbr/references → pbr/references/archive}/agent-anti-patterns.md +0 -1
- package/plugins/{copilot-pbr/references → pbr/references/archive}/pbr-rules.md +0 -1
- package/plugins/pbr/references/signal-files.md +41 -0
- package/plugins/pbr/scripts/check-skill-workflow.js +7 -8
- package/plugins/pbr/scripts/check-subagent-output.js +7 -6
- package/plugins/pbr/scripts/context-budget-check.js +13 -1
- package/plugins/pbr/scripts/enforce-pbr-workflow.js +15 -6
- package/plugins/pbr/scripts/lib/core.js +53 -1
- package/plugins/pbr/scripts/log-subagent.js +7 -10
- package/plugins/pbr/scripts/pbr-tools.js +49 -3
- package/plugins/pbr/scripts/progress-tracker.js +13 -3
- package/plugins/pbr/scripts/session-cleanup.js +6 -0
- package/plugins/pbr/scripts/suggest-compact.js +13 -1
- package/plugins/pbr/skills/begin/SKILL.md +13 -13
- package/plugins/pbr/skills/build/SKILL.md +24 -7
- package/plugins/pbr/skills/milestone/SKILL.md +10 -10
- package/plugins/pbr/skills/plan/SKILL.md +9 -9
- package/plugins/pbr/skills/quick/SKILL.md +3 -3
- package/plugins/pbr/skills/review/SKILL.md +6 -6
- /package/plugins/{pbr/references → copilot-pbr/references/archive}/agent-anti-patterns.md +0 -0
- /package/plugins/copilot-pbr/references/{checkpoints.md → archive/checkpoints.md} +0 -0
- /package/plugins/copilot-pbr/references/{context-quality-tiers.md → archive/context-quality-tiers.md} +0 -0
- /package/plugins/{pbr/references → copilot-pbr/references/archive}/pbr-rules.md +0 -0
- /package/plugins/copilot-pbr/references/{verification-patterns.md → archive/verification-patterns.md} +0 -0
- /package/plugins/cursor-pbr/references/{checkpoints.md → archive/checkpoints.md} +0 -0
- /package/plugins/cursor-pbr/references/{context-quality-tiers.md → archive/context-quality-tiers.md} +0 -0
- /package/plugins/cursor-pbr/references/{verification-patterns.md → archive/verification-patterns.md} +0 -0
- /package/plugins/pbr/references/{checkpoints.md → archive/checkpoints.md} +0 -0
- /package/plugins/pbr/references/{context-quality-tiers.md → archive/context-quality-tiers.md} +0 -0
- /package/plugins/pbr/references/{verification-patterns.md → archive/verification-patterns.md} +0 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
<!-- canonical: ../../../pbr/templates/prompt-partials/phase-project-context.md.tmpl -->
|
|
2
1
|
<!-- Source: templates/prompt-partials/ | Purpose: Shared context blocks for agent prompt templates -->
|
|
3
2
|
<!-- Usage: Read this file and fill in placeholders, then include the result in agent prompts. -->
|
|
4
3
|
<!-- Orchestrators should omit sections that don't apply to their agent type. -->
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbr",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.53.0",
|
|
4
4
|
"description": "Plan-Build-Run — Structured development workflow for Claude Code. Solves context rot through disciplined subagent delegation, structured planning, atomic execution, and goal-backward verification.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "SienkLogic",
|
|
@@ -141,8 +141,6 @@ Only append to the LAST commit of the plan — intermediate commits (RED/GREEN i
|
|
|
141
141
|
|
|
142
142
|
## Deviation Rules
|
|
143
143
|
|
|
144
|
-
Reference: `references/deviation-rules.md` for examples and decision tree.
|
|
145
|
-
|
|
146
144
|
| Rule | Trigger | Action | Approval |
|
|
147
145
|
|------|---------|--------|----------|
|
|
148
146
|
| 1 — Bug | Code bug (typo, wrong import, syntax) | Auto-fix in same commit. 3 attempts max. | No |
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Signal Files Reference
|
|
2
|
+
|
|
3
|
+
Signal files are ephemeral files in `.planning/` that coordinate state between hook scripts
|
|
4
|
+
and skills. They are scoped to either the current session or the current phase/plan.
|
|
5
|
+
|
|
6
|
+
## Session-Scoped Files
|
|
7
|
+
|
|
8
|
+
All 5 session signals are consolidated in `.planning/.session.json`. Scripts must read and write
|
|
9
|
+
`.session.json` via `pbr-tools session get|set|clear` — never read the raw `.session.json` file directly.
|
|
10
|
+
The `.session.json` schema is an object with the keys documented below.
|
|
11
|
+
|
|
12
|
+
| JSON Key | Former File | Written By | Read By | Semantics |
|
|
13
|
+
|----------|-------------|------------|---------|-----------|
|
|
14
|
+
| `activeSkill` | `.active-skill` | Skills (Write tool) | check-skill-workflow, enforce-pbr-workflow, check-subagent-output, log-subagent, block-skill-self-read | Which skill is active. Written at skill start, cleared at skill end (session-cleanup). |
|
|
15
|
+
| `compactCounter` | `.compact-counter` | suggest-compact.js | suggest-compact.js | Write count since last /compact. Resets on SessionStart. |
|
|
16
|
+
| `sessionStart` | `.session-start` | progress-tracker.js | local-llm metrics | ISO timestamp of session start. Used for LLM metrics correlation. |
|
|
17
|
+
| `activeOperation` | `.active-operation` | context-budget-check.js | context-budget-check.js | Current named operation for budget display. |
|
|
18
|
+
| `activePlan` | `.active-plan` | context-budget-check.js | context-budget-check.js | Current plan ID for budget display. |
|
|
19
|
+
|
|
20
|
+
**Atomic access**: Use `pbr-tools session get|set|clear` for safe reads/writes from hook scripts.
|
|
21
|
+
|
|
22
|
+
**Lifecycle**: Written during SessionStart (progress-tracker), cleared during SessionEnd (session-cleanup).
|
|
23
|
+
Stale sessions (> 60 min) are auto-cleaned by progress-tracker.js on next SessionStart.
|
|
24
|
+
|
|
25
|
+
## One-Shot Files
|
|
26
|
+
|
|
27
|
+
These files are NOT consolidated — they use write-once, delete-on-read semantics.
|
|
28
|
+
|
|
29
|
+
| File | Written By | Read By | Semantics |
|
|
30
|
+
|------|------------|---------|-----------|
|
|
31
|
+
| `.planning/.auto-next` | auto-continue.js | auto-continue.js (Stop hook) | Next command to run after session stops. Deleted after read. |
|
|
32
|
+
| `.planning/.auto-verify` | event-handler.js | event-handler.js (SubagentStop hook) | Trigger auto-verification after agent completes. Deleted after read. |
|
|
33
|
+
|
|
34
|
+
## Phase-Scoped Files
|
|
35
|
+
|
|
36
|
+
These files persist across sessions, scoped to a specific phase or plan.
|
|
37
|
+
|
|
38
|
+
| File Pattern | Written By | Read By | Semantics |
|
|
39
|
+
|-------------|------------|---------|-----------|
|
|
40
|
+
| `.planning/phases/{id}/.checkpoint-manifest.json` | build skill | validate-task.js, session-cleanup.js | Checkpoint state for a plan in progress. Cleaned up after 24h. |
|
|
41
|
+
| `.planning/phases/{id}/.PROGRESS-{taskId}` | executor agent | validate-task.js | Task progress marker for crash recovery. Orphaned files warn on SessionStart. |
|
|
@@ -25,6 +25,7 @@ const fs = require('fs');
|
|
|
25
25
|
const path = require('path');
|
|
26
26
|
const { logHook } = require('./hook-logger');
|
|
27
27
|
const { logEvent } = require('./event-logger');
|
|
28
|
+
const { sessionLoad } = require('./pbr-tools');
|
|
28
29
|
|
|
29
30
|
function main() {
|
|
30
31
|
let input = '';
|
|
@@ -80,15 +81,13 @@ function main() {
|
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
function readActiveSkill(planningDir) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const content = fs.readFileSync(skillFile, 'utf8').trim();
|
|
88
|
-
return content || null;
|
|
89
|
-
} catch (_e) {
|
|
90
|
-
return null;
|
|
84
|
+
// Try .session.json first, fall back to legacy .active-skill
|
|
85
|
+
let activeSkill = sessionLoad(planningDir).activeSkill || null;
|
|
86
|
+
if (!activeSkill) {
|
|
87
|
+
try { activeSkill = fs.readFileSync(path.join(planningDir, '.active-skill'), 'utf8').trim(); } catch (_) { /* legacy file missing */ }
|
|
91
88
|
}
|
|
89
|
+
// TODO(Phase 55+): Remove legacy .active-skill fallback once .session.json is confirmed stable
|
|
90
|
+
return activeSkill || null;
|
|
92
91
|
}
|
|
93
92
|
|
|
94
93
|
/**
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
const fs = require('fs');
|
|
21
21
|
const path = require('path');
|
|
22
22
|
const { logHook } = require('./hook-logger');
|
|
23
|
-
const { KNOWN_AGENTS } = require('./pbr-tools');
|
|
23
|
+
const { KNOWN_AGENTS, sessionLoad } = require('./pbr-tools');
|
|
24
24
|
const { resolveConfig } = require('./local-llm/health');
|
|
25
25
|
const { classifyError } = require('./local-llm/operations/classify-error');
|
|
26
26
|
|
|
@@ -437,11 +437,12 @@ async function main() {
|
|
|
437
437
|
process.exit(0);
|
|
438
438
|
}
|
|
439
439
|
|
|
440
|
-
// Read active skill
|
|
441
|
-
let activeSkill = '';
|
|
442
|
-
|
|
443
|
-
activeSkill = fs.readFileSync(path.join(planningDir, '.active-skill'), 'utf8').trim();
|
|
444
|
-
}
|
|
440
|
+
// Read active skill — try .session.json first, fall back to legacy .active-skill
|
|
441
|
+
let activeSkill = sessionLoad(planningDir).activeSkill || '';
|
|
442
|
+
if (!activeSkill) {
|
|
443
|
+
try { activeSkill = fs.readFileSync(path.join(planningDir, '.active-skill'), 'utf8').trim(); } catch (_) { /* legacy file missing */ }
|
|
444
|
+
}
|
|
445
|
+
// TODO(Phase 55+): Remove legacy .active-skill fallback once .session.json is confirmed stable
|
|
445
446
|
|
|
446
447
|
// Check for expected outputs
|
|
447
448
|
const found = outputSpec.check(planningDir);
|
|
@@ -21,7 +21,7 @@ const fs = require('fs');
|
|
|
21
21
|
const path = require('path');
|
|
22
22
|
const { logHook } = require('./hook-logger');
|
|
23
23
|
const { logEvent } = require('./event-logger');
|
|
24
|
-
const { configLoad, tailLines, lockedFileUpdate } = require('./pbr-tools');
|
|
24
|
+
const { configLoad, tailLines, lockedFileUpdate, sessionLoad } = require('./pbr-tools');
|
|
25
25
|
|
|
26
26
|
function main() {
|
|
27
27
|
const cwd = process.cwd();
|
|
@@ -113,6 +113,12 @@ function main() {
|
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
function readActiveOperation(planningDir) {
|
|
116
|
+
// Try .session.json first (new), fall back to legacy .active-operation file
|
|
117
|
+
try {
|
|
118
|
+
const session = sessionLoad(planningDir);
|
|
119
|
+
if (session.activeOperation) return session.activeOperation;
|
|
120
|
+
} catch (_e) { /* fall through */ }
|
|
121
|
+
|
|
116
122
|
const activeOpFile = path.join(planningDir, '.active-operation');
|
|
117
123
|
if (!fs.existsSync(activeOpFile)) return '';
|
|
118
124
|
try {
|
|
@@ -160,6 +166,12 @@ function readRoadmapSummary(planningDir) {
|
|
|
160
166
|
}
|
|
161
167
|
|
|
162
168
|
function readCurrentPlan(planningDir, stateContent) {
|
|
169
|
+
// Try .session.json first (new), then .active-plan file (legacy)
|
|
170
|
+
try {
|
|
171
|
+
const session = sessionLoad(planningDir);
|
|
172
|
+
if (session.activePlan) return session.activePlan;
|
|
173
|
+
} catch (_e) { /* fall through */ }
|
|
174
|
+
|
|
163
175
|
// Prefer .active-plan signal file (definitive) over directory listing (guesswork)
|
|
164
176
|
const activePlanFile = path.join(planningDir, '.active-plan');
|
|
165
177
|
if (fs.existsSync(activePlanFile)) {
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
const fs = require('fs');
|
|
22
22
|
const path = require('path');
|
|
23
23
|
const { logHook } = require('./hook-logger');
|
|
24
|
+
const { sessionLoad } = require('./pbr-tools');
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* Load the enforcement configuration from .planning/config.json.
|
|
@@ -73,9 +74,13 @@ function checkUnmanagedSourceWrite(data) {
|
|
|
73
74
|
// Skip if not a PBR project
|
|
74
75
|
if (!fs.existsSync(planningDir)) return null;
|
|
75
76
|
|
|
76
|
-
// Skip if a PBR skill is active
|
|
77
|
-
|
|
78
|
-
if (
|
|
77
|
+
// Skip if a PBR skill is active — try .session.json first, fall back to legacy .active-skill
|
|
78
|
+
let activeSkill = sessionLoad(planningDir).activeSkill || '';
|
|
79
|
+
if (!activeSkill) {
|
|
80
|
+
try { activeSkill = fs.readFileSync(path.join(planningDir, '.active-skill'), 'utf8').trim(); } catch (_) { /* legacy file missing */ }
|
|
81
|
+
}
|
|
82
|
+
// TODO(Phase 55+): Remove legacy .active-skill fallback once .session.json is confirmed stable
|
|
83
|
+
if (activeSkill) return null;
|
|
79
84
|
|
|
80
85
|
// Skip if writing inside .planning/
|
|
81
86
|
const normalizedFile = filePath.replace(/\\/g, '/');
|
|
@@ -208,9 +213,13 @@ function checkUnmanagedCommit(data) {
|
|
|
208
213
|
// Skip if not a PBR project
|
|
209
214
|
if (!fs.existsSync(planningDir)) return null;
|
|
210
215
|
|
|
211
|
-
// Skip if a PBR skill is active
|
|
212
|
-
|
|
213
|
-
if (
|
|
216
|
+
// Skip if a PBR skill is active — try .session.json first, fall back to legacy .active-skill
|
|
217
|
+
let activeSkillCommit = sessionLoad(planningDir).activeSkill || '';
|
|
218
|
+
if (!activeSkillCommit) {
|
|
219
|
+
try { activeSkillCommit = fs.readFileSync(path.join(planningDir, '.active-skill'), 'utf8').trim(); } catch (_) { /* legacy file missing */ }
|
|
220
|
+
}
|
|
221
|
+
// TODO(Phase 55+): Remove legacy .active-skill fallback once .session.json is confirmed stable
|
|
222
|
+
if (activeSkillCommit) return null;
|
|
214
223
|
|
|
215
224
|
const config = loadEnforcementConfig(planningDir);
|
|
216
225
|
if (config.level === 'off') return null;
|
|
@@ -450,8 +450,54 @@ function lockedFileUpdate(filePath, updateFn, opts = {}) {
|
|
|
450
450
|
}
|
|
451
451
|
}
|
|
452
452
|
|
|
453
|
+
// --- Session state management (.planning/.session.json) ---
|
|
454
|
+
|
|
455
|
+
const SESSION_ALLOWED_KEYS = ['activeSkill', 'compactCounter', 'sessionStart', 'activeOperation', 'activePlan'];
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Load .session.json from .planning/ directory.
|
|
459
|
+
* Returns parsed object or {} if file is missing or unreadable.
|
|
460
|
+
*
|
|
461
|
+
* @param {string} dir - Path to .planning/ directory
|
|
462
|
+
* @returns {object}
|
|
463
|
+
*/
|
|
464
|
+
function sessionLoad(dir) {
|
|
465
|
+
const sessionPath = path.join(dir, '.session.json');
|
|
466
|
+
try {
|
|
467
|
+
if (!fs.existsSync(sessionPath)) return {};
|
|
468
|
+
const content = fs.readFileSync(sessionPath, 'utf8');
|
|
469
|
+
return JSON.parse(content);
|
|
470
|
+
} catch (_e) {
|
|
471
|
+
return {};
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Save data to .session.json using atomic write (write .tmp, then rename).
|
|
477
|
+
* Merges provided data with existing session data.
|
|
478
|
+
*
|
|
479
|
+
* @param {string} dir - Path to .planning/ directory
|
|
480
|
+
* @param {object} data - Key-value pairs to merge into session
|
|
481
|
+
* @returns {{ success: boolean, error?: string }}
|
|
482
|
+
*/
|
|
483
|
+
function sessionSave(dir, data) {
|
|
484
|
+
const sessionPath = path.join(dir, '.session.json');
|
|
485
|
+
const tmpPath = sessionPath + '.tmp';
|
|
486
|
+
try {
|
|
487
|
+
const existing = sessionLoad(dir);
|
|
488
|
+
const merged = Object.assign(existing, data);
|
|
489
|
+
fs.writeFileSync(tmpPath, JSON.stringify(merged, null, 2), 'utf8');
|
|
490
|
+
fs.renameSync(tmpPath, sessionPath);
|
|
491
|
+
return { success: true };
|
|
492
|
+
} catch (e) {
|
|
493
|
+
try { if (fs.existsSync(tmpPath)) fs.unlinkSync(tmpPath); } catch (_) { /* cleanup */ }
|
|
494
|
+
return { success: false, error: e.message };
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
453
498
|
/**
|
|
454
499
|
* Write .active-skill with OS-level mutual exclusion.
|
|
500
|
+
* Also writes activeSkill to .session.json for consolidated session tracking.
|
|
455
501
|
*
|
|
456
502
|
* @param {string} planningDir - Path to .planning/ directory
|
|
457
503
|
* @param {string} skillName - Skill name to write
|
|
@@ -485,9 +531,12 @@ function writeActiveSkill(planningDir, skillName) {
|
|
|
485
531
|
}
|
|
486
532
|
}
|
|
487
533
|
|
|
488
|
-
// Write the skill name
|
|
534
|
+
// Write the skill name (legacy file — kept for backward compat with reader scripts)
|
|
489
535
|
fs.writeFileSync(skillFile, skillName, 'utf8');
|
|
490
536
|
|
|
537
|
+
// Also write to .session.json for consolidated session tracking
|
|
538
|
+
try { sessionSave(planningDir, { activeSkill: skillName }); } catch (_e) { /* non-fatal */ }
|
|
539
|
+
|
|
491
540
|
// Release lock
|
|
492
541
|
try { fs.unlinkSync(lockFile); } catch (_e) { /* best effort */ }
|
|
493
542
|
|
|
@@ -585,5 +634,8 @@ module.exports = {
|
|
|
585
634
|
atomicWrite,
|
|
586
635
|
lockedFileUpdate,
|
|
587
636
|
writeActiveSkill,
|
|
637
|
+
sessionLoad,
|
|
638
|
+
sessionSave,
|
|
639
|
+
SESSION_ALLOWED_KEYS,
|
|
588
640
|
validateObject
|
|
589
641
|
};
|
|
@@ -17,7 +17,7 @@ const fs = require('fs');
|
|
|
17
17
|
const path = require('path');
|
|
18
18
|
const { logHook } = require('./hook-logger');
|
|
19
19
|
const { logEvent } = require('./event-logger');
|
|
20
|
-
const { configLoad } = require('./pbr-tools');
|
|
20
|
+
const { configLoad, sessionLoad } = require('./pbr-tools');
|
|
21
21
|
|
|
22
22
|
function readStdin() {
|
|
23
23
|
try {
|
|
@@ -136,16 +136,13 @@ function buildAgentContext() {
|
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
// Active skill context
|
|
140
|
-
|
|
141
|
-
if (
|
|
142
|
-
try {
|
|
143
|
-
const skill = fs.readFileSync(activeSkillFile, 'utf8').trim();
|
|
144
|
-
if (skill) parts.push(`Active skill: /pbr:${skill}`);
|
|
145
|
-
} catch (_e) {
|
|
146
|
-
// skip
|
|
147
|
-
}
|
|
139
|
+
// Active skill context — try .session.json first, fall back to legacy .active-skill
|
|
140
|
+
let activeSkill = sessionLoad(planningDir).activeSkill || '';
|
|
141
|
+
if (!activeSkill) {
|
|
142
|
+
try { activeSkill = fs.readFileSync(path.join(planningDir, '.active-skill'), 'utf8').trim(); } catch (_) { /* legacy file missing */ }
|
|
148
143
|
}
|
|
144
|
+
// TODO(Phase 55+): Remove legacy .active-skill fallback once .session.json is confirmed stable
|
|
145
|
+
if (activeSkill) parts.push(`Active skill: /pbr:${activeSkill}`);
|
|
149
146
|
|
|
150
147
|
// Config highlights
|
|
151
148
|
const config = configLoad(planningDir);
|
|
@@ -46,6 +46,10 @@
|
|
|
46
46
|
* checkpoint init <phase-slug> [--plans "id1,id2"] — Initialize checkpoint manifest
|
|
47
47
|
* checkpoint update <phase-slug> --wave N --resolved id [--sha hash] — Update manifest
|
|
48
48
|
* seeds match <phase-slug> <phase-number> — Find matching seed files for a phase
|
|
49
|
+
* session get <key> — Read a key from .planning/.session.json
|
|
50
|
+
* session set <key> <value> — Write a key to .planning/.session.json
|
|
51
|
+
* session clear [key] — Delete .session.json or set key to null
|
|
52
|
+
* session dump — Print entire .session.json content
|
|
49
53
|
*
|
|
50
54
|
* Environment: PBR_PROJECT_ROOT — Override project root directory (used when hooks fire from subagent cwd)
|
|
51
55
|
*/
|
|
@@ -68,7 +72,10 @@ const {
|
|
|
68
72
|
determinePhaseStatus,
|
|
69
73
|
atomicWrite,
|
|
70
74
|
lockedFileUpdate,
|
|
71
|
-
writeActiveSkill
|
|
75
|
+
writeActiveSkill,
|
|
76
|
+
sessionLoad,
|
|
77
|
+
sessionSave,
|
|
78
|
+
SESSION_ALLOWED_KEYS
|
|
72
79
|
} = require('./lib/core');
|
|
73
80
|
|
|
74
81
|
const {
|
|
@@ -833,6 +840,45 @@ async function main() {
|
|
|
833
840
|
const manifestPath = args[1];
|
|
834
841
|
if (!manifestPath) { error('Usage: pbr-tools.js rollback <manifest-path>'); return; }
|
|
835
842
|
output(rollbackPlan(manifestPath));
|
|
843
|
+
} else if (command === 'session') {
|
|
844
|
+
const sub = args[1];
|
|
845
|
+
const key = args[2];
|
|
846
|
+
const value = args[3];
|
|
847
|
+
const dir = planningDir;
|
|
848
|
+
if (sub === 'get') {
|
|
849
|
+
if (!key) { error('Usage: pbr-tools.js session get <key>'); return; }
|
|
850
|
+
if (!SESSION_ALLOWED_KEYS.includes(key)) { error(`Unknown session key: ${key}. Allowed: ${SESSION_ALLOWED_KEYS.join(', ')}`); return; }
|
|
851
|
+
const data = sessionLoad(dir);
|
|
852
|
+
const val = Object.prototype.hasOwnProperty.call(data, key) ? data[key] : null;
|
|
853
|
+
output({ key, value: val });
|
|
854
|
+
} else if (sub === 'set') {
|
|
855
|
+
if (!key || value === undefined) { error('Usage: pbr-tools.js session set <key> <value>'); return; }
|
|
856
|
+
if (!SESSION_ALLOWED_KEYS.includes(key)) { error(`Unknown session key: ${key}. Allowed: ${SESSION_ALLOWED_KEYS.join(', ')}`); return; }
|
|
857
|
+
// Coerce numeric strings
|
|
858
|
+
let coerced = value;
|
|
859
|
+
if (/^\d+$/.test(value)) coerced = parseInt(value, 10);
|
|
860
|
+
else if (value === 'null') coerced = null;
|
|
861
|
+
const result = sessionSave(dir, { [key]: coerced });
|
|
862
|
+
if (!result.success) { error(result.error || 'Failed to save session'); return; }
|
|
863
|
+
output({ ok: true });
|
|
864
|
+
} else if (sub === 'clear') {
|
|
865
|
+
const sessionPath = path.join(dir, '.session.json');
|
|
866
|
+
if (key) {
|
|
867
|
+
// Clear a specific key — set to null
|
|
868
|
+
if (!SESSION_ALLOWED_KEYS.includes(key)) { error(`Unknown session key: ${key}. Allowed: ${SESSION_ALLOWED_KEYS.join(', ')}`); return; }
|
|
869
|
+
const result = sessionSave(dir, { [key]: null });
|
|
870
|
+
if (!result.success) { error(result.error || 'Failed to clear session key'); return; }
|
|
871
|
+
} else {
|
|
872
|
+
// Clear entire session file
|
|
873
|
+
try { if (fs.existsSync(sessionPath)) fs.unlinkSync(sessionPath); } catch (e) { error(e.message); return; }
|
|
874
|
+
}
|
|
875
|
+
output({ ok: true });
|
|
876
|
+
} else if (sub === 'dump') {
|
|
877
|
+
const data = sessionLoad(dir);
|
|
878
|
+
output(data);
|
|
879
|
+
} else {
|
|
880
|
+
error('Usage: pbr-tools.js session get|set|clear|dump <key> [value]');
|
|
881
|
+
}
|
|
836
882
|
} else if (command === 'context-triage') {
|
|
837
883
|
const options = {};
|
|
838
884
|
const agentsIdx = args.indexOf('--agents-done');
|
|
@@ -856,7 +902,7 @@ async function main() {
|
|
|
856
902
|
} else if (command === 'validate-project') {
|
|
857
903
|
output(validateProject());
|
|
858
904
|
} else {
|
|
859
|
-
error(`Unknown command: ${args.join(' ')}\nCommands: state load|check-progress|update|patch|advance-plan|record-metric, config validate|load-defaults|save-defaults|resolve-depth, validate-project, migrate [--dry-run] [--force], init execute-phase|plan-phase|quick|verify-work|resume|progress, state-bundle <phase>, plan-index, frontmatter, must-haves, phase-info, phase add|remove|list, roadmap update-status|update-plans, history append|load, todo list|get|add|done, event, llm health|status|classify|score-source|classify-error|summarize|metrics [--session <ISO>]|adjust-thresholds, learnings ingest|query|check-thresholds, milestone-stats <version>, context-triage [--agents-done N] [--plans-total N] [--step NAME], ci-poll <run-id> [--timeout <seconds>], rollback <manifest-path
|
|
905
|
+
error(`Unknown command: ${args.join(' ')}\nCommands: state load|check-progress|update|patch|advance-plan|record-metric, config validate|load-defaults|save-defaults|resolve-depth, validate-project, migrate [--dry-run] [--force], init execute-phase|plan-phase|quick|verify-work|resume|progress, state-bundle <phase>, plan-index, frontmatter, must-haves, phase-info, phase add|remove|list, roadmap update-status|update-plans, history append|load, todo list|get|add|done, event, llm health|status|classify|score-source|classify-error|summarize|metrics [--session <ISO>]|adjust-thresholds, learnings ingest|query|check-thresholds, milestone-stats <version>, context-triage [--agents-done N] [--plans-total N] [--step NAME], ci-poll <run-id> [--timeout <seconds>], rollback <manifest-path>, session get|set|clear|dump`);
|
|
860
906
|
}
|
|
861
907
|
} catch (e) {
|
|
862
908
|
error(e.message);
|
|
@@ -864,6 +910,6 @@ async function main() {
|
|
|
864
910
|
}
|
|
865
911
|
|
|
866
912
|
if (require.main === module || process.argv[1] === __filename) { main().catch(err => { process.stderr.write(err.message + '\n'); process.exit(1); }); }
|
|
867
|
-
module.exports = { KNOWN_AGENTS, initExecutePhase, initPlanPhase, initQuick, initVerifyWork, initResume, initProgress, initStateBundle: stateBundle, stateBundle, statePatch, stateAdvancePlan, stateRecordMetric, parseStateMd, parseRoadmapMd, parseYamlFrontmatter, parseMustHaves, countMustHaves, stateLoad, stateCheckProgress, configLoad, configClearCache, configValidate, lockedFileUpdate, planIndex, determinePhaseStatus, findFiles, atomicWrite, tailLines, frontmatter, mustHavesCollect, phaseInfo, stateUpdate, roadmapUpdateStatus, roadmapUpdatePlans, updateLegacyStateField, updateFrontmatterField, updateTableRow, findRoadmapRow, resolveDepthProfile, DEPTH_PROFILE_DEFAULTS, historyAppend, historyLoad, VALID_STATUS_TRANSITIONS, validateStatusTransition, writeActiveSkill, validateProject, phaseAdd, phaseRemove, phaseList, loadUserDefaults, saveUserDefaults, mergeUserDefaults, USER_DEFAULTS_PATH, todoList, todoGet, todoAdd, todoDone, migrate, spotCheck, referenceGet, milestoneStats, contextTriage, stalenessCheck, summaryGate, checkpointInit, checkpointUpdate, seedsMatch, ciPoll, rollbackPlan };
|
|
913
|
+
module.exports = { KNOWN_AGENTS, initExecutePhase, initPlanPhase, initQuick, initVerifyWork, initResume, initProgress, initStateBundle: stateBundle, stateBundle, statePatch, stateAdvancePlan, stateRecordMetric, parseStateMd, parseRoadmapMd, parseYamlFrontmatter, parseMustHaves, countMustHaves, stateLoad, stateCheckProgress, configLoad, configClearCache, configValidate, lockedFileUpdate, planIndex, determinePhaseStatus, findFiles, atomicWrite, tailLines, frontmatter, mustHavesCollect, phaseInfo, stateUpdate, roadmapUpdateStatus, roadmapUpdatePlans, updateLegacyStateField, updateFrontmatterField, updateTableRow, findRoadmapRow, resolveDepthProfile, DEPTH_PROFILE_DEFAULTS, historyAppend, historyLoad, VALID_STATUS_TRANSITIONS, validateStatusTransition, writeActiveSkill, validateProject, phaseAdd, phaseRemove, phaseList, loadUserDefaults, saveUserDefaults, mergeUserDefaults, USER_DEFAULTS_PATH, todoList, todoGet, todoAdd, todoDone, migrate, spotCheck, referenceGet, milestoneStats, contextTriage, stalenessCheck, summaryGate, checkpointInit, checkpointUpdate, seedsMatch, ciPoll, rollbackPlan, sessionLoad, sessionSave, SESSION_ALLOWED_KEYS };
|
|
868
914
|
// NOTE: validateProject, phaseAdd, phaseRemove, phaseList were previously CLI-only (not exported).
|
|
869
915
|
// They are now exported for testability. This is additive and backwards-compatible.
|
|
@@ -14,7 +14,7 @@ const os = require('os');
|
|
|
14
14
|
const { execSync } = require('child_process');
|
|
15
15
|
const { logHook } = require('./hook-logger');
|
|
16
16
|
const { logEvent } = require('./event-logger');
|
|
17
|
-
const { configLoad } = require('./pbr-tools');
|
|
17
|
+
const { configLoad, sessionSave } = require('./pbr-tools');
|
|
18
18
|
const { resolveConfig, checkHealth, warmUp } = require('./local-llm/health');
|
|
19
19
|
|
|
20
20
|
async function main() {
|
|
@@ -40,9 +40,13 @@ async function main() {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
// Write session-start timestamp for local-llm metrics correlation
|
|
43
|
+
// Primary: write to .session.json (unified session state)
|
|
44
|
+
// Legacy: also write .session-start file for session-cleanup.js backward compat
|
|
45
|
+
const sessionStart = new Date().toISOString();
|
|
46
|
+
try { sessionSave(planningDir, { sessionStart }); } catch (_e) { /* non-fatal */ }
|
|
43
47
|
const sessionStartFile = path.join(planningDir, '.session-start');
|
|
44
48
|
try {
|
|
45
|
-
fs.writeFileSync(sessionStartFile,
|
|
49
|
+
fs.writeFileSync(sessionStartFile, sessionStart, 'utf8');
|
|
46
50
|
} catch (_e) { /* non-fatal */ }
|
|
47
51
|
|
|
48
52
|
// Local LLM health check (advisory only — never blocks SessionStart)
|
|
@@ -217,14 +221,20 @@ function buildContext(planningDir, stateFile) {
|
|
|
217
221
|
}
|
|
218
222
|
|
|
219
223
|
// Check for stale .active-skill (multi-session conflict detection)
|
|
224
|
+
// Try .session.json first (new), fall back to .active-skill file (legacy)
|
|
220
225
|
const activeSkillFile = path.join(planningDir, '.active-skill');
|
|
226
|
+
const { sessionLoad: _sessionLoad } = require('./pbr-tools');
|
|
227
|
+
const sessionData = _sessionLoad(planningDir);
|
|
228
|
+
const sessionActiveSkill = sessionData.activeSkill || null;
|
|
229
|
+
|
|
221
230
|
if (fs.existsSync(activeSkillFile)) {
|
|
222
231
|
try {
|
|
223
232
|
const stats = fs.statSync(activeSkillFile);
|
|
224
233
|
const ageMs = Date.now() - stats.mtimeMs;
|
|
225
234
|
const ageMinutes = Math.floor(ageMs / 60000);
|
|
226
235
|
if (ageMinutes > 60) {
|
|
227
|
-
|
|
236
|
+
// Prefer skill name from .session.json if available
|
|
237
|
+
const skill = sessionActiveSkill || fs.readFileSync(activeSkillFile, 'utf8').trim();
|
|
228
238
|
// Auto-cleanup stale .active-skill lock (> 60 minutes = certainly stale)
|
|
229
239
|
try {
|
|
230
240
|
fs.unlinkSync(activeSkillFile);
|
|
@@ -216,6 +216,12 @@ function main() {
|
|
|
216
216
|
// NOTE: .auto-next is intentionally NOT cleaned here — it is a one-shot
|
|
217
217
|
// signal consumed by auto-continue.js (Stop hook). SessionEnd cleanup
|
|
218
218
|
// races with the Stop hook and would delete the signal before it is read.
|
|
219
|
+
|
|
220
|
+
// Primary: remove .session.json (consolidated session state)
|
|
221
|
+
if (tryRemove(path.join(planningDir, '.session.json'))) {
|
|
222
|
+
cleaned.push('.session.json');
|
|
223
|
+
}
|
|
224
|
+
// Legacy fallback: also clean individual signal files during transition period
|
|
219
225
|
if (tryRemove(path.join(planningDir, '.active-operation'))) {
|
|
220
226
|
cleaned.push('.active-operation');
|
|
221
227
|
}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
const fs = require('fs');
|
|
21
21
|
const path = require('path');
|
|
22
22
|
const { logHook } = require('./hook-logger');
|
|
23
|
-
const { configLoad } = require('./pbr-tools');
|
|
23
|
+
const { configLoad, sessionSave } = require('./pbr-tools');
|
|
24
24
|
const { loadBridge, TIER_MESSAGES } = require('./context-bridge');
|
|
25
25
|
|
|
26
26
|
const DEFAULT_THRESHOLD = 50;
|
|
@@ -155,6 +155,12 @@ function saveCounter(counterPath, counter) {
|
|
|
155
155
|
} catch (_e) {
|
|
156
156
|
// Best-effort
|
|
157
157
|
}
|
|
158
|
+
// Mirror to .session.json for consolidated session state tracking
|
|
159
|
+
// Derive planningDir from counterPath (counterPath is planningDir/.compact-counter)
|
|
160
|
+
try {
|
|
161
|
+
const planningDir = path.dirname(counterPath);
|
|
162
|
+
sessionSave(planningDir, { compactCounter: counter });
|
|
163
|
+
} catch (_e) { /* non-fatal mirror */ }
|
|
158
164
|
}
|
|
159
165
|
|
|
160
166
|
function getThreshold(cwd) {
|
|
@@ -165,6 +171,12 @@ function getThreshold(cwd) {
|
|
|
165
171
|
}
|
|
166
172
|
|
|
167
173
|
function resetCounter(planningDir) {
|
|
174
|
+
// Primary: reset compactCounter in .session.json to 0
|
|
175
|
+
try {
|
|
176
|
+
sessionSave(planningDir, { compactCounter: { count: 0, lastSuggested: 0 } });
|
|
177
|
+
} catch (_e) { /* best-effort */ }
|
|
178
|
+
|
|
179
|
+
// Legacy: also delete .compact-counter file if present
|
|
168
180
|
const counterPath = path.join(planningDir, '.compact-counter');
|
|
169
181
|
try {
|
|
170
182
|
if (fs.existsSync(counterPath)) {
|
|
@@ -168,7 +168,7 @@ Use the **yes-no** pattern from `skills/shared/gate-prompts.md`:
|
|
|
168
168
|
|
|
169
169
|
**After gathering preferences:**
|
|
170
170
|
|
|
171
|
-
**CRITICAL: You MUST create the .planning/ directory and write config.json NOW. Do not proceed without this.**
|
|
171
|
+
**CRITICAL (no hook): You MUST create the .planning/ directory and write config.json NOW. Do not proceed without this.**
|
|
172
172
|
|
|
173
173
|
1. Read the config template from `skills/begin/templates/config.json.tmpl`
|
|
174
174
|
2. Apply the user's choices to the template
|
|
@@ -177,7 +177,7 @@ Use the **yes-no** pattern from `skills/shared/gate-prompts.md`:
|
|
|
177
177
|
|
|
178
178
|
**IMPORTANT**: This step MUST happen BEFORE research (Step 5) because depth controls how many researchers to spawn.
|
|
179
179
|
|
|
180
|
-
**CRITICAL: Write .active-skill NOW.** Write the text "begin" to `.planning/.active-skill` using the Write tool. Verify the file exists before proceeding.
|
|
180
|
+
**CRITICAL (hook-enforced): Write .active-skill NOW.** Write the text "begin" to `.planning/.active-skill` using the Write tool. Verify the file exists before proceeding.
|
|
181
181
|
|
|
182
182
|
---
|
|
183
183
|
|
|
@@ -213,7 +213,7 @@ Use the **yes-no** pattern from `skills/shared/gate-prompts.md`:
|
|
|
213
213
|
|
|
214
214
|
Spawn parallel Task() subagents for research. Each researcher writes to `.planning/research/`.
|
|
215
215
|
|
|
216
|
-
**CRITICAL: Create .planning/research/ directory NOW before spawning researchers. Do NOT skip this step.**
|
|
216
|
+
**CRITICAL (no hook): Create .planning/research/ directory NOW before spawning researchers. Do NOT skip this step.**
|
|
217
217
|
|
|
218
218
|
**Learnings injection (opt-in):** Before spawning researchers, check if global learnings exist:
|
|
219
219
|
|
|
@@ -258,7 +258,7 @@ Read `skills/begin/templates/researcher-prompt.md.tmpl` for the prompt structure
|
|
|
258
258
|
|
|
259
259
|
```
|
|
260
260
|
<files_to_read>
|
|
261
|
-
CRITICAL: Read these files BEFORE any other action:
|
|
261
|
+
CRITICAL (no hook): Read these files BEFORE any other action:
|
|
262
262
|
1. .planning/REQUIREMENTS.md — scoped requirements (if exists)
|
|
263
263
|
{if learnings_temp_path exists}2. {learnings_temp_path} — cross-project learnings (tech stack patterns from past PBR projects){/if}
|
|
264
264
|
</files_to_read>
|
|
@@ -338,7 +338,7 @@ Read `skills/begin/templates/synthesis-prompt.md.tmpl` for the prompt structure.
|
|
|
338
338
|
**Prepend this block to the synthesizer prompt before sending:**
|
|
339
339
|
```
|
|
340
340
|
<files_to_read>
|
|
341
|
-
CRITICAL: Read these files BEFORE any other action:
|
|
341
|
+
CRITICAL (no hook): Read these files BEFORE any other action:
|
|
342
342
|
1. .planning/research/*.md — all research output files from Step 5
|
|
343
343
|
</files_to_read>
|
|
344
344
|
```
|
|
@@ -406,7 +406,7 @@ Each requirement must be:
|
|
|
406
406
|
|
|
407
407
|
**7e. Write REQUIREMENTS.md:**
|
|
408
408
|
|
|
409
|
-
**CRITICAL: Write REQUIREMENTS.md NOW. The roadmap planner depends on this file.**
|
|
409
|
+
**CRITICAL (no hook): Write REQUIREMENTS.md NOW. The roadmap planner depends on this file.**
|
|
410
410
|
|
|
411
411
|
Read the template from `skills/begin/templates/REQUIREMENTS.md.tmpl` and write `.planning/REQUIREMENTS.md` with:
|
|
412
412
|
- All v1 requirements grouped by category
|
|
@@ -441,7 +441,7 @@ Read `skills/begin/templates/roadmap-prompt.md.tmpl` for the prompt structure.
|
|
|
441
441
|
**Prepend this block to the roadmap planner prompt before sending:**
|
|
442
442
|
```
|
|
443
443
|
<files_to_read>
|
|
444
|
-
CRITICAL: Read these files BEFORE any other action:
|
|
444
|
+
CRITICAL (no hook): Read these files BEFORE any other action:
|
|
445
445
|
1. .planning/REQUIREMENTS.md — scoped requirements for phase planning
|
|
446
446
|
2. .planning/research/SUMMARY.md — research synthesis (if exists)
|
|
447
447
|
</files_to_read>
|
|
@@ -477,9 +477,9 @@ CRITICAL: Read these files BEFORE any other action:
|
|
|
477
477
|
|
|
478
478
|
Write the project state files from templates:
|
|
479
479
|
|
|
480
|
-
**CRITICAL: You MUST write all 5 state initialization files (Steps 9a-9e). Do NOT skip any.**
|
|
480
|
+
**CRITICAL (no hook): You MUST write all 5 state initialization files (Steps 9a-9e). Do NOT skip any.**
|
|
481
481
|
|
|
482
|
-
**CRITICAL: Write PROJECT.md NOW. Do NOT skip this step.**
|
|
482
|
+
**CRITICAL (no hook): Write PROJECT.md NOW. Do NOT skip this step.**
|
|
483
483
|
|
|
484
484
|
**9a. Write PROJECT.md:**
|
|
485
485
|
1. Read `skills/begin/templates/PROJECT.md.tmpl`
|
|
@@ -493,7 +493,7 @@ Write the project state files from templates:
|
|
|
493
493
|
3. Write to `.planning/PROJECT.md`
|
|
494
494
|
4. Ensure the `## Milestones` section is filled in with the project name and phase count from the roadmap
|
|
495
495
|
|
|
496
|
-
**CRITICAL: Write STATE.md NOW. Do NOT skip this step.**
|
|
496
|
+
**CRITICAL (no hook): Write STATE.md NOW. Do NOT skip this step.**
|
|
497
497
|
|
|
498
498
|
**9b. Write STATE.md:**
|
|
499
499
|
1. Read `skills/begin/templates/STATE.md.tmpl`
|
|
@@ -507,7 +507,7 @@ Write the project state files from templates:
|
|
|
507
507
|
4. Fill in the `## Milestone` section with the project name and total phase count
|
|
508
508
|
5. **STATE.md size limit**: Follow size limit enforcement rules in `skills/shared/state-update.md` (150 lines max).
|
|
509
509
|
|
|
510
|
-
**CRITICAL: Write CONTEXT.md NOW. Do NOT skip this step.**
|
|
510
|
+
**CRITICAL (no hook): Write CONTEXT.md NOW. Do NOT skip this step.**
|
|
511
511
|
|
|
512
512
|
**9c. Write CONTEXT.md:**
|
|
513
513
|
Create `.planning/CONTEXT.md` from information gathered during questioning:
|
|
@@ -533,7 +533,7 @@ Create `.planning/CONTEXT.md` from information gathered during questioning:
|
|
|
533
533
|
| {feature} | {reason} |
|
|
534
534
|
```
|
|
535
535
|
|
|
536
|
-
**CRITICAL: Write HISTORY.md NOW. Do NOT skip this step.**
|
|
536
|
+
**CRITICAL (no hook): Write HISTORY.md NOW. Do NOT skip this step.**
|
|
537
537
|
|
|
538
538
|
**9d. Write HISTORY.md:**
|
|
539
539
|
Create `.planning/HISTORY.md` with an initial entry:
|
|
@@ -548,7 +548,7 @@ Create `.planning/HISTORY.md` with an initial entry:
|
|
|
548
548
|
- Roadmap: {N} phases planned
|
|
549
549
|
```
|
|
550
550
|
|
|
551
|
-
**CRITICAL: Create phase directories NOW. Do NOT skip this step.**
|
|
551
|
+
**CRITICAL (no hook): Create phase directories NOW. Do NOT skip this step.**
|
|
552
552
|
|
|
553
553
|
**9e. Create phase directories:**
|
|
554
554
|
For each phase in the roadmap, create the directory structure:
|