portable-agent-layer 0.30.1 → 0.32.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.
Files changed (58) hide show
  1. package/assets/skills/consulting-report/SKILL.md +74 -74
  2. package/assets/skills/consulting-report/demo/app/globals.css +459 -0
  3. package/assets/skills/consulting-report/demo/app/layout.tsx +32 -0
  4. package/assets/skills/consulting-report/demo/app/page.tsx +302 -0
  5. package/assets/skills/consulting-report/demo/bun.lock +240 -0
  6. package/assets/skills/consulting-report/demo/components/callout.tsx +13 -0
  7. package/assets/skills/consulting-report/demo/components/comparison-table.tsx +40 -0
  8. package/assets/skills/consulting-report/demo/components/cover-page.tsx +34 -0
  9. package/assets/skills/consulting-report/demo/components/exhibit.tsx +21 -0
  10. package/assets/skills/consulting-report/demo/components/finding-card.tsx +28 -0
  11. package/assets/skills/consulting-report/demo/components/quote-block.tsx +17 -0
  12. package/assets/skills/consulting-report/demo/components/recommendation-card.tsx +52 -0
  13. package/assets/skills/consulting-report/demo/components/section.tsx +17 -0
  14. package/assets/skills/consulting-report/demo/components/severity-badge.tsx +19 -0
  15. package/assets/skills/consulting-report/demo/components/stat-grid.tsx +26 -0
  16. package/assets/skills/consulting-report/demo/components/table-of-contents.tsx +27 -0
  17. package/assets/skills/consulting-report/demo/components/timeline.tsx +20 -0
  18. package/assets/skills/consulting-report/demo/lib/report-data.ts +247 -0
  19. package/assets/skills/consulting-report/demo/lib/utils.ts +6 -0
  20. package/assets/skills/consulting-report/demo/next.config.js +9 -0
  21. package/assets/skills/consulting-report/demo/package.json +27 -0
  22. package/assets/skills/consulting-report/demo/postcss.config.mjs +5 -0
  23. package/assets/skills/consulting-report/demo/tsconfig.json +41 -0
  24. package/assets/skills/consulting-report/template/app/globals.css +459 -0
  25. package/assets/skills/consulting-report/template/app/layout.tsx +32 -0
  26. package/assets/skills/consulting-report/template/app/page.tsx +282 -0
  27. package/assets/skills/consulting-report/template/bun.lock +240 -0
  28. package/assets/skills/consulting-report/template/components/callout.tsx +13 -0
  29. package/assets/skills/consulting-report/template/components/comparison-table.tsx +40 -0
  30. package/assets/skills/consulting-report/template/components/cover-page.tsx +34 -0
  31. package/assets/skills/consulting-report/template/components/exhibit.tsx +21 -0
  32. package/assets/skills/consulting-report/template/components/finding-card.tsx +28 -0
  33. package/assets/skills/consulting-report/template/components/quote-block.tsx +17 -0
  34. package/assets/skills/consulting-report/template/components/recommendation-card.tsx +52 -0
  35. package/assets/skills/consulting-report/template/components/section.tsx +17 -0
  36. package/assets/skills/consulting-report/template/components/severity-badge.tsx +19 -0
  37. package/assets/skills/consulting-report/template/components/stat-grid.tsx +26 -0
  38. package/assets/skills/consulting-report/template/components/table-of-contents.tsx +27 -0
  39. package/assets/skills/consulting-report/template/components/timeline.tsx +20 -0
  40. package/assets/skills/consulting-report/template/lib/report-data.ts +176 -0
  41. package/assets/skills/consulting-report/template/lib/utils.ts +6 -0
  42. package/assets/skills/consulting-report/template/next.config.js +9 -0
  43. package/assets/skills/consulting-report/template/package.json +27 -0
  44. package/assets/skills/consulting-report/template/postcss.config.mjs +5 -0
  45. package/assets/skills/consulting-report/template/tsconfig.json +27 -0
  46. package/assets/skills/consulting-report/tools/dev.ts +47 -0
  47. package/assets/skills/consulting-report/tools/generate-pdf.ts +140 -408
  48. package/assets/skills/consulting-report/tools/scaffold.ts +83 -48
  49. package/assets/skills/presentation/SKILL.md +1 -1
  50. package/package.json +9 -9
  51. package/assets/skills/consulting-report/demo/content/current-state.md +0 -33
  52. package/assets/skills/consulting-report/demo/content/executive-summary.md +0 -19
  53. package/assets/skills/consulting-report/demo/content/report-data.ts +0 -101
  54. package/assets/skills/consulting-report/demo/diagrams/.gitkeep +0 -0
  55. package/assets/skills/consulting-report/template/README.md +0 -28
  56. package/assets/skills/consulting-report/template/content/executive-summary.md +0 -19
  57. package/assets/skills/consulting-report/template/content/report-data.ts +0 -59
  58. package/assets/skills/consulting-report/template/diagrams/.gitkeep +0 -0
@@ -1,29 +1,23 @@
1
1
  #!/usr/bin/env bun
2
2
 
3
- // consulting-report skill tool: scaffold a new report directory from the template.
3
+ // consulting-report skill tool: scaffold a new report directory from the template
4
+ // and install Next.js dependencies.
4
5
  //
5
6
  // Usage:
6
- // bun ~/.pal/skills/consulting-report/tools/scaffold.ts <target-dir> [--client "Client Name"] [--title "Report Title"]
7
+ // bun ~/.pal/skills/consulting-report/tools/scaffold.ts <target-dir> \
8
+ // [--client "Client Name"] [--title "Report Title"] [--no-install]
7
9
 
10
+ import { spawnSync } from "node:child_process";
8
11
  import { constants as fsConstants } from "node:fs";
9
12
  import { access, cp, mkdir, readFile, writeFile } from "node:fs/promises";
10
13
  import { dirname, join, resolve } from "node:path";
11
14
  import { fileURLToPath } from "node:url";
12
15
 
13
- const args = process.argv.slice(2);
14
- if (args.length === 0) {
15
- console.error(
16
- 'usage: scaffold.ts <target-dir> [--client "Client Name"] [--title "Report Title"]'
17
- );
18
- process.exit(1);
19
- }
20
-
21
- const targetDir = resolve(args[0]);
22
- let clientName = "";
23
- let reportTitle = "";
24
- for (let i = 1; i < args.length; i++) {
25
- if (args[i] === "--client") clientName = args[++i];
26
- else if (args[i] === "--title") reportTitle = args[++i];
16
+ interface ScaffoldOptions {
17
+ targetDir: string;
18
+ clientName?: string;
19
+ reportTitle?: string;
20
+ install?: boolean;
27
21
  }
28
22
 
29
23
  async function exists(p: string): Promise<boolean> {
@@ -35,40 +29,81 @@ async function exists(p: string): Promise<boolean> {
35
29
  }
36
30
  }
37
31
 
38
- const here = dirname(fileURLToPath(import.meta.url));
39
- const templateDir = resolve(here, "..", "template");
40
-
41
- if (!(await exists(templateDir))) {
42
- console.error(`template not found at ${templateDir}`);
43
- process.exit(1);
32
+ function templateDir(): string {
33
+ const here = dirname(fileURLToPath(import.meta.url));
34
+ return resolve(here, "..", "template");
44
35
  }
45
- if (await exists(targetDir)) {
46
- console.error(`target already exists: ${targetDir}`);
47
- process.exit(1);
36
+
37
+ export async function scaffold(opts: ScaffoldOptions): Promise<void> {
38
+ const tpl = templateDir();
39
+ if (!(await exists(tpl))) {
40
+ throw new Error(`template not found at ${tpl}`);
41
+ }
42
+ if (await exists(opts.targetDir)) {
43
+ throw new Error(`target already exists: ${opts.targetDir}`);
44
+ }
45
+
46
+ await mkdir(dirname(opts.targetDir), { recursive: true });
47
+ await cp(tpl, opts.targetDir, { recursive: true });
48
+
49
+ if (opts.clientName || opts.reportTitle) {
50
+ const dataPath = join(opts.targetDir, "lib", "report-data.ts");
51
+ let data = await readFile(dataPath, "utf8");
52
+ if (opts.clientName) {
53
+ data = data.replace(/\[CLIENT NAME\]/g, opts.clientName);
54
+ }
55
+ if (opts.reportTitle) {
56
+ data = data.replace(
57
+ /Strategic Assessment & Transformation Roadmap/,
58
+ opts.reportTitle
59
+ );
60
+ }
61
+ await writeFile(dataPath, data, "utf8");
62
+ }
63
+
64
+ if (opts.install !== false) {
65
+ console.log("Installing dependencies (bun install)...");
66
+ const result = spawnSync("bun", ["install"], {
67
+ cwd: opts.targetDir,
68
+ stdio: "inherit",
69
+ shell: true,
70
+ });
71
+ if (result.status !== 0) {
72
+ console.warn(
73
+ `bun install failed (exit ${result.status}) — run it manually in ${opts.targetDir}`
74
+ );
75
+ }
76
+ }
48
77
  }
49
78
 
50
- await mkdir(dirname(targetDir), { recursive: true });
51
- await cp(templateDir, targetDir, { recursive: true });
79
+ function parseArgs(argv: string[]): ScaffoldOptions {
80
+ if (argv.length === 0) {
81
+ throw new Error(
82
+ 'usage: scaffold.ts <target-dir> [--client "Name"] [--title "Title"] [--no-install]'
83
+ );
84
+ }
85
+ const opts: ScaffoldOptions = { targetDir: resolve(argv[0]) };
86
+ for (let i = 1; i < argv.length; i++) {
87
+ if (argv[i] === "--client") opts.clientName = argv[++i];
88
+ else if (argv[i] === "--title") opts.reportTitle = argv[++i];
89
+ else if (argv[i] === "--no-install") opts.install = false;
90
+ }
91
+ return opts;
92
+ }
52
93
 
53
- // Stamp today's date + client/title + tool import path into the new report-data.ts.
54
- // Scaffolded reports live outside the skill tree, so the type-import needs an
55
- // absolute path to the generator rather than a relative one.
56
- const dataPath = join(targetDir, "content", "report-data.ts");
57
- const toolPath = resolve(here, "generate-pdf").replace(/\.ts$/, "");
58
- const today = new Date().toISOString().slice(0, 10);
59
- let data = await readFile(dataPath, "utf8");
60
- data = data.replace(/\{\{DATE\}\}/g, today);
61
- data = data.replace(/\{\{TOOL_PATH\}\}/g, toolPath);
62
- if (clientName) data = data.replace(/\{\{CLIENT_NAME\}\}/g, clientName);
63
- if (reportTitle) data = data.replace(/\{\{REPORT_TITLE\}\}/g, reportTitle);
64
- await writeFile(dataPath, data, "utf8");
94
+ export async function run(argv: string[] = process.argv.slice(2)): Promise<void> {
95
+ const opts = parseArgs(argv);
96
+ await scaffold(opts);
97
+ console.log(`Scaffolded: ${opts.targetDir}`);
98
+ console.log("Next steps:");
99
+ console.log(` 1. cd ${opts.targetDir}`);
100
+ console.log(` 2. Edit lib/report-data.ts (metadata) and app/page.tsx (layout)`);
101
+ console.log(` 3. Live preview: bun run dev`);
102
+ console.log(
103
+ ` 4. Generate PDF: node --experimental-strip-types ~/.pal/skills/consulting-report/tools/generate-pdf.ts ${opts.targetDir}`
104
+ );
105
+ }
65
106
 
66
- console.log(`Scaffolded: ${targetDir}`);
67
- console.log("Next steps:");
68
- console.log(` 1. Edit ${join(targetDir, "content", "report-data.ts")}`);
69
- console.log(` 2. Fill ${join(targetDir, "content")} with your section markdown files`);
70
- console.log(` 3. Drop images into ${join(targetDir, "diagrams")}`);
71
- console.log(` 4. Render:`);
72
- console.log(
73
- ` node --experimental-strip-types ~/.pal/skills/consulting-report/tools/generate-pdf.ts ${targetDir}`
74
- );
107
+ if (import.meta.main) {
108
+ await run();
109
+ }
@@ -32,7 +32,7 @@ bun ~/.pal/skills/presentation/tools/setup-template.ts \
32
32
  --logo <abs-path-to-logo.svg> \
33
33
  --primary "#0E1335" \
34
34
  [--accent "#FFB84D"] \
35
- [--footer "Konvert7 · 2026"] \
35
+ [--footer "Your Brand · 2026"] \
36
36
  [--logo-placement "footer"] \
37
37
  [--fonts "system"] \
38
38
  [--aspect "16:9"] \
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "portable-agent-layer",
3
- "version": "0.30.1",
3
+ "version": "0.32.0",
4
4
  "description": "PAL — Portable Agent Layer: persistent personal context for AI coding assistants",
5
5
  "type": "module",
6
6
  "bin": {
@@ -61,8 +61,8 @@
61
61
  },
62
62
  "devDependencies": {
63
63
  "@biomejs/biome": "2.4.7",
64
- "@commitlint/cli": "^20.5.0",
65
- "@commitlint/config-conventional": "^20.5.0",
64
+ "@commitlint/cli": "^20.5.3",
65
+ "@commitlint/config-conventional": "^20.5.3",
66
66
  "@opencode-ai/plugin": "latest",
67
67
  "@semantic-release/changelog": "^6.0.3",
68
68
  "@semantic-release/git": "^10.0.1",
@@ -72,14 +72,14 @@
72
72
  "@types/node": "latest",
73
73
  "husky": "^9.1.7",
74
74
  "knip": "^6.9.0",
75
- "lint-staged": "^15.5.0",
75
+ "lint-staged": "^15.5.2",
76
76
  "semantic-release": "^25.0.3",
77
- "typescript": "^5.9.0"
77
+ "typescript": "^5.9.3"
78
78
  },
79
79
  "dependencies": {
80
- "@clack/prompts": "^1.1.0",
81
- "adm-zip": "^0.5.16",
82
- "marked": "^15.0.0",
83
- "playwright": "^1.49.0"
80
+ "@clack/prompts": "^1.3.0",
81
+ "adm-zip": "^0.5.17",
82
+ "marked": "^15.0.12",
83
+ "playwright": "^1.59.1"
84
84
  }
85
85
  }
@@ -1,33 +0,0 @@
1
- ## Production Deploy Pipeline
2
-
3
- The current pipeline is a linear GitHub Actions workflow: PR → staging → canary → production. There are health checks at each stage, and SLO-based gates block on red. What's missing is a rollback step: once traffic is shifted to a new version, reverting requires a manual re-deploy of the previous image, which in 4 out of the last 12 incidents required direct database work because schema migrations had already run.
4
-
5
- | Stage | Automated | Gate | Rollback |
6
- |-------|-----------|------|----------|
7
- | PR checks | Yes | Unit + integration tests | N/A |
8
- | Staging deploy | Yes | Smoke tests | One-click |
9
- | Canary (10%) | Yes | SLO compare 15m | Automatic |
10
- | Production | Yes | Manual approve | **Manual, untested** |
11
-
12
- > The "Manual, untested" cell is the single largest finding in this report.
13
-
14
- ## On-Call Practice
15
-
16
- The team runs a weekly rotation. In practice, three engineers cover most of the load:
17
-
18
- - Engineer A — 28% of minutes
19
- - Engineer B — 24%
20
- - Engineer C — 19%
21
- - Remaining 8 engineers split the other 29%
22
-
23
- The organization's own runbook requires a shadow-rotation before any solo shift. In the last two quarters, zero new engineers completed it.
24
-
25
- ## Runbook Inventory
26
-
27
- Of 14 tier-1 services:
28
-
29
- - **Fresh** (reviewed within 6 months): 5
30
- - **Aging** (6–18 months): 2
31
- - **Stale** (18+ months): 7
32
-
33
- Three of the stale services have been re-architected since their last runbook update.
@@ -1,19 +0,0 @@
1
- ## Context
2
-
3
- Acme Industries asked for an independent read on whether their engineering operations are ready to support the 3× revenue growth planned over the next 18 months. The assessment ran for six weeks and covered tier-1 production services, on-call practice, and incident response.
4
-
5
- ## Key Findings
6
-
7
- - Production deploys lack a tested rollback path — the single largest operational risk.
8
- - Runbooks are stale across half of tier-1 services.
9
- - On-call coverage is concentrated in three engineers; knowledge has not diffused.
10
-
11
- ## Primary Recommendations
12
-
13
- 1. Add a rollback gate to the deploy pipeline within four weeks.
14
- 2. Refresh all tier-1 runbooks in a dedicated Q3 sprint.
15
- 3. Broaden the on-call roster from three to eight engineers over the next six months.
16
-
17
- ## Scope & Method
18
-
19
- In scope: engineering operations — deploy, on-call, incident response, service ownership. Out of scope: product, sales, finance processes, though they surfaced repeatedly. Five semi-structured interviews; 12 incident post-mortems reviewed; 90 days of on-call coverage logs analyzed.
@@ -1,101 +0,0 @@
1
- import type { ConsultingReport } from "../../tools/generate-pdf";
2
-
3
- const report: ConsultingReport = {
4
- clientName: "Acme Industries",
5
- reportTitle: "Operational Readiness Assessment",
6
- reportDate: "2026-04-21",
7
- classification: "CONFIDENTIAL",
8
- version: "1.0",
9
-
10
- // No brand block — uses the Konvert7 default.
11
-
12
- sections: [
13
- {
14
- id: "executive-summary",
15
- title: "Executive Summary",
16
- content: "executive-summary.md",
17
- },
18
- {
19
- id: "current-state",
20
- title: "Current State",
21
- content: "current-state.md",
22
- },
23
- ],
24
-
25
- findings: [
26
- {
27
- id: "f-01",
28
- title: "Release pipeline lacks a rollback path",
29
- severity: "critical",
30
- evidence:
31
- "Production deploys are one-way: the pipeline lacks a tested rollback step. Of the last 12 incidents, 4 required manual database surgery because the deploy couldn't be reverted.",
32
- impact:
33
- "Mean time to recovery is 3× peer benchmarks, and engineers report avoiding late-week deploys — slowing feature delivery.",
34
- },
35
- {
36
- id: "f-02",
37
- title: "Runbooks are out of date across half the critical services",
38
- severity: "high",
39
- evidence:
40
- "7 of 14 tier-1 services have runbooks last updated more than 18 months ago. Three of those services have been re-architected since.",
41
- },
42
- {
43
- id: "f-03",
44
- title: "On-call rotation is concentrated in three engineers",
45
- severity: "medium",
46
- evidence:
47
- "Over the last quarter, three engineers covered 71% of the on-call minutes. The shadow-rotation system exists on paper but isn't enforced.",
48
- },
49
- ],
50
-
51
- recommendations: [
52
- {
53
- id: "r-01",
54
- title: "Add a tested rollback gate to the deploy pipeline",
55
- priority: "immediate",
56
- detail:
57
- "Before any production deploy, require a successful rollback dry-run in staging. Block the pipeline on red. Target: implemented within 4 weeks; validated monthly via chaos day.",
58
- owner: "Platform team",
59
- },
60
- {
61
- id: "r-02",
62
- title: "Runbook refresh sprint",
63
- priority: "short-term",
64
- detail:
65
- "Allocate one sprint in Q3 to refresh all tier-1 runbooks. Each owner writes a 10-minute 'what wakes me up at 3am' paragraph. Review as pair exercise with oncall.",
66
- owner: "Service owners + SRE",
67
- },
68
- {
69
- id: "r-03",
70
- title: "Broaden on-call to 8 engineers within 6 months",
71
- priority: "long-term",
72
- detail:
73
- "Rotate 2 new engineers through a 4-week shadow period each quarter. Gate solo rotation on a resolved-incident checklist, not tenure.",
74
- },
75
- ],
76
-
77
- conclusion: {
78
- assessorNote:
79
- "The team is competent and well-intentioned; the gaps are process, not ability. The critical finding around rollback is the single highest-leverage fix available.",
80
- contextNote:
81
- "This assessment was scoped to engineering operations. Product, sales, and finance processes were out of scope but came up repeatedly in interviews as related bottlenecks.",
82
- closingRemarks:
83
- "A 30-day follow-up is recommended after the rollback gate lands to verify MTTR trend.",
84
- },
85
-
86
- supportingEvidence: {
87
- Interviews: [
88
- "Head of Platform — 45m",
89
- "SRE Lead — 45m",
90
- "Three senior engineers — 30m each",
91
- "VP Engineering — 30m",
92
- ],
93
- "Documents reviewed": [
94
- "Q1 incident post-mortems (12)",
95
- "On-call schedule & coverage logs (90 days)",
96
- "Current runbook index",
97
- ],
98
- },
99
- };
100
-
101
- export default report;
@@ -1,28 +0,0 @@
1
- # Consulting Report — Working Directory
2
-
3
- ## Structure
4
-
5
- - `content/report-data.ts` — report structure (cover metadata, sections, optional findings / recommendations / conclusion / appendix)
6
- - `content/*.md` — narrative sections; reference them from `report-data.ts` by filename
7
- - `diagrams/` — drop PNG/JPG images; they're compressed to JPEG 70% / max 1200px at render time
8
- - `diagrams-compressed/` — generated; do not edit
9
-
10
- ## Render
11
-
12
- ```
13
- node --experimental-strip-types ~/.pal/skills/consulting-report/tools/generate-pdf.ts .
14
- ```
15
-
16
- Output goes into this directory as `<client>-<title>-<date>.{pdf,html}` unless you pass `--pdf <path>` or `--html <path>`.
17
-
18
- ## Defaults
19
-
20
- Without a `brand` block in `report-data.ts`, reports are stamped with **Konvert7** branding. Override per engagement by adding:
21
-
22
- ```ts
23
- brand: {
24
- businessName: "Your Brand",
25
- logoPath: "/absolute/path/to/logo.png", // optional — text-only cover if omitted
26
- brandLabel: "Strategic Assessment", // optional sub-label on cover
27
- }
28
- ```
@@ -1,19 +0,0 @@
1
- ## Context
2
-
3
- One-paragraph framing of the engagement: who the client is, what they asked for, what's at stake.
4
-
5
- ## Key Findings
6
-
7
- - Finding one — punchy, evidenced, and actionable.
8
- - Finding two.
9
- - Finding three.
10
-
11
- ## Primary Recommendations
12
-
13
- 1. Recommendation one — what to do, by when, and what it unblocks.
14
- 2. Recommendation two.
15
- 3. Recommendation three.
16
-
17
- ## Scope & Method
18
-
19
- Short note on what was reviewed, who was interviewed, what was explicitly out of scope.
@@ -1,59 +0,0 @@
1
- import type { ConsultingReport } from "{{TOOL_PATH}}";
2
-
3
- const report: ConsultingReport = {
4
- clientName: "{{CLIENT_NAME}}",
5
- reportTitle: "{{REPORT_TITLE}}",
6
- reportDate: "{{DATE}}",
7
- classification: "CONFIDENTIAL",
8
- version: "0.1",
9
-
10
- // Brand is optional — defaults to Konvert7. Override per report if needed:
11
- // brand: { businessName: "Konvert7", logoPath: "/absolute/path/to/logo.png", brandLabel: "Strategic Assessment" },
12
-
13
- sections: [
14
- {
15
- id: "executive-summary",
16
- title: "Executive Summary",
17
- content: "executive-summary.md",
18
- },
19
- // Add sections — each `content` is either an inline markdown string OR a
20
- // .md filename relative to this content/ directory.
21
- ],
22
-
23
- // Optional. Delete the block if unused.
24
- findings: [
25
- // {
26
- // id: "f-01",
27
- // title: "Example critical finding",
28
- // severity: "critical",
29
- // evidence: "What was observed, with specifics.",
30
- // impact: "Why it matters.",
31
- // },
32
- ],
33
-
34
- // Optional.
35
- recommendations: [
36
- // {
37
- // id: "r-01",
38
- // title: "Example recommendation",
39
- // priority: "immediate",
40
- // detail: "What to do, by when, and why.",
41
- // owner: "Team or person",
42
- // },
43
- ],
44
-
45
- // Optional.
46
- conclusion: {
47
- // assessorNote: "Personal assessor voice.",
48
- // contextNote: "Situational context the reader needs.",
49
- // closingRemarks: "Where to go next.",
50
- },
51
-
52
- // Optional. Appendix — keyed by heading, each value is a list of bullets.
53
- // supportingEvidence: {
54
- // "Interviews": ["Person A — 45m", "Person B — 30m"],
55
- // "Documents reviewed": ["doc-1.pdf", "doc-2.md"],
56
- // },
57
- };
58
-
59
- export default report;