portable-agent-layer 0.30.1 → 0.31.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 (52) hide show
  1. package/assets/skills/consulting-report/SKILL.md +68 -74
  2. package/assets/skills/consulting-report/demo/app/globals.css +344 -0
  3. package/assets/skills/consulting-report/demo/app/layout.tsx +32 -0
  4. package/assets/skills/consulting-report/demo/app/page.tsx +255 -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/cover-page.tsx +34 -0
  8. package/assets/skills/consulting-report/demo/components/exhibit.tsx +21 -0
  9. package/assets/skills/consulting-report/demo/components/finding-card.tsx +28 -0
  10. package/assets/skills/consulting-report/demo/components/quote-block.tsx +17 -0
  11. package/assets/skills/consulting-report/demo/components/recommendation-card.tsx +52 -0
  12. package/assets/skills/consulting-report/demo/components/section.tsx +16 -0
  13. package/assets/skills/consulting-report/demo/components/severity-badge.tsx +19 -0
  14. package/assets/skills/consulting-report/demo/components/timeline.tsx +20 -0
  15. package/assets/skills/consulting-report/demo/lib/report-data.ts +247 -0
  16. package/assets/skills/consulting-report/demo/lib/utils.ts +6 -0
  17. package/assets/skills/consulting-report/demo/next.config.js +9 -0
  18. package/assets/skills/consulting-report/demo/package.json +27 -0
  19. package/assets/skills/consulting-report/demo/postcss.config.mjs +5 -0
  20. package/assets/skills/consulting-report/demo/tsconfig.json +41 -0
  21. package/assets/skills/consulting-report/template/app/globals.css +344 -0
  22. package/assets/skills/consulting-report/template/app/layout.tsx +32 -0
  23. package/assets/skills/consulting-report/template/app/page.tsx +255 -0
  24. package/assets/skills/consulting-report/template/bun.lock +240 -0
  25. package/assets/skills/consulting-report/template/components/callout.tsx +13 -0
  26. package/assets/skills/consulting-report/template/components/cover-page.tsx +34 -0
  27. package/assets/skills/consulting-report/template/components/exhibit.tsx +21 -0
  28. package/assets/skills/consulting-report/template/components/finding-card.tsx +28 -0
  29. package/assets/skills/consulting-report/template/components/quote-block.tsx +17 -0
  30. package/assets/skills/consulting-report/template/components/recommendation-card.tsx +52 -0
  31. package/assets/skills/consulting-report/template/components/section.tsx +16 -0
  32. package/assets/skills/consulting-report/template/components/severity-badge.tsx +19 -0
  33. package/assets/skills/consulting-report/template/components/timeline.tsx +20 -0
  34. package/assets/skills/consulting-report/template/lib/report-data.ts +176 -0
  35. package/assets/skills/consulting-report/template/lib/utils.ts +6 -0
  36. package/assets/skills/consulting-report/template/next.config.js +9 -0
  37. package/assets/skills/consulting-report/template/package.json +27 -0
  38. package/assets/skills/consulting-report/template/postcss.config.mjs +5 -0
  39. package/assets/skills/consulting-report/template/tsconfig.json +27 -0
  40. package/assets/skills/consulting-report/tools/dev.ts +47 -0
  41. package/assets/skills/consulting-report/tools/generate-pdf.ts +140 -408
  42. package/assets/skills/consulting-report/tools/scaffold.ts +83 -48
  43. package/assets/skills/presentation/SKILL.md +1 -1
  44. package/package.json +9 -9
  45. package/assets/skills/consulting-report/demo/content/current-state.md +0 -33
  46. package/assets/skills/consulting-report/demo/content/executive-summary.md +0 -19
  47. package/assets/skills/consulting-report/demo/content/report-data.ts +0 -101
  48. package/assets/skills/consulting-report/demo/diagrams/.gitkeep +0 -0
  49. package/assets/skills/consulting-report/template/README.md +0 -28
  50. package/assets/skills/consulting-report/template/content/executive-summary.md +0 -19
  51. package/assets/skills/consulting-report/template/content/report-data.ts +0 -59
  52. package/assets/skills/consulting-report/template/diagrams/.gitkeep +0 -0
@@ -0,0 +1,17 @@
1
+ interface QuoteBlockProps {
2
+ quote: string;
3
+ attribution: string;
4
+ role?: string;
5
+ }
6
+
7
+ export function QuoteBlock({ quote, attribution, role }: QuoteBlockProps) {
8
+ return (
9
+ <div className="quote-block">
10
+ <p className="quote-text">{quote}</p>
11
+ <p className="quote-attribution">
12
+ — {attribution}
13
+ {role && <span className="text-muted">, {role}</span>}
14
+ </p>
15
+ </div>
16
+ );
17
+ }
@@ -0,0 +1,52 @@
1
+ import { ArrowRight, Clock, Zap } from "lucide-react";
2
+ import type { Recommendation } from "@/lib/report-data";
3
+ import { cn } from "@/lib/utils";
4
+
5
+ interface RecommendationCardProps {
6
+ recommendation: Recommendation;
7
+ index: number;
8
+ }
9
+
10
+ const priorityConfig = {
11
+ immediate: {
12
+ icon: Zap,
13
+ label: "Immediate",
14
+ className: "bg-destructive/10 text-destructive border-destructive/20",
15
+ },
16
+ "short-term": {
17
+ icon: Clock,
18
+ label: "Short-term",
19
+ className: "bg-warning/10 text-warning border-warning/20",
20
+ },
21
+ "long-term": {
22
+ icon: ArrowRight,
23
+ label: "Long-term",
24
+ className: "bg-primary/10 text-primary border-primary/20",
25
+ },
26
+ } as const;
27
+
28
+ export function RecommendationCard({ recommendation, index }: RecommendationCardProps) {
29
+ const config = priorityConfig[recommendation.priority];
30
+ const Icon = config.icon;
31
+
32
+ return (
33
+ <div className="finding-card">
34
+ <div className="finding-header">
35
+ <div className="flex items-start gap-3">
36
+ <span className="text-primary font-bold font-sans text-lg">{index + 1}</span>
37
+ <span className="finding-title">{recommendation.title}</span>
38
+ </div>
39
+ <span
40
+ className={cn(
41
+ "inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-semibold border",
42
+ config.className
43
+ )}
44
+ >
45
+ <Icon className="h-3 w-3" />
46
+ {config.label}
47
+ </span>
48
+ </div>
49
+ <p className="text-foreground ml-8">{recommendation.description}</p>
50
+ </div>
51
+ );
52
+ }
@@ -0,0 +1,16 @@
1
+ import { cn } from "@/lib/utils";
2
+
3
+ interface SectionProps {
4
+ title: string;
5
+ children: React.ReactNode;
6
+ className?: string;
7
+ }
8
+
9
+ export function Section({ title, children, className }: SectionProps) {
10
+ return (
11
+ <section className={cn("report-section", className)}>
12
+ <h2>{title}</h2>
13
+ {children}
14
+ </section>
15
+ );
16
+ }
@@ -0,0 +1,19 @@
1
+ import { cn } from "@/lib/utils";
2
+
3
+ type Severity = "critical" | "high" | "medium" | "low";
4
+
5
+ interface SeverityBadgeProps {
6
+ severity: Severity;
7
+ }
8
+
9
+ const severityConfig: Record<Severity, { label: string; className: string }> = {
10
+ critical: { label: "Critical", className: "severity-critical" },
11
+ high: { label: "High", className: "severity-high" },
12
+ medium: { label: "Medium", className: "severity-medium" },
13
+ low: { label: "Low", className: "severity-low" },
14
+ };
15
+
16
+ export function SeverityBadge({ severity }: SeverityBadgeProps) {
17
+ const config = severityConfig[severity];
18
+ return <span className={cn("severity-badge", config.className)}>{config.label}</span>;
19
+ }
@@ -0,0 +1,20 @@
1
+ import type { TimelinePhase } from "@/lib/report-data";
2
+
3
+ interface TimelineProps {
4
+ phases: TimelinePhase[];
5
+ }
6
+
7
+ export function Timeline({ phases }: TimelineProps) {
8
+ return (
9
+ <div className="timeline">
10
+ {phases.map((phase) => (
11
+ <div key={`${phase.phase}-${phase.title}`} className="timeline-item">
12
+ <div className="timeline-phase">{phase.phase}</div>
13
+ <div className="timeline-title">{phase.title}</div>
14
+ <div className="timeline-description">{phase.description}</div>
15
+ <div className="text-xs text-primary font-medium mt-1">{phase.duration}</div>
16
+ </div>
17
+ ))}
18
+ </div>
19
+ );
20
+ }
@@ -0,0 +1,247 @@
1
+ export interface Finding {
2
+ id: string;
3
+ title: string;
4
+ description: string;
5
+ evidence: string;
6
+ source: string;
7
+ severity: "critical" | "high" | "medium" | "low";
8
+ }
9
+
10
+ export interface Recommendation {
11
+ id: string;
12
+ title: string;
13
+ description: string;
14
+ priority: "immediate" | "short-term" | "long-term";
15
+ }
16
+
17
+ export interface TimelinePhase {
18
+ phase: string;
19
+ title: string;
20
+ description: string;
21
+ duration: string;
22
+ }
23
+
24
+ export interface ReportData {
25
+ clientName: string;
26
+ reportTitle: string;
27
+ reportDate: string;
28
+ classification: string;
29
+ consultancyName: string;
30
+ preTitle?: string;
31
+
32
+ executiveSummary: {
33
+ context: string;
34
+ methodology: { interviewCount: number; roles: string[] };
35
+ keyFindings: string[];
36
+ primaryRecommendation: string;
37
+ expectedOutcomes: string[];
38
+ };
39
+
40
+ situationAssessment: {
41
+ currentState: string;
42
+ clientAsk: string;
43
+ whyNow: string;
44
+ };
45
+
46
+ findings: Finding[];
47
+
48
+ riskAnalysis: {
49
+ existentialRisks: string[];
50
+ competitiveThreats: string[];
51
+ timelinePressures: string;
52
+ };
53
+
54
+ strategicOpportunity: {
55
+ goodNews: string;
56
+ requirements: string[];
57
+ };
58
+
59
+ recommendations: Recommendation[];
60
+
61
+ targetState: {
62
+ description: string;
63
+ keyCapabilities: string[];
64
+ successMetrics: string[];
65
+ };
66
+
67
+ roadmap: TimelinePhase[];
68
+
69
+ callToAction: {
70
+ immediateSteps: string[];
71
+ decisionPoints: string[];
72
+ commitmentRequired: string;
73
+ };
74
+ }
75
+
76
+ export const reportData: ReportData = {
77
+ clientName: "Acme Industries",
78
+ reportTitle: "Operational Readiness Assessment",
79
+ reportDate: "April 21, 2026",
80
+ classification: "CONFIDENTIAL",
81
+ consultancyName: "Northbridge Advisory",
82
+ preTitle: "Operational Assessment",
83
+
84
+ executiveSummary: {
85
+ context:
86
+ "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.",
87
+ methodology: {
88
+ interviewCount: 5,
89
+ roles: ["Head of Platform", "SRE Lead", "Senior Engineers (3)", "VP Engineering"],
90
+ },
91
+ keyFindings: [
92
+ "Production deploys lack a tested rollback path — the single largest operational risk.",
93
+ "Runbooks are stale across half of tier-1 services.",
94
+ "On-call coverage is concentrated in three engineers; knowledge has not diffused.",
95
+ ],
96
+ primaryRecommendation:
97
+ "Add a tested rollback gate to the production deploy pipeline within four weeks. It is the single highest-leverage operational fix available and unblocks the rest of the readiness work.",
98
+ expectedOutcomes: [
99
+ "Mean time to recovery within 1.5× peer benchmark by end of Q3",
100
+ "Zero production deploys without a successful rollback dry-run in staging",
101
+ "On-call coverage spread across 8 engineers within six months",
102
+ ],
103
+ },
104
+
105
+ situationAssessment: {
106
+ clientAsk:
107
+ "An independent read on whether engineering operations are ready to support the planned 3× revenue ramp over the next 18 months.",
108
+ currentState:
109
+ "Engineering operations are competent but carry three structural gaps: an untested rollback path in production, stale runbooks across half of tier-1 services, and dangerous concentration of on-call coverage in three engineers. MTTR is currently running at 3× peer benchmarks.",
110
+ whyNow:
111
+ "The 3× revenue ramp begins in Q3 2026 and pulls forward operational scale that today's processes cannot absorb. Each gap that goes into Q3 unaddressed compounds under load — the cost of remediation rises sharply once growth begins.",
112
+ },
113
+
114
+ findings: [
115
+ {
116
+ id: "F1",
117
+ title: "Release pipeline lacks a rollback path",
118
+ description:
119
+ "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.",
120
+ evidence:
121
+ "Mean time to recovery is 3× peer benchmarks, and engineers report avoiding late-week deploys — slowing feature delivery.",
122
+ source: "Pipeline review + Q1 incident post-mortems (12)",
123
+ severity: "critical",
124
+ },
125
+ {
126
+ id: "F2",
127
+ title: "Runbooks are out of date across half the critical services",
128
+ description:
129
+ "7 of 14 tier-1 services have runbooks last updated more than 18 months ago. Three of those services have been re-architected since.",
130
+ evidence:
131
+ "Runbook inventory: 5 fresh (≤6 months), 2 aging (6–18 months), 7 stale (>18 months).",
132
+ source: "Runbook inventory audit",
133
+ severity: "high",
134
+ },
135
+ {
136
+ id: "F3",
137
+ title: "On-call rotation is concentrated in three engineers",
138
+ description:
139
+ "Over the last quarter, three engineers covered 71% of the on-call minutes. The shadow-rotation system exists on paper but is not enforced.",
140
+ evidence:
141
+ "Engineer A: 28%, Engineer B: 24%, Engineer C: 19%. Remaining 8 engineers split 29%. Zero shadow rotations completed in the last two quarters.",
142
+ source: "On-call coverage logs (90 days)",
143
+ severity: "medium",
144
+ },
145
+ ],
146
+
147
+ riskAnalysis: {
148
+ existentialRisks: [
149
+ "Production deploys with no rollback path during the growth ramp — a single bad deploy at peak load could require live database surgery during the busiest hour.",
150
+ "Knowledge concentration in three engineers means a single departure or unavailability event compromises incident response across half the platform.",
151
+ ],
152
+ competitiveThreats: [
153
+ "MTTR running at 3× peer benchmarks materially limits feature velocity at exactly the moment competitors are accelerating.",
154
+ "Engineers self-report avoiding late-week deploys; growth requires the opposite — confidence to deploy at any time.",
155
+ ],
156
+ timelinePressures:
157
+ "The Q3 2026 ramp begins in roughly three months. Operational fixes that take a sprint today take a quarter once the team is also absorbing 3× load.",
158
+ },
159
+
160
+ strategicOpportunity: {
161
+ goodNews:
162
+ "All three findings are process gaps, not capability gaps. The team is competent and well-intentioned — the fixes don't require new hires, only sequencing and leadership commitment.",
163
+ requirements: [
164
+ "Treat the rollback gate as a P0 platform initiative, not a sprint task",
165
+ "Create a cross-team runbook refresh ritual that doesn't depend on individual heroics",
166
+ "Make on-call rotation breadth a leadership-tracked KPI",
167
+ ],
168
+ },
169
+
170
+ recommendations: [
171
+ {
172
+ id: "R1",
173
+ title: "Add a tested rollback gate to the deploy pipeline",
174
+ description:
175
+ "Before any production deploy, require a successful rollback dry-run in staging. Block the pipeline on red. Validate monthly via chaos day. Owner: Platform team. Target: implemented within 4 weeks.",
176
+ priority: "immediate",
177
+ },
178
+ {
179
+ id: "R2",
180
+ title: "Runbook refresh sprint",
181
+ description:
182
+ "Allocate one sprint in Q3 to refresh all tier-1 runbooks. Each owner writes a 10-minute 'what wakes me up at 3am' paragraph. Reviewed as pair exercise with on-call. Owner: Service owners + SRE.",
183
+ priority: "short-term",
184
+ },
185
+ {
186
+ id: "R3",
187
+ title: "Broaden on-call to 8 engineers within 6 months",
188
+ description:
189
+ "Rotate 2 new engineers through a 4-week shadow period each quarter. Gate solo rotation on a resolved-incident checklist, not tenure.",
190
+ priority: "long-term",
191
+ },
192
+ ],
193
+
194
+ targetState: {
195
+ description:
196
+ "Engineering operations that can absorb 3× load without operator heroics — every tier-1 service has a fresh runbook, every production deploy has a tested rollback, and on-call is a shared discipline rather than a three-person tax.",
197
+ keyCapabilities: [
198
+ "Single-command rollback validated monthly",
199
+ "Tier-1 runbook freshness as a service-owner KPI",
200
+ "8-engineer on-call rotation with a tracked shadow program",
201
+ ],
202
+ successMetrics: [
203
+ "MTTR within 1.5× peer benchmark",
204
+ "Zero deploys without successful rollback dry-run in staging",
205
+ "No engineer carries more than 15% of monthly on-call minutes",
206
+ ],
207
+ },
208
+
209
+ roadmap: [
210
+ {
211
+ phase: "Phase 1",
212
+ title: "Rollback Gate",
213
+ description:
214
+ "Implement and validate the tested rollback step in the production pipeline. Block deploys that haven't passed the rollback dry-run.",
215
+ duration: "Weeks 1-4",
216
+ },
217
+ {
218
+ phase: "Phase 2",
219
+ title: "Runbook Refresh",
220
+ description:
221
+ "Q3 dedicated sprint refreshing all tier-1 runbooks with current architecture and on-call pair review.",
222
+ duration: "Weeks 5-12",
223
+ },
224
+ {
225
+ phase: "Phase 3",
226
+ title: "On-Call Broadening",
227
+ description:
228
+ "Run two cohorts of shadow rotations; reach 8-engineer coverage with tracked solo-readiness checklist.",
229
+ duration: "Weeks 13-26",
230
+ },
231
+ ],
232
+
233
+ callToAction: {
234
+ immediateSteps: [
235
+ "Approve P0 status for the rollback gate initiative",
236
+ "Block the first runbook refresh sprint slot in Q3",
237
+ "Identify the five engineers entering shadow rotation in Q3",
238
+ ],
239
+ decisionPoints: [
240
+ "Approve dedicated platform-team capacity for the rollback gate",
241
+ "Approve sprint allocation for the Q3 runbook refresh",
242
+ "Approve the on-call expansion target of 8 engineers",
243
+ ],
244
+ commitmentRequired:
245
+ "Treat operational readiness as a leadership priority through Q4. Without sustained executive attention, the rollback gate ships and then drifts; the runbook refresh becomes one-time. The discipline must be visible from the top.",
246
+ },
247
+ };
@@ -0,0 +1,6 @@
1
+ import { type ClassValue, clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
@@ -0,0 +1,9 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ output: "export",
4
+ images: { unoptimized: true },
5
+ trailingSlash: true,
6
+ turbopack: { root: __dirname },
7
+ };
8
+
9
+ module.exports = nextConfig;
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "consulting-report",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "lint": "next lint"
9
+ },
10
+ "dependencies": {
11
+ "next": "16.2.4",
12
+ "react": "19.2.5",
13
+ "react-dom": "19.2.5",
14
+ "lucide-react": "1.14.0",
15
+ "clsx": "2.1.1",
16
+ "tailwind-merge": "3.5.0"
17
+ },
18
+ "devDependencies": {
19
+ "@tailwindcss/postcss": "4.2.4",
20
+ "@types/node": "25.6.0",
21
+ "@types/react": "19.2.14",
22
+ "@types/react-dom": "19.2.3",
23
+ "postcss": "8.5.13",
24
+ "tailwindcss": "4.2.4",
25
+ "typescript": "6.0.3"
26
+ }
27
+ }
@@ -0,0 +1,5 @@
1
+ export default {
2
+ plugins: {
3
+ "@tailwindcss/postcss": {},
4
+ },
5
+ };
@@ -0,0 +1,41 @@
1
+ {
2
+ "compilerOptions": {
3
+ "lib": [
4
+ "dom",
5
+ "dom.iterable",
6
+ "esnext"
7
+ ],
8
+ "allowJs": true,
9
+ "skipLibCheck": true,
10
+ "strict": true,
11
+ "noEmit": true,
12
+ "esModuleInterop": true,
13
+ "module": "esnext",
14
+ "moduleResolution": "bundler",
15
+ "resolveJsonModule": true,
16
+ "isolatedModules": true,
17
+ "jsx": "react-jsx",
18
+ "incremental": true,
19
+ "plugins": [
20
+ {
21
+ "name": "next"
22
+ }
23
+ ],
24
+ "paths": {
25
+ "@/*": [
26
+ "./*"
27
+ ]
28
+ },
29
+ "target": "ES2017"
30
+ },
31
+ "include": [
32
+ "next-env.d.ts",
33
+ "**/*.ts",
34
+ "**/*.tsx",
35
+ ".next/types/**/*.ts",
36
+ ".next/dev/types/**/*.ts"
37
+ ],
38
+ "exclude": [
39
+ "node_modules"
40
+ ]
41
+ }