github-portfolio-analyzer 1.1.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 ADDED
@@ -0,0 +1,26 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [Unreleased]
6
+
7
+ ### Added
8
+ - Colored terminal output — progress, success, warning, and error states with ANSI colors
9
+ - Terminal header with ASCII art, version info, user, token status, and policy status
10
+ - Per-repository progress logging during `analyze` (Analyzing N/total: repo-name)
11
+ - Elapsed time in analyze completion summary
12
+ - Fallback count in analyze summary when structural inspection fails
13
+ - Fatal error messages for missing token, auth failure, and rate limit
14
+
15
+ ## [1.0.0] — 2026-03-31
16
+
17
+ ### Added
18
+ - Initial public release
19
+ - `analyze` command: fetch and score GitHub repositories into inventory outputs
20
+ - `ingest-ideas` command: normalize and score project ideas from JSON input
21
+ - `build-portfolio` command: merge repos and ideas into unified portfolio artifacts
22
+ - `report` command: generate decision-oriented reports (JSON, Markdown, ASCII)
23
+ - `--version` flag
24
+ - `--quiet`, `--strict`, `--explain`, `--format`, `--policy`, `--output-dir` flags
25
+ - JSON Schema for `portfolio-report.json` at `schemas/portfolio-report.schema.json`
26
+ - `analyzer.manifest.json` integration contract for external orchestrators
package/README.md ADDED
@@ -0,0 +1,686 @@
1
+ # github-portfolio-analyzer
2
+
3
+ [![npm version](https://img.shields.io/npm/v/github-portfolio-analyzer.svg)](https://www.npmjs.com/package/github-portfolio-analyzer)
4
+ [![node](https://img.shields.io/node/v/github-portfolio-analyzer.svg)](https://nodejs.org)
5
+ [![license](https://img.shields.io/npm/l/github-portfolio-analyzer.svg)](./LICENSE)
6
+ [![npm downloads](https://img.shields.io/npm/dm/github-portfolio-analyzer.svg)](https://www.npmjs.com/package/github-portfolio-analyzer)
7
+
8
+ Build a decision-ready developer portfolio from real GitHub repositories and planned ideas in one deterministic CLI workflow.
9
+ This project turns raw repository metadata into actionable prioritization outputs for execution planning.
10
+
11
+ ---
12
+ **Tagline:** From repository inventory to execution decisions in minutes.
13
+
14
+ ```
15
+ ◉──●──●──●──◉
16
+ \ /
17
+ ◉──◉
18
+
19
+ now ████ ↑↑↑
20
+ next ███░ ↑↑
21
+ later█░░░ ↑
22
+
23
+ ✓ report.json
24
+ ```
25
+
26
+ **What this does:** you run one command. It reads all your GitHub repositories,
27
+ scores and prioritizes them, and writes a structured JSON report ready to feed
28
+ your portfolio site — automatically, without manual curation.
29
+
30
+ ## Flow Overview
31
+
32
+ ```mermaid
33
+ flowchart TD
34
+ A[analyze] --> I[output/inventory.json]
35
+ A --> IC[output/inventory.csv]
36
+ B[ingest-ideas] --> IJ[output/ideas.json]
37
+ I --> C[build-portfolio]
38
+ IJ --> C
39
+ C --> P[output/portfolio.json]
40
+ D[report] --> R[output/portfolio-report.json]
41
+ D --> RM[output/portfolio-report.md]
42
+ D --> RT[output/portfolio-report.txt]
43
+ POL[priorities/policy.json] --> D
44
+ D -->|--format json --quiet| STDOUT[(stdout JSON)]
45
+ ```
46
+
47
+ ## Table of Contents
48
+
49
+ - [Flow Overview](#flow-overview)
50
+ - [Why This Tool Exists](#why-this-tool-exists)
51
+ - [Project Overview](#project-overview)
52
+ - [Installation](#installation)
53
+ - [Quick Start](#quick-start)
54
+ - [CLI Commands](#cli-commands)
55
+ - [CLI Flags](#cli-flags)
56
+ - [Required and Optional Inputs](#required-and-optional-inputs)
57
+ - [Output Artifacts](#output-artifacts)
58
+ - [End-to-End Example](#end-to-end-example)
59
+ - [Machine Integration](#machine-integration)
60
+ - [3-Minute Quickstart](#3-minute-quickstart)
61
+ - [End-to-End Tutorial](#end-to-end-tutorial)
62
+ - [Command Reference](#command-reference)
63
+ - [Integration Contract](#integration-contract)
64
+ - [Exit Codes](#exit-codes)
65
+ - [Optional Policy Overlay and Explain Mode](#optional-policy-overlay-and-explain-mode)
66
+ - [Output Directory Map](#output-directory-map)
67
+ - [Data Contracts](#data-contracts)
68
+ - [Decision Model (Report)](#decision-model-report)
69
+ - [Determinism and Time Rules](#determinism-and-time-rules)
70
+ - [nextAction Validation](#nextaction-validation)
71
+ - [Architecture](#architecture)
72
+ - [Testing and Quality](#testing-and-quality)
73
+ - [Troubleshooting](#troubleshooting)
74
+ - [License and Contribution](#license-and-contribution)
75
+
76
+ ## Documentation
77
+
78
+ - [Agent Guide](AGENT_GUIDE.md)
79
+ - [Integration Guide](docs/INTEGRATION.md)
80
+ - [Analyzer Manifest](analyzer.manifest.json)
81
+ - [Portfolio Report Schema](schemas/portfolio-report.schema.json)
82
+
83
+ ## Why This Tool Exists
84
+
85
+ Most portfolios are incomplete: repositories are analyzed, but pending ideas live in notes and never enter prioritization.
86
+ `github-portfolio-analyzer` unifies both streams and emits stable artifacts for reporting, planning, and backlog strategy.
87
+
88
+ ## Project Overview
89
+
90
+ `github-portfolio-analyzer` is a deterministic CLI that analyzes GitHub repositories and project ideas, then produces portfolio and decision-report artifacts for execution planning.
91
+
92
+ Design goals:
93
+
94
+ - deterministic outputs for the same inputs
95
+ - explainable ranking and priority signals
96
+ - tool-agnostic artifacts (JSON, Markdown, ASCII)
97
+ - orchestration-friendly CLI behavior for scripts, agents, and CI
98
+
99
+ ## Installation
100
+
101
+ Install dependencies and run the CLI locally:
102
+
103
+ ```bash
104
+ npm install
105
+ github-portfolio-analyzer --version
106
+ ```
107
+
108
+ If the global binary is not available yet, use:
109
+
110
+ ```bash
111
+ node bin/github-portfolio-analyzer.js --version
112
+ ```
113
+
114
+ ## Quick Start
115
+
116
+ Minimal workflow:
117
+
118
+ ```bash
119
+ github-portfolio-analyzer analyze
120
+ github-portfolio-analyzer ingest-ideas
121
+ github-portfolio-analyzer build-portfolio
122
+ github-portfolio-analyzer report
123
+ ```
124
+
125
+ What each step does:
126
+
127
+ - `analyze`: pulls repository metadata from GitHub API and writes inventory artifacts
128
+ - `ingest-ideas`: normalizes/scoring ideas into `ideas.json`
129
+ - `build-portfolio`: merges repositories and ideas into portfolio artifacts
130
+ - `report`: creates decision-oriented report artifacts (JSON/MD/TXT)
131
+
132
+ ## CLI Commands
133
+
134
+ - `analyze`: fetch and score GitHub repositories into inventory outputs
135
+ - `ingest-ideas`: ingest idea records from JSON or interactive prompt
136
+ - `build-portfolio`: merge repository inventory and ideas into unified portfolio outputs
137
+ - `report`: generate decision reports from portfolio artifacts
138
+
139
+ ## CLI Flags
140
+
141
+ - `--version`: print CLI version only
142
+ - `--policy <path>`: apply optional policy overlay when generating reports
143
+ - `--explain`: print NOW-band ranking explanation to console
144
+ - `--output <dir>`: report-only output directory override for report artifacts
145
+ - `--format json`: emit report JSON to stdout (artifacts are still written)
146
+ - `--quiet`: suppress non-error logs
147
+ - `--strict`: fail on unknown flags and invalid usage with exit code `2`
148
+
149
+ ## Required and Optional Inputs
150
+
151
+ Required inputs depend on the command path:
152
+
153
+ - For `analyze`: `.env` with `GITHUB_TOKEN` (and usually `GITHUB_USERNAME`)
154
+ - For `report`: `output/portfolio.json` must exist
155
+
156
+ Optional inputs:
157
+
158
+ - `ideas/input.json` (or custom path via `ingest-ideas --input`)
159
+ - `priorities/policy.json` for manual priority overlays in `report`
160
+ - `--as-of YYYY-MM-DD` for deterministic snapshot control during `analyze`
161
+
162
+ Create a local policy file:
163
+
164
+ ```bash
165
+ cp priorities/policy.example.json priorities/policy.json
166
+ ```
167
+
168
+ `priorities/policy.json` is local and git-ignored by design.
169
+
170
+ ## Output Artifacts
171
+
172
+ Primary artifacts:
173
+
174
+ - `output/inventory.json`
175
+ - `output/portfolio.json`
176
+ - `output/portfolio-report.json`
177
+ - `output/portfolio-report.md`
178
+ - `output/portfolio-report.txt`
179
+
180
+ Output directory control:
181
+
182
+ - `report --output <dir>` writes report artifacts to a custom directory
183
+ - Pipeline commands also support `--output-dir <dir>` for their output roots
184
+
185
+ ## End-to-End Example
186
+
187
+ ```bash
188
+ github-portfolio-analyzer analyze --as-of 2026-03-03
189
+ github-portfolio-analyzer ingest-ideas --input ./ideas/input.json
190
+ github-portfolio-analyzer build-portfolio
191
+ github-portfolio-analyzer report --format json
192
+ ```
193
+
194
+ After this run, you should have (in `output/` by default):
195
+
196
+ - `inventory.json` and `inventory.csv`
197
+ - `ideas.json`
198
+ - `portfolio.json` and `portfolio-summary.md`
199
+ - `portfolio-report.json`, `portfolio-report.md`, `portfolio-report.txt`
200
+
201
+ ## Machine Integration
202
+
203
+ Use this CLI from scripts, CI jobs, or agent runtimes with deterministic artifacts and predictable exit codes.
204
+
205
+ Programmatic JSON via stdout:
206
+
207
+ ```bash
208
+ github-portfolio-analyzer report --format json --quiet
209
+ ```
210
+
211
+ Custom report output directory:
212
+
213
+ ```bash
214
+ github-portfolio-analyzer report --output ./runs/run-001
215
+ ```
216
+
217
+ `--format json --quiet` is recommended for machine consumers because stdout contains only JSON unless an error occurs.
218
+ See [Integration Contract](#integration-contract) and the dedicated [Integration Guide](docs/INTEGRATION.md).
219
+
220
+ ## 3-Minute Quickstart
221
+
222
+ ### 1) Requirements
223
+
224
+ - Node.js `22+`
225
+ - GitHub Personal Access Token (PAT) for `analyze`
226
+
227
+ ### 2) Create a GitHub PAT (short version)
228
+
229
+ Create a token in GitHub settings and store it in `.env`.
230
+ Use the minimum read permissions needed to list repos and inspect repository files/workflows:
231
+
232
+ - **Fine-grained token:** repository `Metadata: Read`, `Contents: Read`, `Actions: Read`
233
+ - **Classic token (fallback):** `repo` scope (read usage by this CLI)
234
+
235
+ ### 3) Install and configure
236
+
237
+ ```bash
238
+ npm install
239
+ cp .env.example .env
240
+ ```
241
+
242
+ Set values in `.env`:
243
+
244
+ ```dotenv
245
+ GITHUB_TOKEN=your_github_token_here
246
+ GITHUB_USERNAME=your_github_username_here
247
+ ```
248
+
249
+ ### 4) Run the core pipeline
250
+
251
+ ```bash
252
+ github-portfolio-analyzer analyze --as-of 2026-03-03
253
+ github-portfolio-analyzer ingest-ideas
254
+ github-portfolio-analyzer build-portfolio
255
+ github-portfolio-analyzer report --format all
256
+ ```
257
+
258
+ Example console snippet:
259
+
260
+ ```bash
261
+ $ github-portfolio-analyzer analyze --as-of 2026-03-03
262
+ Analyzed 51 repositories for octocat.
263
+ Wrote output/inventory.json.
264
+ Wrote output/inventory.csv.
265
+ ```
266
+
267
+ ## End-to-End Tutorial
268
+
269
+ ### Step 1: Analyze repositories
270
+
271
+ ```bash
272
+ github-portfolio-analyzer analyze --as-of 2026-03-03
273
+ ```
274
+
275
+ What happens:
276
+
277
+ - Authenticates with GitHub API
278
+ - Fetches all repos with pagination
279
+ - Computes structural health, activity, maturity, score, taxonomy
280
+ - Writes `inventory.json` and `inventory.csv`
281
+
282
+ ### Step 2: Ingest ideas
283
+
284
+ Default file mode:
285
+
286
+ ```bash
287
+ github-portfolio-analyzer ingest-ideas
288
+ ```
289
+
290
+ Interactive mode:
291
+
292
+ ```bash
293
+ github-portfolio-analyzer ingest-ideas --prompt
294
+ ```
295
+
296
+ What happens:
297
+
298
+ - Normalizes idea records
299
+ - Scores ideas
300
+ - Applies taxonomy defaults/inference with provenance metadata
301
+ - Normalizes `nextAction` to canonical format
302
+
303
+ ### Step 3: Build merged portfolio
304
+
305
+ ```bash
306
+ github-portfolio-analyzer build-portfolio
307
+ ```
308
+
309
+ What happens:
310
+
311
+ - Merges repos + ideas
312
+ - Preserves deterministic ordering
313
+ - Writes `portfolio.json`, per-project markdown pages, and `portfolio-summary.md`
314
+
315
+ ### Step 4: Generate decision report
316
+
317
+ ```bash
318
+ github-portfolio-analyzer report --format all
319
+ ```
320
+
321
+ What happens:
322
+
323
+ - Reads `portfolio.json` (required)
324
+ - Optionally reads `inventory.json` for richer repo completion signals
325
+ - Computes completion level, effort estimate, and priority band
326
+ - Writes ASCII + Markdown + JSON report artifacts
327
+
328
+ ## Command Reference
329
+
330
+ | Command | Purpose | Key Options |
331
+ |---|---|---|
332
+ | `analyze` | Build repository inventory from GitHub API | `--as-of YYYY-MM-DD`, `--output-dir PATH` |
333
+ | `ingest-ideas` | Add/update idea records | `--input PATH`, `--prompt`, `--output-dir PATH` |
334
+ | `build-portfolio` | Merge repos + ideas into portfolio outputs | `--output-dir PATH` |
335
+ | `report` | Produce decision-oriented report artifacts | `--output-dir PATH`, `--format ascii\|md\|json\|all` |
336
+
337
+ Default for `report --format` is `all`.
338
+
339
+ ## Integration Contract
340
+
341
+ This section defines the stable integration points for external tools and orchestrators.
342
+ For a fast first run path, start with [Quick Start](#quick-start).
343
+
344
+ ### Available commands
345
+
346
+ - `analyze`
347
+ - `ingest-ideas`
348
+ - `build-portfolio`
349
+ - `report`
350
+
351
+ ### Relevant report flags
352
+
353
+ - `report --policy`
354
+ - `report --explain`
355
+ - `report --quiet`
356
+
357
+ ### Canonical analyzer outputs
358
+
359
+ - `output/inventory.json`
360
+ - `output/portfolio.json`
361
+ - `output/portfolio-report.json`
362
+
363
+ ### Machine-readable interface files
364
+
365
+ - `analyzer.manifest.json`: static command/output manifest for external orchestrators
366
+ - `schemas/portfolio-report.schema.json`: JSON Schema for `portfolio-report.json` validation
367
+
368
+ ### Optional local configuration
369
+
370
+ - `priorities/policy.json`
371
+ - This file is local and git-ignored.
372
+ - Create it by copying:
373
+ `priorities/policy.example.json` -> `priorities/policy.json`
374
+
375
+ ### Optional strict mode
376
+
377
+ - Use `--strict` to fail on unknown flags with exit code `2`.
378
+ - Without `--strict`, existing permissive parsing behavior remains unchanged.
379
+
380
+ ### CLI version
381
+
382
+ You can get the CLI version with:
383
+
384
+ ```bash
385
+ github-portfolio-analyzer --version
386
+ ```
387
+
388
+ ### JSON schema
389
+
390
+ - `schemas/portfolio-report.schema.json` validates the `output/portfolio-report.json` structure.
391
+ - External systems can use this schema together with `analyzer.manifest.json` as the integration contract.
392
+
393
+ ## Exit Codes
394
+
395
+ - `0`: success
396
+ - `1`: operational failure (runtime/file/network/auth errors)
397
+ - `2`: invalid usage (for example invalid command or `--strict` unknown flag)
398
+
399
+ ## Optional Policy Overlay and Explain Mode
400
+
401
+ The report command supports an optional policy overlay to guide prioritization without changing project taxonomy, state, or score.
402
+ When no policy is provided, ranking remains neutral and deterministic using the built-in heuristics.
403
+
404
+ ### CLI examples
405
+
406
+ ```bash
407
+ github-portfolio-analyzer report --format all
408
+ github-portfolio-analyzer report --policy ./priorities/policy.json --format json
409
+ github-portfolio-analyzer report --priorities ./priorities/policy.json --explain
410
+ ```
411
+
412
+ ### Local policy file setup
413
+
414
+ Use the example as a starting point and keep your real policy file local:
415
+
416
+ ```bash
417
+ cp priorities/policy.example.json priorities/policy.json
418
+ ```
419
+
420
+ `priorities/policy.json` is git-ignored on purpose (local preferences).
421
+ `priorities/policy.example.json` should remain tracked as the shared template.
422
+
423
+ ### Minimal policy example
424
+
425
+ ```json
426
+ {
427
+ "version": 1,
428
+ "rules": [
429
+ {
430
+ "id": "focus-core-tooling",
431
+ "match": {
432
+ "type": ["repo"],
433
+ "category": ["tooling"],
434
+ "state": ["active", "stale"]
435
+ },
436
+ "effects": {
437
+ "boost": 10,
438
+ "tag": "core"
439
+ },
440
+ "reason": "Prioritize currently maintainable internal tooling."
441
+ }
442
+ ],
443
+ "pin": [
444
+ {
445
+ "slug": "developer-onboarding-checklist-generator",
446
+ "band": "now",
447
+ "tag": "manual-priority"
448
+ }
449
+ ]
450
+ }
451
+ ```
452
+
453
+ ### Policy behavior guarantees
454
+
455
+ - Rules are applied in deterministic `id` order.
456
+ - Boosts are cumulative.
457
+ - Pin band has highest precedence.
458
+ - `forceBand` uses strongest precedence: `now > next > later > park`.
459
+ - Policy overlay only affects report-level priority fields (`finalPriorityScore`, `priorityBand`, tags/overrides).
460
+ - Taxonomy fields, item score, and item state remain unchanged.
461
+ - The tool remains deterministic across runs for the same inputs.
462
+
463
+ ## Output Directory Map
464
+
465
+ ```text
466
+ /output
467
+ /projects
468
+ {project-slug}.md
469
+ inventory.json
470
+ inventory.csv
471
+ ideas.json
472
+ portfolio.json
473
+ portfolio-summary.md
474
+ portfolio-report.json
475
+ portfolio-report.md
476
+ portfolio-report.txt
477
+ ```
478
+
479
+ Artifact roles:
480
+
481
+ - `inventory.json`: repository-only enriched source (includes taxonomy + taxonomyMeta)
482
+ - `ideas.json`: ideas-only normalized source
483
+ - `portfolio.json`: merged source of truth
484
+ - `portfolio-summary.md`: high-level portfolio summary (state sections + top 10)
485
+ - `portfolio-report.*`: decision-oriented planning report in machine and human formats
486
+
487
+ ## Data Contracts
488
+
489
+ ### Taxonomy contract (all portfolio items)
490
+
491
+ Each `portfolio.json.items[]` entry includes:
492
+
493
+ - `type`: `repo | idea`
494
+ - `category`: `product | tooling | library | learning | content | infra | experiment | template`
495
+ - `state`: `idea | active | stale | abandoned | archived | reference-only`
496
+ - `strategy`: `strategic-core | strategic-support | opportunistic | maintenance | parked`
497
+ - `effort`: `xs | s | m | l | xl`
498
+ - `value`: `low | medium | high | very-high`
499
+ - `nextAction`: `"<Verb> <target> — Done when: <measurable condition>"`
500
+ - `taxonomyMeta`: per-field provenance (`default | user | inferred`)
501
+
502
+ `inventory.json.items[]` includes the same taxonomy fields and `taxonomyMeta` for repositories.
503
+
504
+ ### Report contract
505
+
506
+ `portfolio-report.json` includes:
507
+
508
+ - `meta` (generatedAt, asOfDate, owner, counts)
509
+ - `summary` (state counts, top10 by score, now/next/later/park)
510
+ - `matrix.completionByEffort` (`CL0..CL5` by `xs..xl`)
511
+ - `items[]` with decision fields (`completionLevel`, `effortEstimate`, `priorityBand`, `priorityWhy`)
512
+
513
+ ## Decision Model (Report)
514
+
515
+ ### Completion Level
516
+
517
+ - `CL0`: no README
518
+ - `CL1`: has README
519
+ - `CL2`: has package.json, or non-JS repo with size >= 500 KB
520
+ - `CL3`: CL2 + CI
521
+ - `CL4`: CL3 + tests
522
+ - `CL5`: CL4 + score >= 70
523
+ - Ideas default to `CL0`
524
+
525
+ ### Effort Estimate
526
+
527
+ Uses taxonomy `effort` unless `effort` source is `default`.
528
+ If defaulted, infer by size and completion:
529
+
530
+ - `xs`: size < 100 KB and CL <= 2
531
+ - `s`: size < 500 KB and CL <= 3
532
+ - `m`: size < 5000 KB
533
+ - `l`: size < 20000 KB
534
+ - `xl`: size >= 20000 KB
535
+
536
+ `effortEstimate` is a report field only; it does not overwrite taxonomy `effort`.
537
+
538
+ ### Priority Band
539
+
540
+ Internal score calculation:
541
+
542
+ - base: `score`
543
+ - `+10` if state `active`
544
+ - `+5` if state `stale`
545
+ - `-20` if state `abandoned` or `archived`
546
+ - `+10` if completion is CL1..CL3
547
+ - `-10` if effortEstimate is `l` or `xl`
548
+
549
+ Band mapping:
550
+
551
+ - `now`: >= 80
552
+ - `next`: 65..79
553
+ - `later`: 45..64
554
+ - `park`: < 45
555
+
556
+ ## Determinism and Time Rules
557
+
558
+ - `asOfDate` is UTC-based (`--as-of` or UTC today once per `analyze` run)
559
+ - `inventory.json.meta.asOfDate` persists snapshot date
560
+ - `portfolio.json.meta.asOfDate` copies inventory asOfDate, or `null` when inventory is missing
561
+ - Item-level timestamps are not persisted
562
+ - Deterministic ordering:
563
+ - inventory repos by `fullName` ascending
564
+ - ideas by `slug` ascending
565
+ - portfolio by `score` descending then `slug` ascending
566
+
567
+ ## nextAction Validation
568
+
569
+ Required canonical format:
570
+
571
+ `"<Verb> <target> — Done when: <measurable condition>"`
572
+
573
+ Robust input support:
574
+
575
+ - Accepts fallback marker `" - Done when:"`
576
+ - Normalizes to em dash marker `"— Done when:"`
577
+ - Throws clear error for invalid format
578
+
579
+ ## Architecture
580
+
581
+ ```text
582
+ bin/
583
+ github-portfolio-analyzer.js
584
+ src/
585
+ commands/ (analyze, ingest-ideas, build-portfolio, report)
586
+ core/ (classification, scoring, taxonomy, ideas, portfolio, report)
587
+ github/ (api client, pagination, structural inspection)
588
+ io/ (json/csv/markdown/report writers)
589
+ utils/ (args, time, slug, retry, concurrency, nextAction)
590
+ ```
591
+
592
+ ### Architecture Overview
593
+
594
+ ```mermaid
595
+ flowchart LR
596
+
597
+ subgraph User Layer
598
+ U[Developer / Script / Agent]
599
+ end
600
+
601
+ subgraph CLI Layer
602
+ A[analyze]
603
+ B[ingest-ideas]
604
+ C[build-portfolio]
605
+ D[report]
606
+ end
607
+
608
+ subgraph Core Engine
609
+ S1[GitHub API Client]
610
+ S2[Ideas Normalizer]
611
+ S3[Portfolio Builder]
612
+ S4[Decision Engine]
613
+ end
614
+
615
+ subgraph Artifacts
616
+ O1[inventory.json]
617
+ O2[ideas.json]
618
+ O3[portfolio.json]
619
+ O4[portfolio-report.json]
620
+ end
621
+
622
+ U --> A
623
+ U --> B
624
+ U --> C
625
+ U --> D
626
+
627
+ A --> S1
628
+ B --> S2
629
+ C --> S3
630
+ D --> S4
631
+
632
+ S1 --> O1
633
+ S2 --> O2
634
+ S3 --> O3
635
+ S4 --> O4
636
+ ```
637
+
638
+ Implementation characteristics:
639
+
640
+ - Minimal dependencies (`dotenv` only)
641
+ - Built-in `fetch`
642
+ - GitHub API only (no repository cloning)
643
+ - Retry/backoff on 403/429 and transient failures
644
+ - Per-repo error isolation during analysis
645
+
646
+ ## Testing and Quality
647
+
648
+ Run the full suite:
649
+
650
+ ```bash
651
+ npm test
652
+ ```
653
+
654
+ Coverage includes:
655
+
656
+ - activity/maturity/scoring boundaries
657
+ - taxonomy presence and provenance behavior
658
+ - `nextAction` validation and normalization
659
+ - portfolio merge determinism
660
+ - report completion logic, priority mapping, and deterministic model generation
661
+
662
+ ## Troubleshooting
663
+
664
+ ### Missing `GITHUB_TOKEN`
665
+
666
+ `analyze` fails fast with a clear error when token is missing.
667
+ `ingest-ideas`, `build-portfolio`, and `report` still run without GitHub authentication.
668
+
669
+ ### Missing `portfolio.json` for report
670
+
671
+ `report` requires `output/portfolio.json` and will fail with:
672
+
673
+ - `Missing required input: output/portfolio.json. Run build-portfolio before report.`
674
+
675
+ ### Report with no inventory
676
+
677
+ If `inventory.json` is absent:
678
+
679
+ - report still runs from `portfolio.json`
680
+ - owner is `null`
681
+ - completion signals are best-effort from portfolio fields
682
+
683
+ ## License and Contribution
684
+
685
+ Use this repository as a base for portfolio automation workflows and adapt heuristics for your organization.
686
+ Contributions should preserve deterministic contracts and avoid adding non-essential dependencies.