@sienklogic/plan-build-run 2.23.0 → 2.24.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 +15 -0
- package/dashboard/package.json +1 -1
- package/dashboard/src/repositories/planning.repository.js +1 -11
- package/dashboard/src/routes/pages.routes.js +117 -2
- package/dashboard/src/server.js +4 -0
- package/dashboard/src/services/audit.service.js +42 -0
- package/dashboard/src/services/dashboard.service.js +1 -12
- package/dashboard/src/services/roadmap.service.js +1 -11
- package/dashboard/src/utils/strip-bom.js +8 -0
- package/dashboard/src/views/audit-detail.ejs +5 -0
- package/dashboard/src/views/audits.ejs +5 -0
- package/dashboard/src/views/partials/audit-detail-content.ejs +12 -0
- package/dashboard/src/views/partials/audits-content.ejs +34 -0
- package/dashboard/src/views/partials/sidebar.ejs +8 -0
- package/dashboard/src/views/partials/todos-content.ejs +13 -3
- package/package.json +1 -1
- package/plugins/copilot-pbr/agents/integration-checker.agent.md +9 -2
- package/plugins/copilot-pbr/agents/planner.agent.md +19 -0
- package/plugins/copilot-pbr/agents/verifier.agent.md +22 -2
- package/plugins/copilot-pbr/plugin.json +1 -1
- package/plugins/copilot-pbr/references/plan-format.md +22 -0
- package/plugins/copilot-pbr/templates/INTEGRATION-REPORT.md.tmpl +18 -2
- package/plugins/copilot-pbr/templates/VERIFICATION-DETAIL.md.tmpl +2 -1
- package/plugins/cursor-pbr/.cursor-plugin/plugin.json +1 -1
- package/plugins/cursor-pbr/agents/integration-checker.md +9 -2
- package/plugins/cursor-pbr/agents/planner.md +19 -0
- package/plugins/cursor-pbr/agents/verifier.md +22 -2
- package/plugins/cursor-pbr/references/plan-format.md +22 -0
- package/plugins/cursor-pbr/templates/INTEGRATION-REPORT.md.tmpl +18 -2
- package/plugins/cursor-pbr/templates/VERIFICATION-DETAIL.md.tmpl +2 -1
- package/plugins/pbr/.claude-plugin/plugin.json +1 -1
- package/plugins/pbr/agents/integration-checker.md +9 -2
- package/plugins/pbr/agents/planner.md +19 -0
- package/plugins/pbr/agents/verifier.md +22 -2
- package/plugins/pbr/references/plan-format.md +22 -0
- package/plugins/pbr/scripts/check-plan-format.js +2 -2
- package/plugins/pbr/scripts/check-subagent-output.js +2 -2
- package/plugins/pbr/scripts/validate-task.js +1 -1
- package/plugins/pbr/templates/INTEGRATION-REPORT.md.tmpl +18 -2
- package/plugins/pbr/templates/VERIFICATION-DETAIL.md.tmpl +2 -1
- package/dashboard/src/views/coming-soon.ejs +0 -11
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,21 @@ All notable changes to Plan-Build-Run will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.24.0](https://github.com/SienkLogic/plan-build-run/compare/plan-build-run-v2.23.0...plan-build-run-v2.24.0) (2026-02-24)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **35-05:** add Audit Reports view with /audits and /audits/:filename routes ([33dfae7](https://github.com/SienkLogic/plan-build-run/commit/33dfae7fff02cbba93e250211e54b26d565f4f76))
|
|
14
|
+
* **35-05:** GREEN - implement audit.service.js with listAuditReports and getAuditReport ([c79179a](https://github.com/SienkLogic/plan-build-run/commit/c79179a75a386096e74589f13fea4a56174b1870))
|
|
15
|
+
* **quick-003:** add data-flow to plan-format reference, verification template, and integration report template ([e73a31e](https://github.com/SienkLogic/plan-build-run/commit/e73a31e0c1eb9535014de4b60924bd98ced2f8cb))
|
|
16
|
+
* **quick-003:** add data-flow verification to planner, verifier, and integration-checker agents ([e37e192](https://github.com/SienkLogic/plan-build-run/commit/e37e19297e038c38aecd7d04e93c007928242f0f))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
* **quick-003:** pass data.session_id to LLM operations instead of undefined ([df4d168](https://github.com/SienkLogic/plan-build-run/commit/df4d1682b50935b53ddcc665b8dcdc394b8b277e))
|
|
22
|
+
|
|
8
23
|
## [2.23.0](https://github.com/SienkLogic/plan-build-run/compare/plan-build-run-v2.22.2...plan-build-run-v2.23.0) (2026-02-24)
|
|
9
24
|
|
|
10
25
|
|
package/dashboard/package.json
CHANGED
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
],
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@rollup/rollup-win32-x64-msvc": "^4.57.1",
|
|
23
22
|
"chokidar": "^5.0.0",
|
|
24
23
|
"commander": "^12.1.0",
|
|
25
24
|
"ejs": "^3.1.10",
|
|
@@ -30,6 +29,7 @@
|
|
|
30
29
|
"sanitize-html": "^2.13.0"
|
|
31
30
|
},
|
|
32
31
|
"devDependencies": {
|
|
32
|
+
"@rollup/rollup-win32-x64-msvc": "^4.57.1",
|
|
33
33
|
"@vitest/coverage-v8": "^4.0.18",
|
|
34
34
|
"memfs": "^4.56.10",
|
|
35
35
|
"supertest": "^7.2.2",
|
|
@@ -3,20 +3,10 @@ import { join, resolve, relative, normalize } from 'node:path';
|
|
|
3
3
|
import matter from 'gray-matter';
|
|
4
4
|
import { marked } from 'marked';
|
|
5
5
|
import sanitizeHtml from 'sanitize-html';
|
|
6
|
+
import { stripBOM } from '../utils/strip-bom.js';
|
|
6
7
|
|
|
7
8
|
marked.setOptions({ gfm: true, breaks: false });
|
|
8
9
|
|
|
9
|
-
/**
|
|
10
|
-
* Strip UTF-8 BOM (Byte Order Mark) if present.
|
|
11
|
-
* Windows editors (Notepad, older VS Code) may prepend BOM to UTF-8 files.
|
|
12
|
-
* gray-matter will fail to detect frontmatter delimiters if BOM is present.
|
|
13
|
-
* @param {string} content - Raw file content
|
|
14
|
-
* @returns {string} Content without BOM
|
|
15
|
-
*/
|
|
16
|
-
function stripBOM(content) {
|
|
17
|
-
return content.replace(/^\uFEFF/, '');
|
|
18
|
-
}
|
|
19
|
-
|
|
20
10
|
/**
|
|
21
11
|
* Validate that a resolved path stays within the base directory.
|
|
22
12
|
* Prevents path traversal attacks (e.g., ../../etc/passwd).
|
|
@@ -2,12 +2,13 @@ import { Router } from 'express';
|
|
|
2
2
|
import { getPhaseDetail, getPhaseDocument } from '../services/phase.service.js';
|
|
3
3
|
import { getRoadmapData, generateDependencyMermaid } from '../services/roadmap.service.js';
|
|
4
4
|
import { parseStateFile, derivePhaseStatuses } from '../services/dashboard.service.js';
|
|
5
|
-
import { listPendingTodos, getTodoDetail, createTodo, completeTodo } from '../services/todo.service.js';
|
|
5
|
+
import { listPendingTodos, getTodoDetail, createTodo, completeTodo, listDoneTodos } from '../services/todo.service.js';
|
|
6
6
|
import { getAllMilestones, getMilestoneDetail } from '../services/milestone.service.js';
|
|
7
7
|
import { getProjectAnalytics } from '../services/analytics.service.js';
|
|
8
8
|
import { getLlmMetrics } from '../services/local-llm-metrics.service.js';
|
|
9
|
-
import { listNotes } from '../services/notes.service.js';
|
|
9
|
+
import { listNotes, getNoteBySlug } from '../services/notes.service.js';
|
|
10
10
|
import { listQuickTasks, getQuickTask } from '../services/quick.service.js';
|
|
11
|
+
import { listAuditReports, getAuditReport } from '../services/audit.service.js';
|
|
11
12
|
|
|
12
13
|
const router = Router();
|
|
13
14
|
|
|
@@ -190,6 +191,27 @@ router.get('/todos/new', (req, res) => {
|
|
|
190
191
|
}
|
|
191
192
|
});
|
|
192
193
|
|
|
194
|
+
router.get('/todos/done', async (req, res) => {
|
|
195
|
+
const projectDir = req.app.locals.projectDir;
|
|
196
|
+
const todos = await listDoneTodos(projectDir);
|
|
197
|
+
|
|
198
|
+
const templateData = {
|
|
199
|
+
title: 'Completed Todos',
|
|
200
|
+
activePage: 'todos',
|
|
201
|
+
currentPath: '/todos/done',
|
|
202
|
+
breadcrumbs: [{ label: 'Todos', url: '/todos' }, { label: 'Completed' }],
|
|
203
|
+
todos
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
res.setHeader('Vary', 'HX-Request');
|
|
207
|
+
|
|
208
|
+
if (req.get('HX-Request') === 'true') {
|
|
209
|
+
res.render('partials/todos-done-content', templateData);
|
|
210
|
+
} else {
|
|
211
|
+
res.render('todos-done', templateData);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
|
|
193
215
|
router.get('/todos/:id', async (req, res) => {
|
|
194
216
|
const { id } = req.params;
|
|
195
217
|
|
|
@@ -404,6 +426,42 @@ router.get('/notes', async (req, res) => {
|
|
|
404
426
|
}
|
|
405
427
|
});
|
|
406
428
|
|
|
429
|
+
router.get('/notes/:slug', async (req, res) => {
|
|
430
|
+
const { slug } = req.params;
|
|
431
|
+
|
|
432
|
+
// Validate slug: lowercase alphanumeric and dashes only
|
|
433
|
+
if (!/^[a-z0-9-]+$/.test(slug)) {
|
|
434
|
+
const err = new Error('Invalid note slug format');
|
|
435
|
+
err.status = 404;
|
|
436
|
+
throw err;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const projectDir = req.app.locals.projectDir;
|
|
440
|
+
const note = await getNoteBySlug(projectDir, slug);
|
|
441
|
+
|
|
442
|
+
if (!note) {
|
|
443
|
+
const err = new Error(`Note "${slug}" not found`);
|
|
444
|
+
err.status = 404;
|
|
445
|
+
throw err;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const templateData = {
|
|
449
|
+
title: note.title,
|
|
450
|
+
activePage: 'notes',
|
|
451
|
+
currentPath: '/notes/' + slug,
|
|
452
|
+
breadcrumbs: [{ label: 'Notes', url: '/notes' }, { label: note.title }],
|
|
453
|
+
...note
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
res.setHeader('Vary', 'HX-Request');
|
|
457
|
+
|
|
458
|
+
if (req.get('HX-Request') === 'true') {
|
|
459
|
+
res.render('partials/note-detail-content', templateData);
|
|
460
|
+
} else {
|
|
461
|
+
res.render('note-detail', templateData);
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
|
|
407
465
|
router.get('/roadmap', async (req, res) => {
|
|
408
466
|
const projectDir = req.app.locals.projectDir;
|
|
409
467
|
const [roadmapData, stateData] = await Promise.all([
|
|
@@ -486,4 +544,61 @@ router.get('/quick/:id', async (req, res) => {
|
|
|
486
544
|
}
|
|
487
545
|
});
|
|
488
546
|
|
|
547
|
+
router.get('/audits', async (req, res) => {
|
|
548
|
+
const projectDir = req.app.locals.projectDir;
|
|
549
|
+
const reports = await listAuditReports(projectDir);
|
|
550
|
+
|
|
551
|
+
const templateData = {
|
|
552
|
+
title: 'Audit Reports',
|
|
553
|
+
activePage: 'audits',
|
|
554
|
+
currentPath: '/audits',
|
|
555
|
+
breadcrumbs: [{ label: 'Audit Reports' }],
|
|
556
|
+
reports
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
res.setHeader('Vary', 'HX-Request');
|
|
560
|
+
|
|
561
|
+
if (req.get('HX-Request') === 'true') {
|
|
562
|
+
res.render('partials/audits-content', templateData);
|
|
563
|
+
} else {
|
|
564
|
+
res.render('audits', templateData);
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
|
|
568
|
+
router.get('/audits/:filename', async (req, res) => {
|
|
569
|
+
const { filename } = req.params;
|
|
570
|
+
|
|
571
|
+
// Validate filename: safe characters only, must end in .md
|
|
572
|
+
if (!/^[\w.-]+\.md$/.test(filename)) {
|
|
573
|
+
const err = new Error('Invalid audit report filename');
|
|
574
|
+
err.status = 404;
|
|
575
|
+
throw err;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
const projectDir = req.app.locals.projectDir;
|
|
579
|
+
const report = await getAuditReport(projectDir, filename);
|
|
580
|
+
|
|
581
|
+
if (!report) {
|
|
582
|
+
const err = new Error(`Audit report "${filename}" not found`);
|
|
583
|
+
err.status = 404;
|
|
584
|
+
throw err;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
const templateData = {
|
|
588
|
+
title: report.title,
|
|
589
|
+
activePage: 'audits',
|
|
590
|
+
currentPath: '/audits/' + filename,
|
|
591
|
+
breadcrumbs: [{ label: 'Audit Reports', url: '/audits' }, { label: report.title }],
|
|
592
|
+
...report
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
res.setHeader('Vary', 'HX-Request');
|
|
596
|
+
|
|
597
|
+
if (req.get('HX-Request') === 'true') {
|
|
598
|
+
res.render('partials/audit-detail-content', templateData);
|
|
599
|
+
} else {
|
|
600
|
+
res.render('audit-detail', templateData);
|
|
601
|
+
}
|
|
602
|
+
});
|
|
603
|
+
|
|
489
604
|
export default router;
|
package/dashboard/src/server.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { createApp } from './app.js';
|
|
2
2
|
import { createWatcher } from './services/watcher.service.js';
|
|
3
3
|
import { broadcast } from './services/sse.service.js';
|
|
4
|
+
import { cache as milestoneCache } from './services/milestone.service.js';
|
|
5
|
+
import { cache as analyticsCache } from './services/analytics.service.js';
|
|
4
6
|
|
|
5
7
|
export function startServer(config) {
|
|
6
8
|
const app = createApp(config);
|
|
@@ -8,6 +10,8 @@ export function startServer(config) {
|
|
|
8
10
|
|
|
9
11
|
// Start file watcher for live updates
|
|
10
12
|
const watcher = createWatcher(projectDir, (event) => {
|
|
13
|
+
milestoneCache.invalidateAll();
|
|
14
|
+
analyticsCache.invalidateAll();
|
|
11
15
|
broadcast('file-change', event);
|
|
12
16
|
});
|
|
13
17
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { readdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { readMarkdownFile } from '../repositories/planning.repository.js';
|
|
4
|
+
|
|
5
|
+
export async function listAuditReports(projectDir) {
|
|
6
|
+
const auditsDir = join(projectDir, '.planning', 'audits');
|
|
7
|
+
let entries;
|
|
8
|
+
try {
|
|
9
|
+
entries = await readdir(auditsDir);
|
|
10
|
+
} catch (err) {
|
|
11
|
+
if (err.code === 'ENOENT') return [];
|
|
12
|
+
throw err;
|
|
13
|
+
}
|
|
14
|
+
const mdFiles = entries.filter(f => f.endsWith('.md')).sort().reverse();
|
|
15
|
+
const reports = [];
|
|
16
|
+
for (const filename of mdFiles) {
|
|
17
|
+
const dateMatch = filename.match(/^(\d{4}-\d{2}-\d{2})-(.+)\.md$/);
|
|
18
|
+
const date = dateMatch ? dateMatch[1] : null;
|
|
19
|
+
const slug = dateMatch ? dateMatch[2] : filename.replace(/\.md$/, '');
|
|
20
|
+
const title = slug.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
|
|
21
|
+
reports.push({ filename, date, slug, title });
|
|
22
|
+
}
|
|
23
|
+
return reports;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function getAuditReport(projectDir, filename) {
|
|
27
|
+
if (!/^[\w.-]+\.md$/.test(filename)) return null;
|
|
28
|
+
if (filename.includes('/') || filename.includes('\\') || filename.includes('..')) return null;
|
|
29
|
+
|
|
30
|
+
const auditsDir = join(projectDir, '.planning', 'audits');
|
|
31
|
+
try {
|
|
32
|
+
const { frontmatter, html } = await readMarkdownFile(join(auditsDir, filename));
|
|
33
|
+
const dateMatch = filename.match(/^(\d{4}-\d{2}-\d{2})-(.+)\.md$/);
|
|
34
|
+
const date = dateMatch ? dateMatch[1] : null;
|
|
35
|
+
const slug = dateMatch ? dateMatch[2] : filename.replace(/\.md$/, '');
|
|
36
|
+
const title = slug.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
|
|
37
|
+
return { filename, date, slug, title, frontmatter, html };
|
|
38
|
+
} catch (err) {
|
|
39
|
+
if (err.code === 'ENOENT') return null;
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -1,17 +1,6 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Strip UTF-8 BOM from file content.
|
|
6
|
-
* Duplicated from planning.repository.js intentionally --
|
|
7
|
-
* this service reads raw text, not via the repository layer.
|
|
8
|
-
*
|
|
9
|
-
* @param {string} content - Raw file content
|
|
10
|
-
* @returns {string} Content without BOM
|
|
11
|
-
*/
|
|
12
|
-
function stripBOM(content) {
|
|
13
|
-
return content.replace(/^\uFEFF/, '');
|
|
14
|
-
}
|
|
3
|
+
import { stripBOM } from '../utils/strip-bom.js';
|
|
15
4
|
|
|
16
5
|
/**
|
|
17
6
|
* Parse STATE.md to extract project status information.
|
|
@@ -1,17 +1,7 @@
|
|
|
1
1
|
import { readFile, readdir } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { parseRoadmapFile } from './dashboard.service.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Strip UTF-8 BOM from file content.
|
|
7
|
-
* Duplicated intentionally -- this service reads raw text, not via the repository layer.
|
|
8
|
-
*
|
|
9
|
-
* @param {string} content - Raw file content
|
|
10
|
-
* @returns {string} Content without BOM
|
|
11
|
-
*/
|
|
12
|
-
function stripBOM(content) {
|
|
13
|
-
return content.replace(/^\uFEFF/, '');
|
|
14
|
-
}
|
|
4
|
+
import { stripBOM } from '../utils/strip-bom.js';
|
|
15
5
|
|
|
16
6
|
/**
|
|
17
7
|
* Count the number of PLAN.md files in a phase directory.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<%- include('breadcrumbs', { breadcrumbs: typeof breadcrumbs !== 'undefined' ? breadcrumbs : [] }) %>
|
|
2
|
+
<h1><%= title %></h1>
|
|
3
|
+
|
|
4
|
+
<p><a href="/audits">← Back to Audit Reports</a></p>
|
|
5
|
+
|
|
6
|
+
<% if (typeof date !== 'undefined' && date) { %>
|
|
7
|
+
<p><small>Date: <%= date %></small></p>
|
|
8
|
+
<% } %>
|
|
9
|
+
|
|
10
|
+
<article class="markdown-body">
|
|
11
|
+
<%- html %>
|
|
12
|
+
</article>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<%- include('breadcrumbs', { breadcrumbs: typeof breadcrumbs !== 'undefined' ? breadcrumbs : [] }) %>
|
|
2
|
+
<h1>Audit Reports</h1>
|
|
3
|
+
|
|
4
|
+
<% if (typeof reports !== 'undefined' && reports.length > 0) { %>
|
|
5
|
+
<article>
|
|
6
|
+
<div class="table-wrap">
|
|
7
|
+
<table>
|
|
8
|
+
<thead>
|
|
9
|
+
<tr>
|
|
10
|
+
<th scope="col">Date</th>
|
|
11
|
+
<th scope="col">Report</th>
|
|
12
|
+
</tr>
|
|
13
|
+
</thead>
|
|
14
|
+
<tbody>
|
|
15
|
+
<% reports.forEach(function(report) { %>
|
|
16
|
+
<tr>
|
|
17
|
+
<td><%= report.date || '—' %></td>
|
|
18
|
+
<td>
|
|
19
|
+
<a href="/audits/<%= report.filename %>"
|
|
20
|
+
hx-get="/audits/<%= report.filename %>"
|
|
21
|
+
hx-target="#main-content"
|
|
22
|
+
hx-push-url="true">
|
|
23
|
+
<%= report.title %>
|
|
24
|
+
</a>
|
|
25
|
+
</td>
|
|
26
|
+
</tr>
|
|
27
|
+
<% }); %>
|
|
28
|
+
</tbody>
|
|
29
|
+
</table>
|
|
30
|
+
</div>
|
|
31
|
+
</article>
|
|
32
|
+
<% } else { %>
|
|
33
|
+
<%- include('empty-state', { icon: '🔍', title: 'No audit reports found', action: 'Run /pbr:audit to generate a session audit report.' }) %>
|
|
34
|
+
<% } %>
|
|
@@ -87,6 +87,14 @@
|
|
|
87
87
|
Quick Tasks
|
|
88
88
|
</a>
|
|
89
89
|
</li>
|
|
90
|
+
<li>
|
|
91
|
+
<a href="/audits"
|
|
92
|
+
hx-get="/audits"
|
|
93
|
+
hx-target="#main-content"
|
|
94
|
+
hx-push-url="true"<%= typeof activePage !== 'undefined' && activePage === 'audits' ? ' aria-current="page"' : '' %>>
|
|
95
|
+
Audit Reports
|
|
96
|
+
</a>
|
|
97
|
+
</li>
|
|
90
98
|
</ul>
|
|
91
99
|
</details>
|
|
92
100
|
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
<%- include('breadcrumbs', { breadcrumbs: typeof breadcrumbs !== 'undefined' ? breadcrumbs : [] }) %>
|
|
2
2
|
<h1>Todos</h1>
|
|
3
3
|
|
|
4
|
-
<p
|
|
4
|
+
<p>
|
|
5
|
+
<a href="/todos/new" role="button"
|
|
5
6
|
hx-get="/todos/new"
|
|
6
7
|
hx-target="#main-content"
|
|
7
|
-
hx-push-url="true">Create Todo</a
|
|
8
|
+
hx-push-url="true">Create Todo</a>
|
|
9
|
+
|
|
10
|
+
<a href="/todos/done"
|
|
11
|
+
hx-get="/todos/done"
|
|
12
|
+
hx-target="#main-content"
|
|
13
|
+
hx-push-url="true">View Completed Todos</a>
|
|
14
|
+
</p>
|
|
8
15
|
|
|
9
16
|
<% const f = typeof filters !== 'undefined' ? filters : { priority: '', status: '', q: '' }; %>
|
|
10
17
|
<article>
|
|
@@ -70,7 +77,10 @@
|
|
|
70
77
|
<tr>
|
|
71
78
|
<td><%= todo.id %></td>
|
|
72
79
|
<td>
|
|
73
|
-
<a href="/todos/<%= todo.id %>"
|
|
80
|
+
<a href="/todos/<%= todo.id %>"
|
|
81
|
+
hx-get="/todos/<%= todo.id %>"
|
|
82
|
+
hx-target="#main-content"
|
|
83
|
+
hx-push-url="true">
|
|
74
84
|
<%= todo.title %>
|
|
75
85
|
</a>
|
|
76
86
|
</td>
|
package/package.json
CHANGED
|
@@ -35,6 +35,7 @@ You MUST perform all applicable categories (skip only if zero items exist for th
|
|
|
35
35
|
3. **Auth Protection** — Every non-public route must have auth middleware. Frontend route guards must match backend protection.
|
|
36
36
|
4. **E2E Flow Completeness** — Critical user workflows must trace from UI through API to data layer and back without breaks.
|
|
37
37
|
5. **Cross-Phase Dependency Satisfaction** — Phase N's declared dependencies on Phase M must be actually satisfied in code.
|
|
38
|
+
6. **Data-Flow Propagation** — Values originating at one boundary (hook stdin fields, API request params, env vars) must propagate correctly through the call chain to their destination (log entries, database records, API responses). A connected pipeline with missing data is a broken integration.
|
|
38
39
|
|
|
39
40
|
> **First-phase edge case**: If no completed phases exist yet, focus on verifying the current phase's internal consistency — exports match imports within the phase, API contracts are self-consistent. Cross-phase checks are not applicable and should be skipped.
|
|
40
41
|
|
|
@@ -47,14 +48,19 @@ Read `references/agent-contracts.md` to validate agent-to-agent handoffs. Verify
|
|
|
47
48
|
- **Write access for output artifact only** — you have Write access for your output artifact only. You CANNOT fix source code — you REPORT issues.
|
|
48
49
|
- **Cross-phase scope** — unlike verifier (single phase), you check across phases.
|
|
49
50
|
|
|
50
|
-
##
|
|
51
|
+
## 7-Step Verification Process
|
|
51
52
|
|
|
52
53
|
1. **Build Export/Import Map**: Read each completed phase's SUMMARY.md frontmatter (`requires`, `provides`, `affects`). Grep actual exports/imports in source. Cross-reference declared vs actual — flag mismatches.
|
|
53
54
|
2. **Verify Export Usage**: For each `provides` item: locate actual export (missing = `MISSING_EXPORT` ERROR), find consumers (none = `ORPHANED` WARNING), verify usage not just import (`IMPORTED_UNUSED` WARNING), check signature compatibility (`MISMATCHED` ERROR). Status `CONSUMED` = OK.
|
|
54
55
|
3. **Verify API Coverage**: Discover routes, find frontend callers, match by method+path+body/params. Produce coverage table. See `references/integration-patterns.md` for framework-specific patterns.
|
|
55
56
|
4. **Verify Auth Protection**: Identify auth mechanism, list all routes, classify (public vs protected), check frontend guards. Flag UNPROTECTED routes.
|
|
56
57
|
5. **Verify E2E Flows**: Trace critical workflows step-by-step — verify each step exists and connects to the next (import/call/redirect). Record evidence (file:line). Flow status: COMPLETE | BROKEN | PARTIAL | UNTRACEABLE. See `references/integration-patterns.md` for flow templates.
|
|
57
|
-
6. **
|
|
58
|
+
6. **Verify Data-Flow Propagation**: For each cross-boundary data field identified in plans or SUMMARY.md, trace the value from source through intermediate functions to destination. Verify the value is actually passed (not `undefined`/`null`/hardcoded) at each step.
|
|
59
|
+
- **Source examples**: hook stdin (`data.session_id`), API request params, environment variables, config fields
|
|
60
|
+
- **Destination examples**: log entries, database records, API responses, metric files
|
|
61
|
+
- **Method**: Grep each intermediate call site and inspect arguments. Flag `DATA_DROPPED` when a value available in scope is replaced by `undefined` or a placeholder.
|
|
62
|
+
- **Status**: `PROPAGATED` (value flows correctly) | `DATA_DROPPED` (value lost at some step) | `UNTRACEABLE` (cannot determine flow)
|
|
63
|
+
7. **Compile Integration Report**: Produce final report with all findings by category.
|
|
58
64
|
|
|
59
65
|
## Output Format
|
|
60
66
|
|
|
@@ -119,3 +125,4 @@ See `references/integration-patterns.md` for grep/search patterns by framework.
|
|
|
119
125
|
- "File exists" is not "component is integrated"
|
|
120
126
|
- Auth middleware existing somewhere does not mean routes are protected
|
|
121
127
|
- Always check error handling paths, not just happy paths
|
|
128
|
+
- Structural connectivity is not data-flow correctness — a connected pipeline can still drop data at any step
|
|
@@ -66,6 +66,23 @@ Each must-have maps to one or more tasks. Every task exists to make a must-have
|
|
|
66
66
|
|
|
67
67
|
---
|
|
68
68
|
|
|
69
|
+
## Data Contracts for Cross-Boundary Parameters
|
|
70
|
+
|
|
71
|
+
When a function signature includes parameters that flow across module boundaries — session IDs from hook stdin, config objects from disk, auth tokens from environment — the plan **MUST** specify the **source** for each argument, not just the type.
|
|
72
|
+
|
|
73
|
+
For every cross-boundary call in a task's `<action>`, document:
|
|
74
|
+
|
|
75
|
+
| Parameter | Source | Context | Fallback |
|
|
76
|
+
|-----------|--------|---------|----------|
|
|
77
|
+
| `sessionId` | `data.session_id` (hook stdin) | Hook scripts only | `undefined` (CLI context) |
|
|
78
|
+
| `config` | `configLoad(planningDir)` | All callers | `resolveConfig(undefined)` |
|
|
79
|
+
|
|
80
|
+
**When to apply:** Any function call where the caller and callee live in different modules AND at least one argument originates from an external boundary (stdin, env, disk, network). Internal helper calls within the same module do not need contracts.
|
|
81
|
+
|
|
82
|
+
**Why this matters:** Without explicit source mapping, executors will use the type-correct but value-wrong default (e.g., `undefined` instead of `data.session_id`). The plan is the single source of truth for how data flows — if the plan says `undefined`, the executor will faithfully implement `undefined`.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
69
86
|
## Plan Structure
|
|
70
87
|
|
|
71
88
|
Read `references/plan-format.md` for the complete plan file specification including:
|
|
@@ -165,6 +182,7 @@ When CONTEXT.md or RESEARCH-SUMMARY.md contains `[NEEDS DECISION]` flags from th
|
|
|
165
182
|
- [ ] Dependencies are acyclic, no file conflicts within same wave
|
|
166
183
|
- [ ] Locked decisions honored, no deferred ideas included
|
|
167
184
|
- [ ] Verify commands are actually executable
|
|
185
|
+
- [ ] Cross-boundary parameters have documented sources (data contracts)
|
|
168
186
|
|
|
169
187
|
---
|
|
170
188
|
|
|
@@ -238,3 +256,4 @@ One-line task descriptions in `<name>`. File paths in `<files>`, not explanation
|
|
|
238
256
|
9. DO NOT plan for features outside the current phase goal
|
|
239
257
|
10. DO NOT assume research is done — check discovery level
|
|
240
258
|
11. DO NOT leave done conditions vague — they must be observable
|
|
259
|
+
12. DO NOT specify literal `undefined` for parameters that have a known source in the calling context — use data contracts to map sources
|
|
@@ -95,10 +95,29 @@ Verify the artifact is imported AND used by other parts of the system (functions
|
|
|
95
95
|
| Yes | Yes | No | UNWIRED |
|
|
96
96
|
| Yes | Yes | Yes | PASSED |
|
|
97
97
|
|
|
98
|
+
> **Note:** WIRED status (Level 3) requires correct arguments, not just correct function names. A call that passes `undefined` for a parameter available in scope is `ARGS_WRONG`, not `WIRED`.
|
|
99
|
+
|
|
98
100
|
### Step 6: Verify Key Links (Always)
|
|
99
101
|
|
|
100
102
|
For each key_link: identify source and target components, verify the import path resolves, verify the imported symbol is actually called/used, and verify call signatures match. Watch for: wrong import paths, imported-but-never-called symbols, defined-but-never-applied middleware, registered-but-never-triggered event handlers.
|
|
101
103
|
|
|
104
|
+
### Step 6b: Argument-Level Spot Checks (Always)
|
|
105
|
+
|
|
106
|
+
Beyond verifying that calls exist, spot-check that **arguments passed to cross-boundary calls carry the correct values**. A call with the right function but wrong arguments is effectively UNWIRED.
|
|
107
|
+
|
|
108
|
+
**Focus on:** IDs (session, user, request), config objects, auth tokens, and context data that originate from external boundaries (stdin, env, disk).
|
|
109
|
+
|
|
110
|
+
**Method:**
|
|
111
|
+
1. For each key_link verified in Step 6, grep the call site and inspect the arguments
|
|
112
|
+
2. Compare each argument against the data source available in the calling scope
|
|
113
|
+
3. Flag any argument that passes `undefined`, `null`, or a hardcoded placeholder when the calling scope has the real value available (e.g., `data.session_id` is in scope but `undefined` is passed)
|
|
114
|
+
|
|
115
|
+
**Classification:**
|
|
116
|
+
- `WIRED` requires both correct function AND correct arguments
|
|
117
|
+
- `ARGS_WRONG` = correct function called but one or more arguments are incorrect/missing — this is a key link gap
|
|
118
|
+
|
|
119
|
+
**Example:** A hook script receives `data` from stdin containing `session_id`. If it calls `logMetric(planningDir, { session_id: undefined })` instead of `logMetric(planningDir, { session_id: data.session_id })`, that is an `ARGS_WRONG` gap even though the call itself exists.
|
|
120
|
+
|
|
102
121
|
### Step 7: Check Requirements Coverage (Always)
|
|
103
122
|
|
|
104
123
|
Cross-reference all must-haves against verification results in a table:
|
|
@@ -107,8 +126,8 @@ Cross-reference all must-haves against verification results in a table:
|
|
|
107
126
|
| # | Must-Have | Type | L1 (Exists) | L2 (Substantive) | L3 (Wired) | Status |
|
|
108
127
|
|---|----------|------|-------------|-------------------|------------|--------|
|
|
109
128
|
| 1 | {description} | truth | - | - | - | VERIFIED/FAILED |
|
|
110
|
-
| 2 | {description} | artifact | YES/NO | YES/STUB/PARTIAL | WIRED/ORPHANED | PASS/FAIL |
|
|
111
|
-
| 3 | {description} | key_link | - | - | YES/NO | PASS/FAIL |
|
|
129
|
+
| 2 | {description} | artifact | YES/NO | YES/STUB/PARTIAL | WIRED/ORPHANED/ARGS_WRONG | PASS/FAIL |
|
|
130
|
+
| 3 | {description} | key_link | - | - | YES/NO/ARGS_WRONG | PASS/FAIL |
|
|
112
131
|
```
|
|
113
132
|
|
|
114
133
|
### Step 8: Scan for Anti-Patterns (Full Verification Only)
|
|
@@ -226,3 +245,4 @@ Read `references/stub-patterns.md` for stub detection patterns by technology. Re
|
|
|
226
245
|
9. DO NOT give PASSED status if ANY must-have fails at ANY level
|
|
227
246
|
10. DO NOT count deferred items as gaps — they are intentionally not implemented
|
|
228
247
|
11. DO NOT be lenient — your job is to find problems, not to be encouraging
|
|
248
|
+
12. DO NOT mark a call as WIRED if it passes hardcoded `undefined`/`null` for parameters that have a known source in scope — check arguments, not just function names
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbr",
|
|
3
3
|
"displayName": "Plan-Build-Run",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.24.0",
|
|
5
5
|
"description": "Plan-Build-Run — Structured development workflow for GitHub Copilot CLI. Solves context rot through disciplined agent delegation, structured planning, atomic execution, and goal-backward verification.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "SienkLogic",
|
|
@@ -71,6 +71,28 @@ requirement_ids:
|
|
|
71
71
|
| `consumes` | NO | array | What this plan needs from prior plans. Format: `"Thing (from plan XX-YY)"` |
|
|
72
72
|
| `requirement_ids` | NO | array | Requirement IDs from REQUIREMENTS.md or ROADMAP.md goal IDs that this plan addresses. Enables bidirectional traceability between plans and requirements/goals. |
|
|
73
73
|
| `dependency_fingerprints` | NO | object | Hashes of dependency phase SUMMARY.md files at plan-creation time. Used to detect stale plans. |
|
|
74
|
+
| `data_contracts` | NO | array | Cross-boundary parameter mappings for calls where arguments originate from external boundaries. Format: `"param: source (context) [fallback]"` |
|
|
75
|
+
|
|
76
|
+
### Data Contracts
|
|
77
|
+
|
|
78
|
+
When a task's `<action>` includes calls across module boundaries where arguments come from external sources (hook stdin, env vars, API params, config files), document the parameter-to-source mapping in `data_contracts` frontmatter and in the `<action>` step itself.
|
|
79
|
+
|
|
80
|
+
Example frontmatter:
|
|
81
|
+
|
|
82
|
+
```yaml
|
|
83
|
+
data_contracts:
|
|
84
|
+
- "sessionId: data.session_id (hook stdin) [undefined in CLI context]"
|
|
85
|
+
- "config: configLoad(planningDir) (disk) [resolveConfig(undefined)]"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Example in `<action>`:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
3. Call classifyArtifact(llmConfig, planningDir, content, fileType, data.session_id)
|
|
92
|
+
Data contract: sessionId ← data.session_id from hook stdin (undefined in CLI context)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**When to apply:** Any call where caller and callee are in different modules AND at least one argument originates from an external boundary. Internal helper calls within the same module do not need contracts.
|
|
74
96
|
|
|
75
97
|
---
|
|
76
98
|
|
|
@@ -112,7 +112,22 @@ Phase 03 (Core) ──provides──→ Phase 04 (Frontend)
|
|
|
112
112
|
### Flow 2: {Flow Name} - {STATUS}
|
|
113
113
|
...
|
|
114
114
|
|
|
115
|
-
## 5.
|
|
115
|
+
## 5. Data-Flow Propagation
|
|
116
|
+
|
|
117
|
+
### Cross-Boundary Data Flows
|
|
118
|
+
|
|
119
|
+
| Data Field | Source | Intermediate Steps | Destination | Status |
|
|
120
|
+
|------------|--------|-------------------|-------------|--------|
|
|
121
|
+
| {field name} | {origin, e.g., hook stdin `data.session_id`} | {module1:L12 → module2:L45} | {dest, e.g., metrics.jsonl `session_id`} | PROPAGATED |
|
|
122
|
+
| {field name} | {origin} | {module1:L12 → module2:L45} | {dest} | DATA_DROPPED |
|
|
123
|
+
|
|
124
|
+
### Data-Flow Issues
|
|
125
|
+
|
|
126
|
+
| Field | Dropped At | Available In Scope | Passed Instead | Fix |
|
|
127
|
+
|-------|-----------|-------------------|----------------|-----|
|
|
128
|
+
| {field} | {file:line} | `data.session_id` | `undefined` | Pass `data.session_id` |
|
|
129
|
+
|
|
130
|
+
## 6. Integration Issues Summary
|
|
116
131
|
|
|
117
132
|
### Critical Issues (system cannot function)
|
|
118
133
|
|
|
@@ -131,7 +146,7 @@ Phase 03 (Core) ──provides──→ Phase 04 (Frontend)
|
|
|
131
146
|
1. **{Issue}**: {description}
|
|
132
147
|
- Fix: {recommended action}
|
|
133
148
|
|
|
134
|
-
##
|
|
149
|
+
## 7. Integration Score
|
|
135
150
|
|
|
136
151
|
| Category | Items Checked | Passed | Failed | Score |
|
|
137
152
|
|----------|--------------|--------|--------|-------|
|
|
@@ -139,6 +154,7 @@ Phase 03 (Core) ──provides──→ Phase 04 (Frontend)
|
|
|
139
154
|
| API coverage | {n} | {n} | {n} | {%} |
|
|
140
155
|
| Auth protection | {n} | {n} | {n} | {%} |
|
|
141
156
|
| E2E flows | {n} | {n} | {n} | {%} |
|
|
157
|
+
| Data-flow propagation | {n} | {n} | {n} | {%} |
|
|
142
158
|
| **Overall** | {n} | {n} | {n} | **{%}** |
|
|
143
159
|
|
|
144
160
|
## Recommendations
|
|
@@ -54,8 +54,9 @@ anti_patterns:
|
|
|
54
54
|
|
|
55
55
|
| # | Link Description | Source | Target | Status | Evidence |
|
|
56
56
|
|---|-----------------|--------|--------|--------|----------|
|
|
57
|
-
| 1 | {what connects to what} | `{source_file}` | `{target_file}` | WIRED | Import at L12, called at L45 |
|
|
57
|
+
| 1 | {what connects to what} | `{source_file}` | `{target_file}` | WIRED | Import at L12, called at L45, args correct |
|
|
58
58
|
| 2 | {what connects to what} | `{source_file}` | `{target_file}` | BROKEN | Imported but never called |
|
|
59
|
+
| 3 | {what connects to what} | `{source_file}` | `{target_file}` | ARGS_WRONG | Called at L45 but passes undefined for sessionId (data.session_id in scope) |
|
|
59
60
|
|
|
60
61
|
## Gaps Found
|
|
61
62
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbr",
|
|
3
3
|
"displayName": "Plan-Build-Run",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.24.0",
|
|
5
5
|
"description": "Plan-Build-Run — Structured development workflow for Cursor. Solves context rot through disciplined subagent delegation, structured planning, atomic execution, and goal-backward verification.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "SienkLogic",
|
|
@@ -34,6 +34,7 @@ You MUST perform all applicable categories (skip only if zero items exist for th
|
|
|
34
34
|
3. **Auth Protection** — Every non-public route must have auth middleware. Frontend route guards must match backend protection.
|
|
35
35
|
4. **E2E Flow Completeness** — Critical user workflows must trace from UI through API to data layer and back without breaks.
|
|
36
36
|
5. **Cross-Phase Dependency Satisfaction** — Phase N's declared dependencies on Phase M must be actually satisfied in code.
|
|
37
|
+
6. **Data-Flow Propagation** — Values originating at one boundary (hook stdin fields, API request params, env vars) must propagate correctly through the call chain to their destination (log entries, database records, API responses). A connected pipeline with missing data is a broken integration.
|
|
37
38
|
|
|
38
39
|
> **First-phase edge case**: If no completed phases exist yet, focus on verifying the current phase's internal consistency — exports match imports within the phase, API contracts are self-consistent. Cross-phase checks are not applicable and should be skipped.
|
|
39
40
|
|
|
@@ -46,14 +47,19 @@ Read `references/agent-contracts.md` to validate agent-to-agent handoffs. Verify
|
|
|
46
47
|
- **Write access for output artifact only** — you have Write access for your output artifact only. You CANNOT fix source code — you REPORT issues.
|
|
47
48
|
- **Cross-phase scope** — unlike verifier (single phase), you check across phases.
|
|
48
49
|
|
|
49
|
-
##
|
|
50
|
+
## 7-Step Verification Process
|
|
50
51
|
|
|
51
52
|
1. **Build Export/Import Map**: Read each completed phase's SUMMARY.md frontmatter (`requires`, `provides`, `affects`). Grep actual exports/imports in source. Cross-reference declared vs actual — flag mismatches.
|
|
52
53
|
2. **Verify Export Usage**: For each `provides` item: locate actual export (missing = `MISSING_EXPORT` ERROR), find consumers (none = `ORPHANED` WARNING), verify usage not just import (`IMPORTED_UNUSED` WARNING), check signature compatibility (`MISMATCHED` ERROR). Status `CONSUMED` = OK.
|
|
53
54
|
3. **Verify API Coverage**: Discover routes, find frontend callers, match by method+path+body/params. Produce coverage table. See `references/integration-patterns.md` for framework-specific patterns.
|
|
54
55
|
4. **Verify Auth Protection**: Identify auth mechanism, list all routes, classify (public vs protected), check frontend guards. Flag UNPROTECTED routes.
|
|
55
56
|
5. **Verify E2E Flows**: Trace critical workflows step-by-step — verify each step exists and connects to the next (import/call/redirect). Record evidence (file:line). Flow status: COMPLETE | BROKEN | PARTIAL | UNTRACEABLE. See `references/integration-patterns.md` for flow templates.
|
|
56
|
-
6. **
|
|
57
|
+
6. **Verify Data-Flow Propagation**: For each cross-boundary data field identified in plans or SUMMARY.md, trace the value from source through intermediate functions to destination. Verify the value is actually passed (not `undefined`/`null`/hardcoded) at each step.
|
|
58
|
+
- **Source examples**: hook stdin (`data.session_id`), API request params, environment variables, config fields
|
|
59
|
+
- **Destination examples**: log entries, database records, API responses, metric files
|
|
60
|
+
- **Method**: Grep each intermediate call site and inspect arguments. Flag `DATA_DROPPED` when a value available in scope is replaced by `undefined` or a placeholder.
|
|
61
|
+
- **Status**: `PROPAGATED` (value flows correctly) | `DATA_DROPPED` (value lost at some step) | `UNTRACEABLE` (cannot determine flow)
|
|
62
|
+
7. **Compile Integration Report**: Produce final report with all findings by category.
|
|
57
63
|
|
|
58
64
|
## Output Format
|
|
59
65
|
|
|
@@ -118,3 +124,4 @@ See `references/integration-patterns.md` for grep/search patterns by framework.
|
|
|
118
124
|
- "File exists" is not "component is integrated"
|
|
119
125
|
- Auth middleware existing somewhere does not mean routes are protected
|
|
120
126
|
- Always check error handling paths, not just happy paths
|
|
127
|
+
- Structural connectivity is not data-flow correctness — a connected pipeline can still drop data at any step
|
|
@@ -65,6 +65,23 @@ Each must-have maps to one or more tasks. Every task exists to make a must-have
|
|
|
65
65
|
|
|
66
66
|
---
|
|
67
67
|
|
|
68
|
+
## Data Contracts for Cross-Boundary Parameters
|
|
69
|
+
|
|
70
|
+
When a function signature includes parameters that flow across module boundaries — session IDs from hook stdin, config objects from disk, auth tokens from environment — the plan **MUST** specify the **source** for each argument, not just the type.
|
|
71
|
+
|
|
72
|
+
For every cross-boundary call in a task's `<action>`, document:
|
|
73
|
+
|
|
74
|
+
| Parameter | Source | Context | Fallback |
|
|
75
|
+
|-----------|--------|---------|----------|
|
|
76
|
+
| `sessionId` | `data.session_id` (hook stdin) | Hook scripts only | `undefined` (CLI context) |
|
|
77
|
+
| `config` | `configLoad(planningDir)` | All callers | `resolveConfig(undefined)` |
|
|
78
|
+
|
|
79
|
+
**When to apply:** Any function call where the caller and callee live in different modules AND at least one argument originates from an external boundary (stdin, env, disk, network). Internal helper calls within the same module do not need contracts.
|
|
80
|
+
|
|
81
|
+
**Why this matters:** Without explicit source mapping, executors will use the type-correct but value-wrong default (e.g., `undefined` instead of `data.session_id`). The plan is the single source of truth for how data flows — if the plan says `undefined`, the executor will faithfully implement `undefined`.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
68
85
|
## Plan Structure
|
|
69
86
|
|
|
70
87
|
Read `references/plan-format.md` for the complete plan file specification including:
|
|
@@ -164,6 +181,7 @@ When CONTEXT.md or RESEARCH-SUMMARY.md contains `[NEEDS DECISION]` flags from th
|
|
|
164
181
|
- [ ] Dependencies are acyclic, no file conflicts within same wave
|
|
165
182
|
- [ ] Locked decisions honored, no deferred ideas included
|
|
166
183
|
- [ ] Verify commands are actually executable
|
|
184
|
+
- [ ] Cross-boundary parameters have documented sources (data contracts)
|
|
167
185
|
|
|
168
186
|
---
|
|
169
187
|
|
|
@@ -237,3 +255,4 @@ One-line task descriptions in `<name>`. File paths in `<files>`, not explanation
|
|
|
237
255
|
9. DO NOT plan for features outside the current phase goal
|
|
238
256
|
10. DO NOT assume research is done — check discovery level
|
|
239
257
|
11. DO NOT leave done conditions vague — they must be observable
|
|
258
|
+
12. DO NOT specify literal `undefined` for parameters that have a known source in the calling context — use data contracts to map sources
|
|
@@ -94,10 +94,29 @@ Verify the artifact is imported AND used by other parts of the system (functions
|
|
|
94
94
|
| Yes | Yes | No | UNWIRED |
|
|
95
95
|
| Yes | Yes | Yes | PASSED |
|
|
96
96
|
|
|
97
|
+
> **Note:** WIRED status (Level 3) requires correct arguments, not just correct function names. A call that passes `undefined` for a parameter available in scope is `ARGS_WRONG`, not `WIRED`.
|
|
98
|
+
|
|
97
99
|
### Step 6: Verify Key Links (Always)
|
|
98
100
|
|
|
99
101
|
For each key_link: identify source and target components, verify the import path resolves, verify the imported symbol is actually called/used, and verify call signatures match. Watch for: wrong import paths, imported-but-never-called symbols, defined-but-never-applied middleware, registered-but-never-triggered event handlers.
|
|
100
102
|
|
|
103
|
+
### Step 6b: Argument-Level Spot Checks (Always)
|
|
104
|
+
|
|
105
|
+
Beyond verifying that calls exist, spot-check that **arguments passed to cross-boundary calls carry the correct values**. A call with the right function but wrong arguments is effectively UNWIRED.
|
|
106
|
+
|
|
107
|
+
**Focus on:** IDs (session, user, request), config objects, auth tokens, and context data that originate from external boundaries (stdin, env, disk).
|
|
108
|
+
|
|
109
|
+
**Method:**
|
|
110
|
+
1. For each key_link verified in Step 6, grep the call site and inspect the arguments
|
|
111
|
+
2. Compare each argument against the data source available in the calling scope
|
|
112
|
+
3. Flag any argument that passes `undefined`, `null`, or a hardcoded placeholder when the calling scope has the real value available (e.g., `data.session_id` is in scope but `undefined` is passed)
|
|
113
|
+
|
|
114
|
+
**Classification:**
|
|
115
|
+
- `WIRED` requires both correct function AND correct arguments
|
|
116
|
+
- `ARGS_WRONG` = correct function called but one or more arguments are incorrect/missing — this is a key link gap
|
|
117
|
+
|
|
118
|
+
**Example:** A hook script receives `data` from stdin containing `session_id`. If it calls `logMetric(planningDir, { session_id: undefined })` instead of `logMetric(planningDir, { session_id: data.session_id })`, that is an `ARGS_WRONG` gap even though the call itself exists.
|
|
119
|
+
|
|
101
120
|
### Step 7: Check Requirements Coverage (Always)
|
|
102
121
|
|
|
103
122
|
Cross-reference all must-haves against verification results in a table:
|
|
@@ -106,8 +125,8 @@ Cross-reference all must-haves against verification results in a table:
|
|
|
106
125
|
| # | Must-Have | Type | L1 (Exists) | L2 (Substantive) | L3 (Wired) | Status |
|
|
107
126
|
|---|----------|------|-------------|-------------------|------------|--------|
|
|
108
127
|
| 1 | {description} | truth | - | - | - | VERIFIED/FAILED |
|
|
109
|
-
| 2 | {description} | artifact | YES/NO | YES/STUB/PARTIAL | WIRED/ORPHANED | PASS/FAIL |
|
|
110
|
-
| 3 | {description} | key_link | - | - | YES/NO | PASS/FAIL |
|
|
128
|
+
| 2 | {description} | artifact | YES/NO | YES/STUB/PARTIAL | WIRED/ORPHANED/ARGS_WRONG | PASS/FAIL |
|
|
129
|
+
| 3 | {description} | key_link | - | - | YES/NO/ARGS_WRONG | PASS/FAIL |
|
|
111
130
|
```
|
|
112
131
|
|
|
113
132
|
### Step 8: Scan for Anti-Patterns (Full Verification Only)
|
|
@@ -225,3 +244,4 @@ Read `references/stub-patterns.md` for stub detection patterns by technology. Re
|
|
|
225
244
|
9. DO NOT give PASSED status if ANY must-have fails at ANY level
|
|
226
245
|
10. DO NOT count deferred items as gaps — they are intentionally not implemented
|
|
227
246
|
11. DO NOT be lenient — your job is to find problems, not to be encouraging
|
|
247
|
+
12. DO NOT mark a call as WIRED if it passes hardcoded `undefined`/`null` for parameters that have a known source in scope — check arguments, not just function names
|
|
@@ -71,6 +71,28 @@ requirement_ids:
|
|
|
71
71
|
| `consumes` | NO | array | What this plan needs from prior plans. Format: `"Thing (from plan XX-YY)"` |
|
|
72
72
|
| `requirement_ids` | NO | array | Requirement IDs from REQUIREMENTS.md or ROADMAP.md goal IDs that this plan addresses. Enables bidirectional traceability between plans and requirements/goals. |
|
|
73
73
|
| `dependency_fingerprints` | NO | object | Hashes of dependency phase SUMMARY.md files at plan-creation time. Used to detect stale plans. |
|
|
74
|
+
| `data_contracts` | NO | array | Cross-boundary parameter mappings for calls where arguments originate from external boundaries. Format: `"param: source (context) [fallback]"` |
|
|
75
|
+
|
|
76
|
+
### Data Contracts
|
|
77
|
+
|
|
78
|
+
When a task's `<action>` includes calls across module boundaries where arguments come from external sources (hook stdin, env vars, API params, config files), document the parameter-to-source mapping in `data_contracts` frontmatter and in the `<action>` step itself.
|
|
79
|
+
|
|
80
|
+
Example frontmatter:
|
|
81
|
+
|
|
82
|
+
```yaml
|
|
83
|
+
data_contracts:
|
|
84
|
+
- "sessionId: data.session_id (hook stdin) [undefined in CLI context]"
|
|
85
|
+
- "config: configLoad(planningDir) (disk) [resolveConfig(undefined)]"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Example in `<action>`:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
3. Call classifyArtifact(llmConfig, planningDir, content, fileType, data.session_id)
|
|
92
|
+
Data contract: sessionId ← data.session_id from hook stdin (undefined in CLI context)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**When to apply:** Any call where caller and callee are in different modules AND at least one argument originates from an external boundary. Internal helper calls within the same module do not need contracts.
|
|
74
96
|
|
|
75
97
|
---
|
|
76
98
|
|
|
@@ -112,7 +112,22 @@ Phase 03 (Core) ──provides──→ Phase 04 (Frontend)
|
|
|
112
112
|
### Flow 2: {Flow Name} - {STATUS}
|
|
113
113
|
...
|
|
114
114
|
|
|
115
|
-
## 5.
|
|
115
|
+
## 5. Data-Flow Propagation
|
|
116
|
+
|
|
117
|
+
### Cross-Boundary Data Flows
|
|
118
|
+
|
|
119
|
+
| Data Field | Source | Intermediate Steps | Destination | Status |
|
|
120
|
+
|------------|--------|-------------------|-------------|--------|
|
|
121
|
+
| {field name} | {origin, e.g., hook stdin `data.session_id`} | {module1:L12 → module2:L45} | {dest, e.g., metrics.jsonl `session_id`} | PROPAGATED |
|
|
122
|
+
| {field name} | {origin} | {module1:L12 → module2:L45} | {dest} | DATA_DROPPED |
|
|
123
|
+
|
|
124
|
+
### Data-Flow Issues
|
|
125
|
+
|
|
126
|
+
| Field | Dropped At | Available In Scope | Passed Instead | Fix |
|
|
127
|
+
|-------|-----------|-------------------|----------------|-----|
|
|
128
|
+
| {field} | {file:line} | `data.session_id` | `undefined` | Pass `data.session_id` |
|
|
129
|
+
|
|
130
|
+
## 6. Integration Issues Summary
|
|
116
131
|
|
|
117
132
|
### Critical Issues (system cannot function)
|
|
118
133
|
|
|
@@ -131,7 +146,7 @@ Phase 03 (Core) ──provides──→ Phase 04 (Frontend)
|
|
|
131
146
|
1. **{Issue}**: {description}
|
|
132
147
|
- Fix: {recommended action}
|
|
133
148
|
|
|
134
|
-
##
|
|
149
|
+
## 7. Integration Score
|
|
135
150
|
|
|
136
151
|
| Category | Items Checked | Passed | Failed | Score |
|
|
137
152
|
|----------|--------------|--------|--------|-------|
|
|
@@ -139,6 +154,7 @@ Phase 03 (Core) ──provides──→ Phase 04 (Frontend)
|
|
|
139
154
|
| API coverage | {n} | {n} | {n} | {%} |
|
|
140
155
|
| Auth protection | {n} | {n} | {n} | {%} |
|
|
141
156
|
| E2E flows | {n} | {n} | {n} | {%} |
|
|
157
|
+
| Data-flow propagation | {n} | {n} | {n} | {%} |
|
|
142
158
|
| **Overall** | {n} | {n} | {n} | **{%}** |
|
|
143
159
|
|
|
144
160
|
## Recommendations
|
|
@@ -54,8 +54,9 @@ anti_patterns:
|
|
|
54
54
|
|
|
55
55
|
| # | Link Description | Source | Target | Status | Evidence |
|
|
56
56
|
|---|-----------------|--------|--------|--------|----------|
|
|
57
|
-
| 1 | {what connects to what} | `{source_file}` | `{target_file}` | WIRED | Import at L12, called at L45 |
|
|
57
|
+
| 1 | {what connects to what} | `{source_file}` | `{target_file}` | WIRED | Import at L12, called at L45, args correct |
|
|
58
58
|
| 2 | {what connects to what} | `{source_file}` | `{target_file}` | BROKEN | Imported but never called |
|
|
59
|
+
| 3 | {what connects to what} | `{source_file}` | `{target_file}` | ARGS_WRONG | Called at L45 but passes undefined for sessionId (data.session_id in scope) |
|
|
59
60
|
|
|
60
61
|
## Gaps Found
|
|
61
62
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbr",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.24.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",
|
|
@@ -40,6 +40,7 @@ You MUST perform all applicable categories (skip only if zero items exist for th
|
|
|
40
40
|
3. **Auth Protection** — Every non-public route must have auth middleware. Frontend route guards must match backend protection.
|
|
41
41
|
4. **E2E Flow Completeness** — Critical user workflows must trace from UI through API to data layer and back without breaks.
|
|
42
42
|
5. **Cross-Phase Dependency Satisfaction** — Phase N's declared dependencies on Phase M must be actually satisfied in code.
|
|
43
|
+
6. **Data-Flow Propagation** — Values originating at one boundary (hook stdin fields, API request params, env vars) must propagate correctly through the call chain to their destination (log entries, database records, API responses). A connected pipeline with missing data is a broken integration.
|
|
43
44
|
|
|
44
45
|
> **First-phase edge case**: If no completed phases exist yet, focus on verifying the current phase's internal consistency — exports match imports within the phase, API contracts are self-consistent. Cross-phase checks are not applicable and should be skipped.
|
|
45
46
|
|
|
@@ -52,14 +53,19 @@ Read `references/agent-contracts.md` to validate agent-to-agent handoffs. Verify
|
|
|
52
53
|
- **Write access for output artifact only** — you have Write access for your output artifact only. You CANNOT fix source code — you REPORT issues.
|
|
53
54
|
- **Cross-phase scope** — unlike verifier (single phase), you check across phases.
|
|
54
55
|
|
|
55
|
-
##
|
|
56
|
+
## 7-Step Verification Process
|
|
56
57
|
|
|
57
58
|
1. **Build Export/Import Map**: Read each completed phase's SUMMARY.md frontmatter (`requires`, `provides`, `affects`). Grep actual exports/imports in source. Cross-reference declared vs actual — flag mismatches.
|
|
58
59
|
2. **Verify Export Usage**: For each `provides` item: locate actual export (missing = `MISSING_EXPORT` ERROR), find consumers (none = `ORPHANED` WARNING), verify usage not just import (`IMPORTED_UNUSED` WARNING), check signature compatibility (`MISMATCHED` ERROR). Status `CONSUMED` = OK.
|
|
59
60
|
3. **Verify API Coverage**: Discover routes, find frontend callers, match by method+path+body/params. Produce coverage table. See `references/integration-patterns.md` for framework-specific patterns.
|
|
60
61
|
4. **Verify Auth Protection**: Identify auth mechanism, list all routes, classify (public vs protected), check frontend guards. Flag UNPROTECTED routes.
|
|
61
62
|
5. **Verify E2E Flows**: Trace critical workflows step-by-step — verify each step exists and connects to the next (import/call/redirect). Record evidence (file:line). Flow status: COMPLETE | BROKEN | PARTIAL | UNTRACEABLE. See `references/integration-patterns.md` for flow templates.
|
|
62
|
-
6. **
|
|
63
|
+
6. **Verify Data-Flow Propagation**: For each cross-boundary data field identified in plans or SUMMARY.md, trace the value from source through intermediate functions to destination. Verify the value is actually passed (not `undefined`/`null`/hardcoded) at each step.
|
|
64
|
+
- **Source examples**: hook stdin (`data.session_id`), API request params, environment variables, config fields
|
|
65
|
+
- **Destination examples**: log entries, database records, API responses, metric files
|
|
66
|
+
- **Method**: Grep each intermediate call site and inspect arguments. Flag `DATA_DROPPED` when a value available in scope is replaced by `undefined` or a placeholder.
|
|
67
|
+
- **Status**: `PROPAGATED` (value flows correctly) | `DATA_DROPPED` (value lost at some step) | `UNTRACEABLE` (cannot determine flow)
|
|
68
|
+
7. **Compile Integration Report**: Produce final report with all findings by category.
|
|
63
69
|
|
|
64
70
|
## Output Format
|
|
65
71
|
|
|
@@ -124,3 +130,4 @@ See `references/integration-patterns.md` for grep/search patterns by framework.
|
|
|
124
130
|
- "File exists" is not "component is integrated"
|
|
125
131
|
- Auth middleware existing somewhere does not mean routes are protected
|
|
126
132
|
- Always check error handling paths, not just happy paths
|
|
133
|
+
- Structural connectivity is not data-flow correctness — a connected pipeline can still drop data at any step
|
|
@@ -73,6 +73,23 @@ Each must-have maps to one or more tasks. Every task exists to make a must-have
|
|
|
73
73
|
|
|
74
74
|
---
|
|
75
75
|
|
|
76
|
+
## Data Contracts for Cross-Boundary Parameters
|
|
77
|
+
|
|
78
|
+
When a function signature includes parameters that flow across module boundaries — session IDs from hook stdin, config objects from disk, auth tokens from environment — the plan **MUST** specify the **source** for each argument, not just the type.
|
|
79
|
+
|
|
80
|
+
For every cross-boundary call in a task's `<action>`, document:
|
|
81
|
+
|
|
82
|
+
| Parameter | Source | Context | Fallback |
|
|
83
|
+
|-----------|--------|---------|----------|
|
|
84
|
+
| `sessionId` | `data.session_id` (hook stdin) | Hook scripts only | `undefined` (CLI context) |
|
|
85
|
+
| `config` | `configLoad(planningDir)` | All callers | `resolveConfig(undefined)` |
|
|
86
|
+
|
|
87
|
+
**When to apply:** Any function call where the caller and callee live in different modules AND at least one argument originates from an external boundary (stdin, env, disk, network). Internal helper calls within the same module do not need contracts.
|
|
88
|
+
|
|
89
|
+
**Why this matters:** Without explicit source mapping, executors will use the type-correct but value-wrong default (e.g., `undefined` instead of `data.session_id`). The plan is the single source of truth for how data flows — if the plan says `undefined`, the executor will faithfully implement `undefined`.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
76
93
|
## Plan Structure
|
|
77
94
|
|
|
78
95
|
Read `references/plan-format.md` for the complete plan file specification including:
|
|
@@ -172,6 +189,7 @@ When CONTEXT.md or RESEARCH-SUMMARY.md contains `[NEEDS DECISION]` flags from th
|
|
|
172
189
|
- [ ] Dependencies are acyclic, no file conflicts within same wave
|
|
173
190
|
- [ ] Locked decisions honored, no deferred ideas included
|
|
174
191
|
- [ ] Verify commands are actually executable
|
|
192
|
+
- [ ] Cross-boundary parameters have documented sources (data contracts)
|
|
175
193
|
|
|
176
194
|
---
|
|
177
195
|
|
|
@@ -245,3 +263,4 @@ One-line task descriptions in `<name>`. File paths in `<files>`, not explanation
|
|
|
245
263
|
9. DO NOT plan for features outside the current phase goal
|
|
246
264
|
10. DO NOT assume research is done — check discovery level
|
|
247
265
|
11. DO NOT leave done conditions vague — they must be observable
|
|
266
|
+
12. DO NOT specify literal `undefined` for parameters that have a known source in the calling context — use data contracts to map sources
|
|
@@ -101,10 +101,29 @@ Verify the artifact is imported AND used by other parts of the system (functions
|
|
|
101
101
|
| Yes | Yes | No | UNWIRED |
|
|
102
102
|
| Yes | Yes | Yes | PASSED |
|
|
103
103
|
|
|
104
|
+
> **Note:** WIRED status (Level 3) requires correct arguments, not just correct function names. A call that passes `undefined` for a parameter available in scope is `ARGS_WRONG`, not `WIRED`.
|
|
105
|
+
|
|
104
106
|
### Step 6: Verify Key Links (Always)
|
|
105
107
|
|
|
106
108
|
For each key_link: identify source and target components, verify the import path resolves, verify the imported symbol is actually called/used, and verify call signatures match. Watch for: wrong import paths, imported-but-never-called symbols, defined-but-never-applied middleware, registered-but-never-triggered event handlers.
|
|
107
109
|
|
|
110
|
+
### Step 6b: Argument-Level Spot Checks (Always)
|
|
111
|
+
|
|
112
|
+
Beyond verifying that calls exist, spot-check that **arguments passed to cross-boundary calls carry the correct values**. A call with the right function but wrong arguments is effectively UNWIRED.
|
|
113
|
+
|
|
114
|
+
**Focus on:** IDs (session, user, request), config objects, auth tokens, and context data that originate from external boundaries (stdin, env, disk).
|
|
115
|
+
|
|
116
|
+
**Method:**
|
|
117
|
+
1. For each key_link verified in Step 6, grep the call site and inspect the arguments
|
|
118
|
+
2. Compare each argument against the data source available in the calling scope
|
|
119
|
+
3. Flag any argument that passes `undefined`, `null`, or a hardcoded placeholder when the calling scope has the real value available (e.g., `data.session_id` is in scope but `undefined` is passed)
|
|
120
|
+
|
|
121
|
+
**Classification:**
|
|
122
|
+
- `WIRED` requires both correct function AND correct arguments
|
|
123
|
+
- `ARGS_WRONG` = correct function called but one or more arguments are incorrect/missing — this is a key link gap
|
|
124
|
+
|
|
125
|
+
**Example:** A hook script receives `data` from stdin containing `session_id`. If it calls `logMetric(planningDir, { session_id: undefined })` instead of `logMetric(planningDir, { session_id: data.session_id })`, that is an `ARGS_WRONG` gap even though the call itself exists.
|
|
126
|
+
|
|
108
127
|
### Step 7: Check Requirements Coverage (Always)
|
|
109
128
|
|
|
110
129
|
Cross-reference all must-haves against verification results in a table:
|
|
@@ -113,8 +132,8 @@ Cross-reference all must-haves against verification results in a table:
|
|
|
113
132
|
| # | Must-Have | Type | L1 (Exists) | L2 (Substantive) | L3 (Wired) | Status |
|
|
114
133
|
|---|----------|------|-------------|-------------------|------------|--------|
|
|
115
134
|
| 1 | {description} | truth | - | - | - | VERIFIED/FAILED |
|
|
116
|
-
| 2 | {description} | artifact | YES/NO | YES/STUB/PARTIAL | WIRED/ORPHANED | PASS/FAIL |
|
|
117
|
-
| 3 | {description} | key_link | - | - | YES/NO | PASS/FAIL |
|
|
135
|
+
| 2 | {description} | artifact | YES/NO | YES/STUB/PARTIAL | WIRED/ORPHANED/ARGS_WRONG | PASS/FAIL |
|
|
136
|
+
| 3 | {description} | key_link | - | - | YES/NO/ARGS_WRONG | PASS/FAIL |
|
|
118
137
|
```
|
|
119
138
|
|
|
120
139
|
### Step 8: Scan for Anti-Patterns (Full Verification Only)
|
|
@@ -232,3 +251,4 @@ Read `references/stub-patterns.md` for stub detection patterns by technology. Re
|
|
|
232
251
|
9. DO NOT give PASSED status if ANY must-have fails at ANY level
|
|
233
252
|
10. DO NOT count deferred items as gaps — they are intentionally not implemented
|
|
234
253
|
11. DO NOT be lenient — your job is to find problems, not to be encouraging
|
|
254
|
+
12. DO NOT mark a call as WIRED if it passes hardcoded `undefined`/`null` for parameters that have a known source in scope — check arguments, not just function names
|
|
@@ -70,6 +70,28 @@ requirement_ids:
|
|
|
70
70
|
| `consumes` | NO | array | What this plan needs from prior plans. Format: `"Thing (from plan XX-YY)"` |
|
|
71
71
|
| `requirement_ids` | NO | array | Requirement IDs from REQUIREMENTS.md or ROADMAP.md goal IDs that this plan addresses. Enables bidirectional traceability between plans and requirements/goals. |
|
|
72
72
|
| `dependency_fingerprints` | NO | object | Hashes of dependency phase SUMMARY.md files at plan-creation time. Used to detect stale plans. |
|
|
73
|
+
| `data_contracts` | NO | array | Cross-boundary parameter mappings for calls where arguments originate from external boundaries. Format: `"param: source (context) [fallback]"` |
|
|
74
|
+
|
|
75
|
+
### Data Contracts
|
|
76
|
+
|
|
77
|
+
When a task's `<action>` includes calls across module boundaries where arguments come from external sources (hook stdin, env vars, API params, config files), document the parameter-to-source mapping in `data_contracts` frontmatter and in the `<action>` step itself.
|
|
78
|
+
|
|
79
|
+
Example frontmatter:
|
|
80
|
+
|
|
81
|
+
```yaml
|
|
82
|
+
data_contracts:
|
|
83
|
+
- "sessionId: data.session_id (hook stdin) [undefined in CLI context]"
|
|
84
|
+
- "config: configLoad(planningDir) (disk) [resolveConfig(undefined)]"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Example in `<action>`:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
3. Call classifyArtifact(llmConfig, planningDir, content, fileType, data.session_id)
|
|
91
|
+
Data contract: sessionId ← data.session_id from hook stdin (undefined in CLI context)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**When to apply:** Any call where caller and callee are in different modules AND at least one argument originates from an external boundary. Internal helper calls within the same module do not need contracts.
|
|
73
95
|
|
|
74
96
|
---
|
|
75
97
|
|
|
@@ -84,7 +84,7 @@ async function main() {
|
|
|
84
84
|
const llmConfig = loadLocalLlmConfig();
|
|
85
85
|
const planningDir = path.join(process.cwd(), '.planning');
|
|
86
86
|
const fileType = isPlan ? 'PLAN' : 'SUMMARY';
|
|
87
|
-
const llmResult = await classifyArtifact(llmConfig, planningDir, content, fileType,
|
|
87
|
+
const llmResult = await classifyArtifact(llmConfig, planningDir, content, fileType, data.session_id);
|
|
88
88
|
if (llmResult && llmResult.classification) {
|
|
89
89
|
const llmNote = `Local LLM: ${fileType} classified as "${llmResult.classification}" (confidence: ${(llmResult.confidence * 100).toFixed(0)}%)${llmResult.reason ? ' — ' + llmResult.reason : ''}`;
|
|
90
90
|
result.warnings.push(llmNote);
|
|
@@ -287,7 +287,7 @@ async function checkPlanWrite(data) {
|
|
|
287
287
|
const llmConfig = loadLocalLlmConfig();
|
|
288
288
|
const planningDir = path.join(process.cwd(), '.planning');
|
|
289
289
|
const fileType = isPlan ? 'PLAN' : 'SUMMARY';
|
|
290
|
-
const llmResult = await classifyArtifact(llmConfig, planningDir, content, fileType,
|
|
290
|
+
const llmResult = await classifyArtifact(llmConfig, planningDir, content, fileType, data.session_id);
|
|
291
291
|
if (llmResult && llmResult.classification) {
|
|
292
292
|
const llmNote = `Local LLM: ${fileType} classified as "${llmResult.classification}" (confidence: ${(llmResult.confidence * 100).toFixed(0)}%)${llmResult.reason ? ' — ' + llmResult.reason : ''}`;
|
|
293
293
|
result.warnings.push(llmNote);
|
|
@@ -444,7 +444,7 @@ async function main() {
|
|
|
444
444
|
const llmConfig = loadLocalLlmConfig(cwd);
|
|
445
445
|
const errorText = (data.tool_output || '').substring(0, 500);
|
|
446
446
|
if (errorText) {
|
|
447
|
-
const llmResult = await classifyError(llmConfig, planningDir, errorText, agentType,
|
|
447
|
+
const llmResult = await classifyError(llmConfig, planningDir, errorText, agentType, data.session_id);
|
|
448
448
|
if (llmResult && llmResult.category) {
|
|
449
449
|
llmCategoryNote = `\nLLM error category: ${llmResult.category} (confidence: ${(llmResult.confidence * 100).toFixed(0)}%)`;
|
|
450
450
|
}
|
|
@@ -467,7 +467,7 @@ async function main() {
|
|
|
467
467
|
const llmConfig = loadLocalLlmConfig(cwd);
|
|
468
468
|
const errorText = (data.tool_output || '').substring(0, 500);
|
|
469
469
|
if (errorText) {
|
|
470
|
-
const llmResult = await classifyError(llmConfig, planningDir, errorText, agentType,
|
|
470
|
+
const llmResult = await classifyError(llmConfig, planningDir, errorText, agentType, data.session_id);
|
|
471
471
|
if (llmResult && llmResult.category) {
|
|
472
472
|
llmCategoryNote = `\nLLM error category: ${llmResult.category} (confidence: ${(llmResult.confidence * 100).toFixed(0)}%)`;
|
|
473
473
|
}
|
|
@@ -805,7 +805,7 @@ function main() {
|
|
|
805
805
|
try {
|
|
806
806
|
const llmConfig = loadLocalLlmConfig(process.cwd());
|
|
807
807
|
const planningDir = path.join(process.cwd(), '.planning');
|
|
808
|
-
const llmResult = await llmValidateTask(llmConfig, planningDir, data.tool_input || {},
|
|
808
|
+
const llmResult = await llmValidateTask(llmConfig, planningDir, data.tool_input || {}, data.session_id);
|
|
809
809
|
if (llmResult && !llmResult.coherent) {
|
|
810
810
|
warnings.push('LLM task coherence advisory: ' + (llmResult.issue || 'Task description may not match intended operation.') + ' (confidence: ' + (llmResult.confidence * 100).toFixed(0) + '%)');
|
|
811
811
|
}
|
|
@@ -111,7 +111,22 @@ Phase 03 (Core) ──provides──→ Phase 04 (Frontend)
|
|
|
111
111
|
### Flow 2: {Flow Name} - {STATUS}
|
|
112
112
|
...
|
|
113
113
|
|
|
114
|
-
## 5.
|
|
114
|
+
## 5. Data-Flow Propagation
|
|
115
|
+
|
|
116
|
+
### Cross-Boundary Data Flows
|
|
117
|
+
|
|
118
|
+
| Data Field | Source | Intermediate Steps | Destination | Status |
|
|
119
|
+
|------------|--------|-------------------|-------------|--------|
|
|
120
|
+
| {field name} | {origin, e.g., hook stdin `data.session_id`} | {module1:L12 → module2:L45} | {dest, e.g., metrics.jsonl `session_id`} | PROPAGATED |
|
|
121
|
+
| {field name} | {origin} | {module1:L12 → module2:L45} | {dest} | DATA_DROPPED |
|
|
122
|
+
|
|
123
|
+
### Data-Flow Issues
|
|
124
|
+
|
|
125
|
+
| Field | Dropped At | Available In Scope | Passed Instead | Fix |
|
|
126
|
+
|-------|-----------|-------------------|----------------|-----|
|
|
127
|
+
| {field} | {file:line} | `data.session_id` | `undefined` | Pass `data.session_id` |
|
|
128
|
+
|
|
129
|
+
## 6. Integration Issues Summary
|
|
115
130
|
|
|
116
131
|
### Critical Issues (system cannot function)
|
|
117
132
|
|
|
@@ -130,7 +145,7 @@ Phase 03 (Core) ──provides──→ Phase 04 (Frontend)
|
|
|
130
145
|
1. **{Issue}**: {description}
|
|
131
146
|
- Fix: {recommended action}
|
|
132
147
|
|
|
133
|
-
##
|
|
148
|
+
## 7. Integration Score
|
|
134
149
|
|
|
135
150
|
| Category | Items Checked | Passed | Failed | Score |
|
|
136
151
|
|----------|--------------|--------|--------|-------|
|
|
@@ -138,6 +153,7 @@ Phase 03 (Core) ──provides──→ Phase 04 (Frontend)
|
|
|
138
153
|
| API coverage | {n} | {n} | {n} | {%} |
|
|
139
154
|
| Auth protection | {n} | {n} | {n} | {%} |
|
|
140
155
|
| E2E flows | {n} | {n} | {n} | {%} |
|
|
156
|
+
| Data-flow propagation | {n} | {n} | {n} | {%} |
|
|
141
157
|
| **Overall** | {n} | {n} | {n} | **{%}** |
|
|
142
158
|
|
|
143
159
|
## Recommendations
|
|
@@ -53,8 +53,9 @@ anti_patterns:
|
|
|
53
53
|
|
|
54
54
|
| # | Link Description | Source | Target | Status | Evidence |
|
|
55
55
|
|---|-----------------|--------|--------|--------|----------|
|
|
56
|
-
| 1 | {what connects to what} | `{source_file}` | `{target_file}` | WIRED | Import at L12, called at L45 |
|
|
56
|
+
| 1 | {what connects to what} | `{source_file}` | `{target_file}` | WIRED | Import at L12, called at L45, args correct |
|
|
57
57
|
| 2 | {what connects to what} | `{source_file}` | `{target_file}` | BROKEN | Imported but never called |
|
|
58
|
+
| 3 | {what connects to what} | `{source_file}` | `{target_file}` | ARGS_WRONG | Called at L45 but passes undefined for sessionId (data.session_id in scope) |
|
|
58
59
|
|
|
59
60
|
## Gaps Found
|
|
60
61
|
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
<%- include('partials/layout-top', { title: title, activePage: activePage }) %>
|
|
2
|
-
|
|
3
|
-
<h1><%= featureName %></h1>
|
|
4
|
-
<p>This feature is coming soon.</p>
|
|
5
|
-
<p>
|
|
6
|
-
The <strong><%= featureName %></strong> view is planned but not yet implemented.
|
|
7
|
-
Check back in a future phase.
|
|
8
|
-
</p>
|
|
9
|
-
<p><a href="/">Back to Dashboard</a></p>
|
|
10
|
-
|
|
11
|
-
<%- include('partials/layout-bottom') %>
|