fullstackgtm 0.23.1 → 0.23.2
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 +18 -0
- package/README.md +18 -0
- package/docs/api.md +51 -9
- package/llms.txt +25 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@ 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
|
+
## [0.23.2] — 2026-06-12
|
|
9
|
+
|
|
10
|
+
Documentation catch-up: the README, llms.txt, and docs/api.md now cover
|
|
11
|
+
everything that shipped 0.19–0.23. (No code changes.)
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- README: new "Routine maintenance as governed verbs" section (`bulk-update`,
|
|
16
|
+
`dedupe`, `reassign`, `fix`) and a market-map paragraph for `market overlay`
|
|
17
|
+
(directives from your own ground truth) and `market scale` (citable,
|
|
18
|
+
calibrated size estimates).
|
|
19
|
+
- llms.txt: governed-write-verbs invariants block; overlay/scale invariants
|
|
20
|
+
added to the market-map block.
|
|
21
|
+
- docs/api.md: CLI command list completed (write verbs, `enrich`, market
|
|
22
|
+
`overlay`/`scale`); new "Governed write verbs" and "Enrich" export
|
|
23
|
+
sections; market-map section updated for 0.16–0.23 exports incl.
|
|
24
|
+
`computeDirectives`/`directivesToPlan` and `computeScaleIndex`.
|
|
25
|
+
|
|
8
26
|
## [0.23.1] — 2026-06-12
|
|
9
27
|
|
|
10
28
|
### Fixed
|
package/README.md
CHANGED
|
@@ -109,6 +109,22 @@ npx fullstackgtm report --provider hubspot --client "Acme" --out acme-health.htm
|
|
|
109
109
|
|
|
110
110
|
`report` renders the same audit as a deliverable — severity counts up front, a prose summary, per-rule detail with example records, and next steps — as markdown or self-contained HTML (printable, emailable, no external assets).
|
|
111
111
|
|
|
112
|
+
## Routine maintenance as governed verbs: bulk-update, dedupe, reassign, fix
|
|
113
|
+
|
|
114
|
+
The maintenance work RevOps actually does in bulk — backfills, book transfers, duplicate sweeps, "just fix everything that rule found" — gets first-class verbs. Each one *builds a plan*; nothing executes without the same approve → apply gauntlet as everything else.
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
fullstackgtm bulk-update deal --where "stage=closedwon" --where "amount:empty" \
|
|
118
|
+
--set amount=from:account.annualrevenue --save # per-record derived values; empty sources skipped, never guessed
|
|
119
|
+
fullstackgtm dedupe account --key domain --keep richest --save # one merge_records op per duplicate group
|
|
120
|
+
fullstackgtm reassign --from 411 --to 902 --except-deal-stage closing --save # ownership handoff playbook
|
|
121
|
+
fullstackgtm fix --rule missing-deal-owner --provider hubspot --yes # audit one rule → suggest → approve → apply, one command
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`bulk-update` filters the snapshot (`=`, `!=`, `~` substring, `:empty`/`:notempty`, `|` any-of, relational pseudo-fields like `account.domain` or `openDealStages`) into a dry-run patch plan — and **the full filter is re-verified per record at apply time**, with mid-apply rechecks, so a record that stopped matching between audit and apply is skipped, not clobbered. Equality filters double as preconditions; `--require` adds explicit ones; `--guard` asserts cross-record conditions; `--max-operations` caps blast radius. `--set field=from:<sourceField>` derives values per record; `--archive` refuses records whose identity key (account domain, contact email) is shared with another record — that's a duplicate, and duplicates are merged with `dedupe`, not archived around.
|
|
125
|
+
|
|
126
|
+
`dedupe` finds duplicate groups by normalized identity key and emits one `merge_records` operation per group with a deterministic survivor (`richest` = most populated fields, ties to lowest id; `oldest`). Merges stay irreversible-and-therefore-low-confidence-capped on approval, exactly like merge suggestions from the audit. `reassign` is the ownership-handoff playbook: one plan per object type, extra scoping account-lifted to deals and contacts, and `--except-deal-stage` excludes both deals in that stage and every record whose account has an open deal in it. `fix` is the one-shot composite for a single rule: audit → save → suggest → approve suggestion-backed operations at the confidence bar → with `--yes`, apply and print the stage-by-stage summary; without it, stop after approval and print the apply command.
|
|
127
|
+
|
|
112
128
|
## The market map: the category, observed
|
|
113
129
|
|
|
114
130
|
Your CRM records what happened in your own deals; nothing records the shape of the category you sell into. The **market map** does: vendors and a claim taxonomy live in a reviewable `market.config.json`, vendor pages are captured into a content-addressed cache, every vendor × claim cell gets a messaging-intensity reading (LOUD / QUIET / ABSENT — with UNOBSERVABLE for failed captures, never a fake absence), and deterministic front states fall out per claim: open, contested, owned, saturated.
|
|
@@ -126,6 +142,8 @@ The discipline matches the rest of the tool. Intensity readings are *proposals*
|
|
|
126
142
|
|
|
127
143
|
`market axes` is for earning a strategic 2×2 instead of asserting one: PCA over the intensity matrix (PC1 = the category's own primary axis, PC2 = the most differentiating direction orthogonal to it), triangulation of your configured axes against the data, and an orthogonality screen that flags two axes that are secretly one. Axes are claim-scoring rubrics in the config; the report renders the primary pair as the strategic map. Captures and observations are profile-scoped (`~/.fullstackgtm/market/<category>`), so one client's category intel never bleeds into another's.
|
|
128
144
|
|
|
145
|
+
Two more derivations close the loop from map to action. `market overlay --snapshot <crm.json> [--calls <files>]` joins the observation store against your own ground truth — which claims and vendors actually come up in your deals and call transcripts (deterministic word-boundary matching, no LLM) — and emits OCCUPY / PROMOTE / URGENT / RETREAT directives, each carrying at least one observation and one CRM stat with its sample size; below the evidence thresholds the honest answer is *no directive*. `--save` turns directives into approval-gated `create_task` operations through the normal plan chain. `market scale` estimates each vendor's size from **citable** signals you record in the config (G2 review counts, LinkedIn headcount, revenue claims — each with source URL, verbatim quote, and caveat): every signal is converted into revenue space first, calibrated within the vendor set and stratified by ACV band, then combined as a weighted geometric mean with the uncertainty spread and calibration table disclosed. The report's strategic-map bubbles become area-proportional to estimated revenue share — captioned "citable but NOT audited" — and without signals, dots are uniform and the caption says size carries no meaning.
|
|
146
|
+
|
|
129
147
|
## Governed enrichment: a diff you approve before third-party data touches your CRM
|
|
130
148
|
|
|
131
149
|
Every enrichment vendor ships fire-and-forget writeback. The **enrich layer** inverts that: declare once which fields come from which source under which conflict policy (`enrich.config.json` — sources, ordered match keys, field mappings, policy), then `enrich append` fills the gaps and `enrich refresh` keeps them current — with every write passing through the normal dry-run → approval → apply contract, and every value traceable to the source payload that produced it.
|
package/docs/api.md
CHANGED
|
@@ -59,8 +59,10 @@ release.
|
|
|
59
59
|
|
|
60
60
|
Commands: `login` / `logout`, `snapshot`, `audit`, `report`, `diff`, `merge`, `plans`,
|
|
61
61
|
`apply`, `suggest`, `call` (`parse` / `score` / `link` / `plan`), `resolve`,
|
|
62
|
+
`bulk-update`, `dedupe`, `reassign`, `fix`,
|
|
62
63
|
`market` (`init` / `capture` / `classify` / `worksheet` / `observe` / `fronts` /
|
|
63
|
-
`axes` / `
|
|
64
|
+
`axes` / `overlay` / `scale` / `report` / `refresh`),
|
|
65
|
+
`enrich` (`append` / `refresh` / `ingest` / `status`), `rules`, `profiles`, `doctor`.
|
|
64
66
|
Exit codes: `0` success · `1` error · `2` findings/regressions at the requested gate
|
|
65
67
|
(`--fail-on`, `--fail-on-new-findings`). `--json` everywhere; JSON output shapes are stable.
|
|
66
68
|
|
|
@@ -80,19 +82,59 @@ deliverable in markdown or self-contained HTML: severity counts, prose summary,
|
|
|
80
82
|
per-rule detail with capped examples, and next steps. `auditReportToMarkdown` /
|
|
81
83
|
`auditReportToHtml` expose the same rendering programmatically.
|
|
82
84
|
|
|
85
|
+
## Governed write verbs
|
|
86
|
+
|
|
87
|
+
Plan builders behind `bulk-update`, `dedupe`, and `reassign` — every one
|
|
88
|
+
emits a standard dry-run `PatchPlan` for the normal approve → apply chain:
|
|
89
|
+
|
|
90
|
+
- `buildBulkUpdatePlan(snapshot, options: BulkUpdateOptions)` with
|
|
91
|
+
`parseWhere` (filter expressions: `=`, `!=`, `~`, `!~`, `:empty`,
|
|
92
|
+
`:notempty`, `|` any-of, relational pseudo-fields) and
|
|
93
|
+
`isFilterableField`. Filters are re-verified per record at apply time;
|
|
94
|
+
`from:<sourceField>` values derive per record from the snapshot.
|
|
95
|
+
- `buildDedupePlan(snapshot, options: DedupeOptions)` with `dedupeKey` —
|
|
96
|
+
duplicate groups by normalized identity key, one `merge_records` per group,
|
|
97
|
+
deterministic survivor selection (`richest` / `oldest`).
|
|
98
|
+
- `buildReassignPlans(snapshot, options: ReassignOptions)` — one plan per
|
|
99
|
+
`ReassignObjectType`, account-lifted scoping, stage exclusions.
|
|
100
|
+
|
|
101
|
+
`fix` is CLI-only composition of existing surfaces (audit → suggest →
|
|
102
|
+
approve → apply for one rule).
|
|
103
|
+
|
|
104
|
+
## Enrich
|
|
105
|
+
|
|
106
|
+
Governed third-party enrichment (spec-first; `enrich.config.json` validated
|
|
107
|
+
by `parseEnrichConfig` / `loadEnrichConfig`, types `EnrichConfig`,
|
|
108
|
+
`EnrichFieldConfig`, `EnrichSourceConfig`): `buildEnrichPlan` matches staged
|
|
109
|
+
or pulled source records to CRM records (`matchSourceRecord` — ordered keys,
|
|
110
|
+
`MatchOutcome` of matched / unmatched / ambiguous) and emits fill-blanks-only
|
|
111
|
+
operations. `createFileEnrichRunStore` / `EnrichRunStore` is the profile-scoped
|
|
112
|
+
append-only run store (resume cursor, per-record/per-field `enrichedAt`
|
|
113
|
+
stamps read by `latestStamps` / `selectStaleWork`). `parseCsv` is the
|
|
114
|
+
dependency-free CSV intake; the Apollo client (`createApolloClient`,
|
|
115
|
+
`pullApolloRecords`, 429-aware with `Retry-After`) is the first `api`-kind
|
|
116
|
+
source.
|
|
117
|
+
|
|
83
118
|
## Market map
|
|
84
119
|
|
|
85
|
-
Newer surface (0.16–0.
|
|
120
|
+
Newer surface (0.16–0.23); shapes are settling toward the 1.0 contract. A live
|
|
86
121
|
model of the competitive category: claim taxonomy + vendor registry as a
|
|
87
122
|
reviewable `market.config.json` (`MarketConfig`, `MarketClaim`, `MarketVendor`,
|
|
88
|
-
`MarketAxis`), content-addressed
|
|
89
|
-
`loadCaptureTexts`), append-only observations
|
|
90
|
-
`MarketObservation`, `ObservationStore` /
|
|
91
|
-
profile-scoped under `<home>/market/<category>`),
|
|
92
|
-
derivations: `computeFrontStates` / `diffFrontStates`
|
|
93
|
-
`assessAxes` / `pcaTop2` / `axisPosition` (axis discovery),
|
|
123
|
+
`MarketAxis` — axes require `negativePole`/`positivePole` labels), content-addressed
|
|
124
|
+
page captures (`captureMarket`, `loadCaptureTexts`), append-only observations
|
|
125
|
+
(`ObservationSet`, `MarketObservation`, `ObservationStore` /
|
|
126
|
+
`createFileObservationStore` — profile-scoped under `<home>/market/<category>`),
|
|
127
|
+
and deterministic derivations: `computeFrontStates` / `diffFrontStates`
|
|
128
|
+
(front rule v1), `assessAxes` / `pcaTop2` / `axisPosition` (axis discovery),
|
|
129
|
+
`computeDirectives` / `computeOverlayStats` / `directivesToPlan`
|
|
130
|
+
(`market overlay` — observations × CRM snapshot × call corpus →
|
|
131
|
+
OCCUPY/PROMOTE/URGENT/RETREAT `MarketDirective`s, convertible to an
|
|
132
|
+
approval-gated plan of `create_task` operations), `computeScaleIndex` /
|
|
133
|
+
`scaleReportToText` (`market scale` — citable `ScaleSignal`s → within-set,
|
|
134
|
+
ACV-band-stratified revenue estimates with disclosed uncertainty), and
|
|
94
135
|
`marketMapToMarkdown` / `marketMapToHtml` (the field report; renders the
|
|
95
|
-
primary strategic 2×2 when `axes` / `primaryAxes` are configured
|
|
136
|
+
primary strategic 2×2 when `axes` / `primaryAxes` are configured, bubbles
|
|
137
|
+
area-proportional to estimated revenue share when scale signals exist).
|
|
96
138
|
|
|
97
139
|
Intensity readings are proposals: `classifyMarket` (LLM, bring-your-own-key,
|
|
98
140
|
provenance-marked) or `buildWorksheet` + `market observe` (agent/human). Every
|
package/llms.txt
CHANGED
|
@@ -44,9 +44,34 @@ elsewhere). Failed captures read UNOBSERVABLE, never ABSENT. `fronts --diff`
|
|
|
44
44
|
= deterministic front states + drift between runs; `axes` = PCA axis
|
|
45
45
|
discovery + orthogonality screen; `report` = self-contained HTML field
|
|
46
46
|
report; `refresh` = capture → classify → drift → report in one command.
|
|
47
|
+
`overlay --snapshot <crm.json> [--calls <files>]` joins observations to YOUR
|
|
48
|
+
CRM/calls (deterministic mention matching, no LLM) and emits OCCUPY/PROMOTE/
|
|
49
|
+
URGENT/RETREAT directives — each needs ≥1 observation + ≥1 CRM stat with
|
|
50
|
+
sample size; below thresholds = no directive; `--save` = approval-gated
|
|
51
|
+
create_task ops. `scale` = citable scaleSignals (sourceUrl + verbatim quote
|
|
52
|
+
each) → revenue-space estimates calibrated within-set by acvBand, disclosed
|
|
53
|
+
uncertainty; report bubbles ∝ estimated share only when signals exist.
|
|
47
54
|
Storage is profile-scoped under `<home>/market/<category>`. MCP:
|
|
48
55
|
`fullstackgtm_market_worksheet`, `fullstackgtm_market_observe`.
|
|
49
56
|
|
|
57
|
+
## Key invariants (governed write verbs)
|
|
58
|
+
|
|
59
|
+
`bulk-update <object> --where … (--set|--archive|--create-task)` filters the
|
|
60
|
+
snapshot into a dry-run plan; the FULL filter is re-verified per record at
|
|
61
|
+
apply time (plus mid-apply rechecks); equality filters double as
|
|
62
|
+
preconditions, `--require`/`--guard` add explicit ones, `--max-operations`
|
|
63
|
+
caps blast radius. `--set f=from:<source>` derives per-record values (empty
|
|
64
|
+
source = skip + count, never guess). `--archive` refuses records sharing an
|
|
65
|
+
identity key — merge with `dedupe` instead. `dedupe <object> --key
|
|
66
|
+
<domain|email|name>` = one merge_records op per duplicate group,
|
|
67
|
+
deterministic survivor (`--keep richest|oldest`); merges are irreversible and
|
|
68
|
+
stay low-confidence-capped at approval. `reassign --from <owner> --to
|
|
69
|
+
<owner>` = ownership handoff plans per object type; `--except-deal-stage`
|
|
70
|
+
also excludes records whose account has an open deal in that stage. `fix
|
|
71
|
+
--rule <id>` = audit one rule → suggest → approve at the confidence bar →
|
|
72
|
+
apply only with `--yes`. All four produce plans; none writes outside
|
|
73
|
+
approve → apply.
|
|
74
|
+
|
|
50
75
|
## Key invariants (enrich)
|
|
51
76
|
|
|
52
77
|
`fullstackgtm enrich` is governed enrichment: `append` pulls (Apollo, BYO key
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fullstackgtm",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.2",
|
|
4
4
|
"description": "Open-source agentic GTM ops framework: canonical GTM data model, pluggable deterministic audits, reviewable dry-run patch plans, approval-gated write-back with conflict detection, and cross-system entity resolution. HubSpot, Salesforce, and Stripe connectors included.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Full Stack GTM",
|