fullstackgtm 0.44.0 → 0.45.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 (99) hide show
  1. package/CHANGELOG.md +185 -1
  2. package/README.md +19 -7
  3. package/dist/audit.d.ts +3 -1
  4. package/dist/audit.js +29 -2
  5. package/dist/cli/audit.d.ts +15 -0
  6. package/dist/cli/audit.js +392 -0
  7. package/dist/cli/auth.d.ts +80 -0
  8. package/dist/cli/auth.js +500 -0
  9. package/dist/cli/call.d.ts +1 -0
  10. package/dist/cli/call.js +373 -0
  11. package/dist/cli/capabilities.d.ts +30 -0
  12. package/dist/cli/capabilities.js +197 -0
  13. package/dist/cli/draft.d.ts +7 -0
  14. package/dist/cli/draft.js +87 -0
  15. package/dist/cli/enrich.d.ts +8 -0
  16. package/dist/cli/enrich.js +788 -0
  17. package/dist/cli/fix.d.ts +33 -0
  18. package/dist/cli/fix.js +344 -0
  19. package/dist/cli/help.d.ts +25 -0
  20. package/dist/cli/help.js +609 -0
  21. package/dist/cli/icp.d.ts +7 -0
  22. package/dist/cli/icp.js +229 -0
  23. package/dist/cli/init.d.ts +7 -0
  24. package/dist/cli/init.js +58 -0
  25. package/dist/cli/market.d.ts +1 -0
  26. package/dist/cli/market.js +391 -0
  27. package/dist/cli/plans.d.ts +5 -0
  28. package/dist/cli/plans.js +454 -0
  29. package/dist/cli/schedule.d.ts +8 -0
  30. package/dist/cli/schedule.js +479 -0
  31. package/dist/cli/shared.d.ts +70 -0
  32. package/dist/cli/shared.js +331 -0
  33. package/dist/cli/signals.d.ts +7 -0
  34. package/dist/cli/signals.js +412 -0
  35. package/dist/cli/suggest.d.ts +49 -0
  36. package/dist/cli/suggest.js +135 -0
  37. package/dist/cli/tam.d.ts +9 -0
  38. package/dist/cli/tam.js +387 -0
  39. package/dist/cli/ui.d.ts +121 -0
  40. package/dist/cli/ui.js +375 -0
  41. package/dist/cli.d.ts +1 -57
  42. package/dist/cli.js +100 -5130
  43. package/dist/connector.d.ts +15 -0
  44. package/dist/connector.js +35 -0
  45. package/dist/connectors/hubspot.d.ts +3 -1
  46. package/dist/connectors/hubspot.js +10 -3
  47. package/dist/connectors/salesforce.d.ts +3 -1
  48. package/dist/connectors/salesforce.js +12 -5
  49. package/dist/connectors/signalSources.js +7 -59
  50. package/dist/icp.d.ts +15 -11
  51. package/dist/icp.js +19 -36
  52. package/dist/judge.d.ts +2 -0
  53. package/dist/judge.js +6 -0
  54. package/dist/marketClassify.d.ts +2 -0
  55. package/dist/marketClassify.js +7 -1
  56. package/dist/mcp-bin.js +2 -2
  57. package/dist/mcp.js +259 -166
  58. package/dist/schedule.d.ts +80 -2
  59. package/dist/schedule.js +254 -1
  60. package/dist/spoolFiles.d.ts +44 -0
  61. package/dist/spoolFiles.js +114 -0
  62. package/dist/types.d.ts +11 -0
  63. package/docs/api.md +73 -7
  64. package/docs/signal-spool-format.md +13 -0
  65. package/llms.txt +15 -6
  66. package/package.json +1 -1
  67. package/skills/fullstackgtm/SKILL.md +1 -1
  68. package/src/audit.ts +27 -1
  69. package/src/cli/audit.ts +447 -0
  70. package/src/cli/auth.ts +549 -0
  71. package/src/cli/call.ts +398 -0
  72. package/src/cli/capabilities.ts +215 -0
  73. package/src/cli/draft.ts +101 -0
  74. package/src/cli/enrich.ts +885 -0
  75. package/src/cli/fix.ts +372 -0
  76. package/src/cli/help.ts +664 -0
  77. package/src/cli/icp.ts +265 -0
  78. package/src/cli/init.ts +65 -0
  79. package/src/cli/market.ts +423 -0
  80. package/src/cli/plans.ts +523 -0
  81. package/src/cli/schedule.ts +526 -0
  82. package/src/cli/shared.ts +375 -0
  83. package/src/cli/signals.ts +434 -0
  84. package/src/cli/suggest.ts +151 -0
  85. package/src/cli/tam.ts +435 -0
  86. package/src/cli/ui.ts +426 -0
  87. package/src/cli.ts +99 -5829
  88. package/src/connector.ts +46 -0
  89. package/src/connectors/hubspot.ts +14 -2
  90. package/src/connectors/salesforce.ts +18 -2
  91. package/src/connectors/signalSources.ts +7 -56
  92. package/src/icp.ts +19 -35
  93. package/src/judge.ts +7 -0
  94. package/src/marketClassify.ts +8 -1
  95. package/src/mcp-bin.ts +2 -2
  96. package/src/mcp.ts +130 -57
  97. package/src/schedule.ts +310 -3
  98. package/src/spoolFiles.ts +116 -0
  99. package/src/types.ts +12 -0
package/CHANGELOG.md CHANGED
@@ -5,7 +5,191 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
5
5
  and the project adheres to [Semantic Versioning](https://semver.org/).
6
6
  The path to 1.0 is planned in [docs/roadmap-to-1.0.md](./docs/roadmap-to-1.0.md).
7
7
 
8
- ## [Unreleased]
8
+ ## [0.45.0] — 2026-07-02
9
+
10
+ ### Added (TUI glamour — interactive terminals only)
11
+
12
+ - **A terminal presentation layer (`src/cli/ui.ts`, zero new dependencies) —
13
+ styling and animation exist ONLY on an interactive TTY.** Piped, redirected,
14
+ `--json`, CI, and `NO_COLOR` output is byte-identical to the pre-TUI CLI
15
+ (verified against the previous build for 14 verbs: stdout, stderr, exit
16
+ codes); a new `agent-cli.yml` step and `tests/fullstackgtmAnsiSafety.test.ts`
17
+ enforce zero ANSI bytes in piped output permanently. `FORCE_COLOR=1` opts
18
+ piped output back into color per spec. On a TTY:
19
+ - `doctor` colors each check (green ok / red MISSING), dims what's not
20
+ connected, bands the health score, appends a score-history sparkline, and
21
+ frames "Next step" in a box. `--help` gets a dimmed brand header
22
+ (version · active profile), bold command names, cyan lifecycle groups.
23
+ - `health` renders a styled rollup: banded score, ▲/▼ delta, score
24
+ sparkline, aligned object-type and per-rule tables (positive finding
25
+ deltas red — more findings is worse — negative green).
26
+ - Live provider pulls show a stderr spinner with a running tally ("Pulling
27
+ contacts from hubspot… 2,400 fetched · 12s"): the HubSpot/Salesforce
28
+ connectors accept an optional per-page `onProgress` (presentation-only,
29
+ errors swallowed). `audit` renders its rule registry as a live checklist
30
+ (○ → spinner → ✓ with finding counts) via a new optional `onRule` on
31
+ `auditSnapshot`; `signals fetch` shows a per-domain ATS tally.
32
+ - `apply` and `fix --yes` tick per-operation progress ("Applying 41/120 ·
33
+ ✓ 40 applied · 0 failed · 1 conflict") via a new optional `onOperation` on
34
+ `applyPatchPlan`, closing with a colored outcome badge. `enrich
35
+ append/refresh` gets a progress bar with rate + ETA over the Apollo pull;
36
+ `enrich acquire` adds a budget fuel gauge (records + spend vs day/month
37
+ caps, color-banded by burn).
38
+ - LLM waits show an elapsed status line (`call parse` / `call score`);
39
+ `icp judge` and `market classify` report per-account / per-vendor progress
40
+ via new optional `onAccount` / `onVendor` callbacks.
41
+ - Patch plans render with severity banding and value diffs — current value
42
+ red, proposed value green, `requires_human_*` placeholders yellow — in
43
+ `audit` and `plans show`; `plans list` becomes an aligned status-banded
44
+ table (summaries truncated with `…` to the terminal width so rows never
45
+ wrap); `fix` frames its stop-before-apply command in a box.
46
+
47
+ ### Added (agent ergonomics pass 1)
48
+
49
+ - **Flag typos are caught instead of silently ignored.** Any `--flag` that is
50
+ documented nowhere in the help reference but sits within one edit of a
51
+ documented flag (after lowercasing and `_`→`-` normalization) now stops with
52
+ exit 1, a `Did you mean: --json` hint, and the exact corrected command;
53
+ `--json` callers get a structured `UNKNOWN_FLAG` envelope. Previously
54
+ `audit --demo --jsn` exited 0 and printed markdown where the caller asked
55
+ for JSON, and `reassign … --sav` exited 0 without saving. Suggest-only —
56
+ the correction is never auto-executed, so a typo can never change what a
57
+ write-shaped invocation stages. The known-flag registry is derived at
58
+ runtime from the help table (no parallel list); unknown flags with no
59
+ near-miss behave exactly as before.
60
+ - **Unknown commands get a did-you-mean on the plain-text path too.**
61
+ `fullstackgtm plan` now answers `Did you mean: fullstackgtm plans` plus one
62
+ pointer line each to `--help` and `capabilities --json`, instead of the
63
+ full usage-reference dump. (The `--json` envelope already had the hint.)
64
+ - **`doctor` is now the one-call triage surface.** `doctor --json` adds a
65
+ `workspace` slice — `healthScore`, `scoreDelta`, `lastAuditAt`,
66
+ `auditCount`, and `pendingPlans` (id, summary, operation/approved counts) —
67
+ and when a plan is awaiting approval `nextSteps` becomes the copy-pasteable
68
+ `plans show` → `plans approve` → `apply` chain with the connected provider
69
+ filled in. Text `doctor` gains the matching `Workspace:` section.
70
+ Previously orienting an agent took three calls (doctor + health +
71
+ plans list).
72
+ - **`audit` output is byte-deterministic under `SOURCE_DATE_EPOCH`.** The
73
+ plan's `createdAt` honors the reproducible-build convention (seconds since
74
+ the epoch) so golden tests and CI diffs can pin `audit --demo --json`
75
+ byte-for-byte. Unset, it remains the real clock.
76
+ - **GNU-style `--flag=value` is corrected too.** `audit --rules=x` was
77
+ silently dropped (the audit ran with all rules); an `=`-form whose base
78
+ resolves to a documented flag now stops with the space-separated form this
79
+ CLI parses (`Try: … --rules x`).
80
+ - **A flag-shaped first token is diagnosed as flag-before-command.**
81
+ `fullstackgtm --jsn` was "Unknown command: --jsn"; now it explains that a
82
+ command must come first and resolves the flag when it near-misses a
83
+ documented one.
84
+ - **Subverb typos get a nearest-match did-you-mean on all 7 multi-verb
85
+ commands** (`enrich`, `market`, `icp`, `signals`, `plans`, `schedule`,
86
+ `tam`): `enrich apend` → `Did you mean: fullstackgtm enrich append?` plus
87
+ the full list. `market <typo>` no longer dies with a `market.config.json`
88
+ ENOENT before the subcommand is validated.
89
+
90
+ ### Changed (agent ergonomics pass 1)
91
+
92
+ - **`apply <planId>` / `suggest <planId>` (positional) now name the exact
93
+ corrected command** (`apply --plan-id <id> --provider <…>`) instead of
94
+ misdiagnosing the mistake as a missing `--provider`. Both verbs stay
95
+ flag-explicit; nothing is inferred into execution.
96
+ - **`Unknown provider: hubpsot` now adds `Did you mean hubspot?`** (CLI and
97
+ MCP paths); the supported-provider list is unchanged.
98
+
99
+ ### Changed
100
+
101
+ - **MCP zero-install is now one short command: `npx -y fullstackgtm-mcp`.** A
102
+ thin wrapper package (`fullstackgtm-mcp@0.1.0`, monorepo
103
+ `packages/fullstackgtm-mcp`, published manually — the OIDC release flow
104
+ covers only this package) pins the optional MCP peers as hard dependencies
105
+ and delegates to this package's `dist/mcp-bin.js`. README, SKILL.md, and the
106
+ missing-peer help text now lead with the short command; the explicit
107
+ `-p fullstackgtm -p @modelcontextprotocol/sdk -p zod` form still works.
108
+
109
+ ### Added
110
+
111
+ - **`schedule install` no longer needs Full Disk Access on macOS: launchd
112
+ LaunchAgents are the default timer there.** macOS gates `crontab` writes
113
+ behind FDA — an unpromptable TCC permission granted to the terminal app,
114
+ not the CLI — so on darwin `install` now writes one LaunchAgent plist per
115
+ enabled entry (`com.fullstackgtm.<profile>.<id>` in
116
+ `~/Library/LaunchAgents`, loaded via `launchctl bootstrap gui/<uid>`),
117
+ which needs no permission at all. The cron expression compiles to
118
+ `StartCalendarInterval` dicts (full-range fields become launchd wildcards;
119
+ dense expressions are capped at 512 dicts with a clear error; Vixie
120
+ dom+dow OR becomes a Day set plus a Weekday set). Every plist's
121
+ `ProgramArguments` is `… schedule run <id> --profile <p> --trigger cron`
122
+ and nothing else — the same single-entry-point audit story as the crontab
123
+ block — and re-install replaces the profile's plist fleet wholesale,
124
+ never touching foreign plists. launchd also coalesces firings missed
125
+ during sleep into one run on wake, where cron silently skips. `--timer
126
+ crontab|launchd` overrides the platform default (launchd on macOS, crontab
127
+ elsewhere); stdout/stderr of each firing lands in
128
+ `<home>/schedule/logs/<label>.log`. New run no-op reason
129
+ `duplicate_firing`: `schedule run` drops a second cron trigger in the same
130
+ minute, so a date matching both the Day and Weekday interval sets cannot
131
+ double-run a command.
132
+
133
+ - **Standardized flag aliases (additive — every legacy flag keeps working).**
134
+ `--dry-run` is now accepted on the plan-spine verbs (`audit`, `suggest`,
135
+ `bulk-update`, `dedupe`, `reassign`, `fix`, `call plan`,
136
+ `enrich append`/`refresh`/`acquire`, `signals fetch`, `icp judge`, `draft`,
137
+ `tam status`, `market overlay`): these verbs were already preview-by-default,
138
+ so the flag asserts that default — it suppresses `--save` (with a stderr note
139
+ when both are passed) and locks `fix` to its stop-before-apply path even with
140
+ `--yes`. Omitting it changes nothing. `--confirm` is now an accepted alias
141
+ for `fix --yes` (matching `tam accounts --confirm`); `--dry-run` beats both.
142
+ - **Staged-file ingestion converged on the spool container convention
143
+ (additive).** `signals fetch --from` and `enrich ingest` now also accept a
144
+ `*.jsonl` spool file (one JSON row per line) or a directory of `*.jsonl` /
145
+ `*.json` spool files — the Phase-2 webhook landing-zone format
146
+ (docs/signal-spool-format.md) — and `market observe --from` accepts a
147
+ `*.jsonl` file / directory of observation-set envelopes, each validated and
148
+ appended through the same gates as the single-file path. Existing `.json` /
149
+ `.csv` inputs parse exactly as before. Shared reader: `src/spoolFiles.ts`
150
+ (the `file` signal-source connector now delegates to it, error text
151
+ unchanged).
152
+ - **Machine-readable agent contract: `capabilities`, `robot-docs`, and
153
+ `--help --json`.** `capabilities` prints the CLI contract as JSON: the
154
+ command inventory with read-only vs write-shaped access derived from the
155
+ help table's lifecycle phases (never a hand-maintained parallel list), the
156
+ documented exit-code contract, safety defaults, and the MCP entrypoint.
157
+ `<command> --help --json` (and `help <command> --json`) prints the same
158
+ per-command help as JSON — plain `--help` output is unchanged except that
159
+ `audit --help` now documents the pre-existing `--input <path>` flag.
160
+ Unknown commands invoked with `--json` return a structured
161
+ `{ ok: false, error: { code: "UNKNOWN_COMMAND", hints: [did-you-mean] } }`
162
+ envelope on stdout (exit 1) instead of the full-usage text wall.
163
+ `robot-docs` prints the packaged agent guide (skills/fullstackgtm/SKILL.md,
164
+ already shipped in the npm tarball) — one maintained guide, not a third
165
+ parallel one.
166
+ - **MCP `fullstackgtm_capabilities` tool.** The MCP server's tools are now
167
+ declared in a single registration table and registered in a loop; the new
168
+ tool reports the inventory (with per-tool `writesCrm` flags — only
169
+ `fullstackgtm_apply` can reach a CRM) from that same table, so the
170
+ advertised list cannot drift from what is actually registered. The existing
171
+ tools' behavior is unchanged.
172
+ - **`--input` snapshot files are validated.** `--input` now checks the file
173
+ parses to the canonical snapshot shape (the JSON `snapshot --out` writes)
174
+ and fails with a field-level error naming what's missing, instead of a
175
+ blind cast that surfaced as a crash deep in a rule — or an empty "clean"
176
+ audit.
177
+
178
+ ### Fixed
179
+
180
+ - **`bulk-update` restored to the help front door.** The grouped short-usage
181
+ map listed the verb in its Remediate group but silently skipped rendering
182
+ it (no help-table entry), and `help bulk-update` dead-ended on the short
183
+ map. It now has a proper entry and appears in the derived `capabilities`
184
+ inventory.
185
+
186
+ ### Changed
187
+
188
+ - **Internal: `src/cli.ts` (6,003 lines) split into per-verb modules under
189
+ `src/cli/`** (help, audit, fix, call, market, enrich, signals, draft, tam,
190
+ icp, init, schedule, plans, auth, shared). No behavior change: `dist/bin.js`
191
+ stays the entry, arg parsing / help text / exit codes are unchanged, and
192
+ `cli.ts` still exports `runCli`, `doctorReport`, `assertSecureBrokerUrl`.
9
193
 
10
194
  ## [0.44.0] — 2026-07-01
11
195
 
package/README.md CHANGED
@@ -254,15 +254,15 @@ Everything the CLI produces is accurate the moment it runs and silently stale af
254
254
  fullstackgtm schedule add "enrich refresh --source apollo --save" --cron "0 6 * * 1" --label weekly-apollo
255
255
  fullstackgtm schedule add "audit --provider hubspot --save" --cron "0 2 * * *" # nightly drift baseline
256
256
  fullstackgtm schedule list # declarative entries; nothing runs yet
257
- fullstackgtm schedule install # materialize enabled entries into a managed crontab block
257
+ fullstackgtm schedule install # materialize enabled entries into the system timer (launchd on macOS, crontab elsewhere)
258
258
  fullstackgtm schedule run <id> # execute now; same run record a cron firing produces
259
259
  fullstackgtm schedule status --runs 5 # last runs, exit codes, artifacts, next + missed firings
260
260
  fullstackgtm schedule uninstall # remove the managed block, touch nothing else
261
261
  ```
262
262
 
263
- **Scheduling never auto-approves.** Schedulable commands are read/plan-side only — `audit`, `snapshot`, `enrich append|refresh`, `market capture|refresh`, `signals fetch`, `icp judge`, `icp eval`, `draft`, `suggest`, `report`, `doctor` — so unattended runs accumulate *proposals* (plans in the queue, run records, reports), never CRM writes. `apply` is schedulable only as `apply --plan-id <id>`, and every firing re-checks the plan's status is approved: an unapproved plan records a `plan_not_approved` no-op run instead of executing, and no flag relaxes this. Arbitrary shell is not schedulable — an entry's argv must resolve to a known fullstackgtm command (validated at `add` time and re-checked at run time), and the crontab line you audit is always `fullstackgtm schedule run <id>` and nothing else.
263
+ **Scheduling never auto-approves.** Schedulable commands are read/plan-side only — `audit`, `snapshot`, `enrich append|refresh`, `market capture|refresh`, `signals fetch`, `icp judge`, `icp eval`, `draft`, `suggest`, `report`, `doctor` — so unattended runs accumulate *proposals* (plans in the queue, run records, reports), never CRM writes. `apply` is schedulable only as `apply --plan-id <id>`, and every firing re-checks the plan's status is approved: an unapproved plan records a `plan_not_approved` no-op run instead of executing, and no flag relaxes this. Arbitrary shell is not schedulable — an entry's argv must resolve to a known fullstackgtm command (validated at `add` time and re-checked at run time), and the timer line you audit — crontab entry or LaunchAgent `ProgramArguments` — is always `fullstackgtm schedule run <id>` and nothing else.
264
264
 
265
- `install` renders enabled entries into a sentinel-delimited block (`# >>> fullstackgtm <profile> >>>` … `# <<< fullstackgtm <profile> <<<`) in your user crontab; re-install replaces the block wholesale and never touches lines outside it. Honest limitation: local cron has no catch-up — a laptop asleep at firing time means a missed run. `schedule status` surfaces missed firings by comparing expected-vs-actual run history, so the gap is at least visible. Entries are provider-agnostic; cloud providers (Modal, AWS) arrive as scaffold generators that call the same `schedule run <id>` contract, and are refused as "not yet implemented" until then.
265
+ `install` materializes enabled entries into the system timer; `--timer` defaults by platform. On macOS it writes one LaunchAgent plist per entry (`com.fullstackgtm.<profile>.<id>` in `~/Library/LaunchAgents`, loaded via `launchctl bootstrap`) — macOS gates `crontab` writes behind Full Disk Access, a permission no program can request, while LaunchAgents need none; launchd also coalesces firings missed during sleep into one run on wake. Re-install replaces the profile's plist fleet wholesale and never touches foreign plists. Elsewhere (or with `--timer crontab`) it renders a sentinel-delimited block (`# >>> fullstackgtm <profile> >>>` … `# <<< fullstackgtm <profile> <<<`) in your user crontab; re-install replaces the block wholesale and never touches lines outside it. Honest limitation: cron has no catch-up — a laptop asleep at firing time means a missed run. `schedule status` surfaces missed firings by comparing expected-vs-actual run history, so the gap is at least visible. Entries are provider-agnostic; cloud providers (Modal, AWS) arrive as scaffold generators that call the same `schedule run <id>` contract, and are refused as "not yet implemented" until then.
266
266
 
267
267
  ### Working across organizations
268
268
 
@@ -281,6 +281,17 @@ Set `FULLSTACKGTM_PROFILE=acme` to pin a shell (or agent sandbox) to one client.
281
281
  Every command is designed to compose in an agent loop — deterministic output, machine-readable everywhere, meaningful exit codes:
282
282
 
283
283
  ```bash
284
+ # Discover the machine-readable contract: every command, read-only vs
285
+ # write-shaped access, exit codes, safety defaults (derived from the same
286
+ # help table humans read, so it can't drift)
287
+ fullstackgtm capabilities --json
288
+
289
+ # Per-command help as JSON; plain --help stays human-shaped
290
+ fullstackgtm audit --help --json
291
+
292
+ # Print the shipped agent operating guide (the same SKILL.md `npx skills add` installs)
293
+ fullstackgtm robot-docs
294
+
284
295
  # Discover what the auditor checks
285
296
  fullstackgtm rules --json
286
297
 
@@ -296,6 +307,7 @@ fullstackgtm audit --provider hubspot --fail-on warning
296
307
  fullstackgtm diff --before old.json --after new.json --fail-on-new-findings
297
308
  ```
298
309
 
310
+ - Terminal polish never leaks into machine output: color, spinners, progress bars, and sparklines render **only on an interactive TTY** (stderr for anything animated). Piped, redirected, `--json`, CI, and `NO_COLOR` output carries **zero ANSI bytes** — enforced by tests and a CI contract check — so transcripts and pipes see the same plain text they always did (`FORCE_COLOR=1` opts back in).
299
311
  - Finding and operation ids are **stable hashes** of rule + record, so two runs over the same data produce identical ids — agents can diff plans, track findings across runs, and approve operations by id without re-parsing.
300
312
  - `--demo` (with `--seed`) generates a realistic mid-market CRM with injected real-world failure modes — departed owners, unlinked deals, orphan accounts, stale pipeline — so agents and CI can exercise the full snapshot → audit → apply pipeline with zero credentials.
301
313
  - Exit codes: `0` success, `1` error, `2` findings at/above `--fail-on`.
@@ -488,14 +500,14 @@ The MCP entrypoint needs the optional peer dependencies `@modelcontextprotocol/s
488
500
  npm install fullstackgtm @modelcontextprotocol/sdk zod
489
501
  HUBSPOT_ACCESS_TOKEN=pat-... npx fullstackgtm-mcp
490
502
 
491
- # Zero-install
492
- npx -p fullstackgtm -p @modelcontextprotocol/sdk -p zod fullstackgtm-mcp
503
+ # Zero-install (the fullstackgtm-mcp wrapper package bundles the MCP peers)
504
+ npx -y fullstackgtm-mcp
493
505
  ```
494
506
 
495
507
  Add it to Claude Code in one command:
496
508
 
497
509
  ```bash
498
- claude mcp add fullstackgtm -e HUBSPOT_ACCESS_TOKEN=pat-... -- npx -y -p fullstackgtm -p @modelcontextprotocol/sdk -p zod fullstackgtm-mcp
510
+ claude mcp add fullstackgtm -e HUBSPOT_ACCESS_TOKEN=pat-... -- npx -y fullstackgtm-mcp
499
511
  ```
500
512
 
501
513
  Or configure any MCP client (Cursor, Claude Desktop, …) with:
@@ -505,7 +517,7 @@ Or configure any MCP client (Cursor, Claude Desktop, …) with:
505
517
  "mcpServers": {
506
518
  "fullstackgtm": {
507
519
  "command": "npx",
508
- "args": ["-y", "-p", "fullstackgtm", "-p", "@modelcontextprotocol/sdk", "-p", "zod", "fullstackgtm-mcp"],
520
+ "args": ["-y", "fullstackgtm-mcp"],
509
521
  "env": { "HUBSPOT_ACCESS_TOKEN": "pat-..." }
510
522
  }
511
523
  }
package/dist/audit.d.ts CHANGED
@@ -3,5 +3,7 @@ export declare function defaultPolicy(today?: string): GtmPolicy;
3
3
  /**
4
4
  * Run every rule over the snapshot and collect the results into a single
5
5
  * dry-run patch plan. Pass custom rules to extend or replace the built-ins.
6
+ * `onRule` reports per-rule progress (presentation only — a throwing callback
7
+ * never fails the audit).
6
8
  */
7
- export declare function auditSnapshot(snapshot: CanonicalGtmSnapshot, policy?: GtmPolicy, rules?: GtmAuditRule[]): PatchPlan;
9
+ export declare function auditSnapshot(snapshot: CanonicalGtmSnapshot, policy?: GtmPolicy, rules?: GtmAuditRule[], onRule?: (ruleId: string, phase: "start" | "done", findings?: number) => void): PatchPlan;
package/dist/audit.js CHANGED
@@ -4,6 +4,19 @@ const DEFAULT_POLICY = {
4
4
  requireDealOwner: true,
5
5
  requireAccountForDeal: true,
6
6
  };
7
+ /**
8
+ * Wall clock for the plan's stdout-bound `createdAt`, honoring the
9
+ * SOURCE_DATE_EPOCH reproducible-build convention (seconds since the Unix
10
+ * epoch). When set, `audit --demo --json` is byte-deterministic across
11
+ * re-runs — golden tests and CI diffs can pin the payload. Unset (normal
12
+ * use) it is the real clock, exactly as before.
13
+ */
14
+ function nowIso() {
15
+ const epoch = process.env.SOURCE_DATE_EPOCH;
16
+ if (epoch && /^\d+$/.test(epoch))
17
+ return new Date(Number(epoch) * 1000).toISOString();
18
+ return new Date().toISOString();
19
+ }
7
20
  export function defaultPolicy(today = new Date().toISOString().slice(0, 10)) {
8
21
  return {
9
22
  ...DEFAULT_POLICY,
@@ -13,15 +26,29 @@ export function defaultPolicy(today = new Date().toISOString().slice(0, 10)) {
13
26
  /**
14
27
  * Run every rule over the snapshot and collect the results into a single
15
28
  * dry-run patch plan. Pass custom rules to extend or replace the built-ins.
29
+ * `onRule` reports per-rule progress (presentation only — a throwing callback
30
+ * never fails the audit).
16
31
  */
17
- export function auditSnapshot(snapshot, policy = defaultPolicy(), rules = builtinAuditRules) {
32
+ export function auditSnapshot(snapshot, policy = defaultPolicy(), rules = builtinAuditRules, onRule) {
18
33
  const context = { snapshot, policy, index: buildSnapshotIndex(snapshot) };
19
34
  const findings = [];
20
35
  const operations = [];
21
36
  for (const rule of rules) {
37
+ try {
38
+ onRule?.(rule.id, "start");
39
+ }
40
+ catch {
41
+ // progress is presentation-only
42
+ }
22
43
  const result = rule.evaluate(context);
23
44
  findings.push(...result.findings);
24
45
  operations.push(...result.operations);
46
+ try {
47
+ onRule?.(rule.id, "done", result.findings.length);
48
+ }
49
+ catch {
50
+ // progress is presentation-only
51
+ }
25
52
  }
26
53
  const evidence = buildEvidence(snapshot, findings, policy.today);
27
54
  const pipelineFindings = buildPipelineFindings(findings, operations, evidence, policy.today);
@@ -29,7 +56,7 @@ export function auditSnapshot(snapshot, policy = defaultPolicy(), rules = builti
29
56
  return {
30
57
  id: `patch_plan_${stableHash(`${snapshot.provider}:${snapshot.generatedAt}:${findings.length}:${operations.length}`)}`,
31
58
  title: "GTM hygiene audit patch plan",
32
- createdAt: new Date().toISOString(),
59
+ createdAt: nowIso(),
33
60
  status: operations.length > 0 ? "needs_approval" : "draft",
34
61
  dryRun: true,
35
62
  summary: `${findings.length} findings and ${operations.length} proposed dry-run operations.`,
@@ -0,0 +1,15 @@
1
+ export declare function snapshotCommand(args: string[]): Promise<void>;
2
+ export declare function audit(args: string[]): Promise<void>;
3
+ /**
4
+ * Roll up the active profile's health timeline (accrued by `audit --save`):
5
+ * current deterministic score, change since the last audit, and per-rule
6
+ * deltas. Read-only — it only reads `health.jsonl`, never re-audits.
7
+ */
8
+ export declare function healthCommand(args: string[]): void;
9
+ /**
10
+ * Render an audit as a client-facing deliverable. Same sources and audit
11
+ * options as `audit`; `--plan` instead renders an existing plan JSON without
12
+ * re-fetching (useful for a plan produced earlier or by another machine).
13
+ */
14
+ export declare function reportCommand(args: string[]): Promise<void>;
15
+ export declare function rulesCommand(args: string[]): Promise<void>;