Skip to content

rosetta-research plugin

Seven-stage Product Family Research Pipeline. Takes a Salesforce Data Foundations product family from corpus consultation through to canonical graph content, which Stage 7 submits to the rosetta-app-server ingestion API as a content:ingest bundle (since 0.19.0, the DT-RX-036 switch; ADR-PL-024: the production graph is the system of record for content).

  • Latest shipped bundle: the current rosetta-research-<version>.zip in this directory, regenerated by make plugin-bundle-rosetta-research
  • Slash commands: /rosetta-research:intake, /rosetta-research:extract, /rosetta-research:author-nodes, /rosetta-research:author-patterns, /rosetta-research:provenance, /rosetta-research:author-adrs (v0.13.0), /rosetta-research:validate, plus /rosetta-research:run-all (v0.7.0 orchestrator — runs all seven stages in one chat). All eight commands accept a v0.8.0 opt-in --bootstrap flag and a v0.10.0 opt-in --target-patterns=N flag (PRODUCT_FAMILY [--bootstrap] [--target-patterns=N]). Since v0.16.0 every run also names its evidence inventory with the required --dataset=<id>@<n|latest> (a pinned rosetta-ugc release, e.g. --dataset=d360-core@2); see § "Evidence inventory: dataset releases (v0.16.0)". Since v0.26.0 a run may instead name a knowledge base with --kb=<domainKey> and read its release list from the app-server; see § "Knowledge base release lists (v0.26.0)". --bootstrap is for foundational runs that initialize the graph from a clean slate. --target-patterns=N (bootstrap-only, cap N=30) asks Stage 4 to author N patterns; if corpus capacity is short, Stage 4 pauses and surfaces three options. Two profiles replace that range: guidance/waf takes 1..40 and reference/d360-mcp-kb (v0.27.0) takes 1..60, each in either mode. product-docs/data360 keeps the default.
  • Profiles: --profile=guidance/waf (v0.15.0), --profile=product-docs/data360 (v0.20.0) and --profile=reference/d360-mcp-kb (v0.27.0). Each is one file under skills/product-family-research/references/profiles/.
  • Skill: product-family-research
  • License: Proprietary — © 2026 Keenan Vision LLC (see the repo LICENSE)

For the full method spec, read skills/product-family-research/SKILL.md. The extracted form under util/plugins/rosetta-research/ is the source of truth per Approach C; the shipped zip above is regenerated from it via make plugin-bundle-rosetta-research.

The run's review page on Curation > Runs (v0.28.1)

Once the run's lifecycle row exists, Stage 7 renders the run's HTML review page and uploads it with make report-family-publish BUNDLE=<run folder> URL=<base> (commands/validate.md, references/run-lifecycle.md). The console's Curation > Runs opens it in a new tab; the server side is platform MySQL 055 and app-server API 1.45.0. The upload is not a lifecycle transition, and a failed one never stops delivery.

The replacement runs' contract fixes, in every profile (v0.28.0)

Platform E3-S4-WP69. The d360-mcp-kb@1 run and E3-S4-WP68 each closed the same gaps with an operator ruling or a run-local script. 0.28.0 writes those fixes into every profile, the no-profile default included:

  • Names. Stage 7's paraphrase check (E8-I6) never receives documented names. A PlatformObject's name, label and alternateNames, any node's alternateNames, and a SourceArtifact's title are exempt. A PlatformObject label must still start with a letter or digit and contain no ", { or }.
  • Unique properties. Stage 3 checks VocabularyTerm.term and Stage 4 ContextPattern.patternId against a restored content snapshot. Before the commit, Stage 7 re-checks those two and ADR.adrId, SourceArtifact.artifactId and SourceArtifact.ugcDocumentId against the newest graph read. Under Q-1-1 (Vernon Keenan, 2026-10-31), an exact held term is reused by qualifiedKey. A case or plural variant is reported and blocked. MANIFEST records vocabulary_reused and unique_property_blocked.
  • Bundle limits. The builder refuses more than 20,000 CITED_BY evidence references, and an anchored CITED_BY whose SourceArtifact is outside the bundle. make content-ingest-build SPLIT=yes splits a run into dependency-ordered parts, with a proof that they equal the single bundle.
  • SemanticEntity entityType is entity, event, relationship or attribute, and nothing else.
  • Thin patterns are folded into a host or blocked, never padded (MANIFEST consolidation).
  • Review page. make report-family BUNDLE=<stage 7 run> reads product_family: data360.

Knowledge base release lists (v0.26.0)

rosetta-meta DT-RX-063 (RATIFIED 2026-10-29), platform E3-S4-WP66. A knowledge base (a canonical domain such as salesforce:rosetta-core) owns an ordered list of up to 8 frozen rosetta-ugc releases, edited on its Knowledge room page with a revision history. After a switch, rebuild with:

/rosetta-research:run-all <family> --kb=<domainKey>
  • Stage 1 reads the list once (GET /api/v1/curation/knowledge-bases/{domainKey}/datasets, app-server API 1.43.0, with your ROSETTA_API_KEY), fetches each release's manifest from rosetta-ugc as --dataset does, and requires the served, recomputed and listed hashes to agree, with each release frozen. The list replaces the pin registry as the third hash, so no pin PR is needed.
  • The bundle freezes the list (corpus/kb-list@<revision>.json) beside the manifests. MANIFEST.md records kb_domain_key and kb_list_revision with the usual dataset… fields; later stages copy them and never re-read the list. Lifecycle reports pass MANIFEST=, so revision 1 carries kbListRevision (references/run-lifecycle.md).
  • One way in. --kb and --dataset are mutually exclusive. --dataset and references/datasets.md work unchanged (DT-RX-063 Q-2-1). The Data 360 text-only profile keeps its profilePins there and runs with --dataset (Q-3-1).
  • Fail closed. An unreachable app-server, an unwritten (revision 0) or empty list, a release that is not frozen, or any hash mismatch stops the run. Nothing falls back to datasets.md.
  • Removing a release from a list retracts nothing (Q-6-1): it changes what the next run reads. DT-RX-061's activation switch takes a release's content out of live retrieval.
  • make kb-datasets KB=<domainKey> OUT=<dir> in a rosetta-platform checkout runs the same list read and checks, for an operator who wants to look before a run.

Every ContextPattern ADDRESSES a BusinessIntent (v0.25.0)

util/plugins/decision-traces/dt-pa-010-product-docs-business-intent-coverage.md (RATIFIED 2026-10-29) closes the gap that left most WP41 Data 360 patterns unreachable by retrieval's graph path. Under every profile, Stage 7 hard-fails a ContextPattern that ADDRESSES no BusinessIntent unless MANIFEST bi_coverage_exceptions names an operator ruling for it, and MANIFEST gains bi_coverage. Under --profile=product-docs/data360, reconciliation synthesizes BusinessIntents from the run's own patterns, grounded in a subset of their citations and never invented; an existing BusinessIntent is reused only at a full fit; each pattern has 1 or 2 ADDRESSES at relevance 0.8 or 0.6; and util/python/d360_authoring fails before bundle build with a D360-BI-* code (platform E3-S4-WP64).

Tech Notes outrank conflicting SF material and must be cited (v0.24.0)

rosetta-meta DT-RX-059 (RATIFIED 2026-10-26) makes an admissible Tech Note the highest-weight evidence in a run. Where a note and an SF item make conflicting claims a node relies on, the node follows the note and does not cite the SF item; each conflict is a row in extraction.md § "Tech Note precedence". Two conflicting notes, or an SF item revised after the note's approval, stop the run. Every admissible note document in the run's inventory must be cited by at least one authored ContextPattern or ADR, or Stage 7 fails; there is no flag to skip one. Under the Data 360 profile every tech-note member must be cited (platform E3-S4-WP58).

Tech Notes as dataset members (v0.23.0)

rosetta-meta DT-RX-055 (RATIFIED 2026-10-25) retires the rtn-core dataset. A Rosetta Tech Note's SME-approved version is a member of whichever datasets include it, under each dataset's own access rules, so a run reads notes through the releases it already pins (d360-core, waf-core, and so on). An RTN member of a registered release that is not engagement-scoped is primary evidence; the app's content:ingest dry run proves its approval, and a note that is not provably approved is refused, never downgraded to KV. One note at one version in two releases is one item; one note at two versions stops the run. Under --profile=guidance/waf an RTN member skips the pair-file filter and is read from its release blob. The rtn-core@1 pin and the make rtn-* importer are gone (platform E3-S4-WP56).

Authoritative run lifecycle (v0.22.0)

Every connected execution has one stable research ID from Stage 1 and an exactly increasing revision stream across all seven stage-specific artifact IDs. Each command reports its running, blocked, failed or cancelled transition through make research-run-report; Stage 7 alone may report completed, and only with the event ID returned by committed content ingestion. The full retry, scope, unavailable and MANIFEST contract is in skills/product-family-research/references/run-lifecycle.md.

The app-server ledger, not IngestionEvent, is authoritative for research lifecycle. Reporting is producer-only and confers no review-verdict rights.

Governed RTN external citations (v0.21.0)

An admissible RTN-NNN note is no longer a SourceArtifact this plugin authors. Stage 5 and Stage 6 reference the existing governed note-document node at salesforce:rosetta-core::sourceartifact:ugc-<documentId> and carry the frozen dataset item's exact ugc:version/<versionId> and sha256:<64 lowercase hex> values on every CITED_BY. The bundle builder refuses a UGC node write, alternate/run-domain key, incomplete or malformed tuple, tuple on an ordinary source, and direct attachment shortcut. This is a source candidate under DT-RX-048; publication and runtime compatibility await the separately reviewed app verifier and release sequence.

Statuses and enums (v0.18.0)

Every new ContextPattern is draft and every new ADR and BusinessIntent proposed, the SME review lane's pending states and the only statuses the ingestion API takes: a run never writes a ContextPattern validated, an ADR accepted, a BusinessIntent active or a status-less one, and a node already in the graph is MATCHed by qualifiedKey, never re-emitted with its graph status (platform E9-S1-WP14; commands/run-all.md § "Statuses"). --hard-promote is refused. A corpus Deploy phase maps to Validate, and VocabularyTerm.category may be concept (metamodel v1.16.0), which the app-server's content:ingest catalog has taken since v0.10.0 (docs/decision-traces/e9-s1-wp2-plugin-ingestion.md Q-B-1, Q-C-3).

Ingestion: the only path (v0.19.0)

Since the DT-RX-036 switch (platform E9-S2-WP1; ADR-PL-024 in effect) every run delivers a rosetta-app-server content:ingest bundle, and nothing else:

  • No seeds target. No stage writes into a repo's db/seeds/, which left main at the switch. The Stage 3–6 Cypher stays inside the run's bundle (bundle-internal db/seeds/ paths) as the review artifact and the source Stage 7 derives the bundle from (make content-ingest-build in the repo snapshot). --target=ingestion is a no-op alias for this release; --target=seeds is a hard fail that points at the frozen baseline tag v0.27.0, which holds the historical seed corpus and the last tagged seed-era plugin (0.18.0).
  • Delivery. Stage 7 submits the bundle through MCP rosetta_ingest_content (preferred) or a REST POST to --ingest-url (default https://api.rosetta-design.com), always a dry run first, and commits only after the operator confirms the graph target in the session. The production API is a legitimate target; ingestion needs a platform admin's key. Content lands at draft / proposed, and only SME review moves it.
  • Existing content comes from the graph: the rosetta MCP read tools live, or offline a local graph restored from a content snapshot (make content-snapshot-restore). Never an old repo zip's db/seeds/.

Details: commands/run-all.md § "Ingestion" and § "Existing content"; commands/validate.md Steps 4b and 4c.

ADR authoring — new Stage 6 (v0.13.0)

v0.13.0 grows the pipeline from six stages to seven by inserting a new authoring stage, author-adrs, between Provenance (now Stage 5) and Validate (now Stage 7). The new Stage 6 emits corpus-baseline ADR Cypher as a first-class canonical node type — joining the six node types Stages 3-4 already author — with (adr)-[:GOVERNS]->(cp) edges to the patterns each decision constrains, (sa)-[:CITED_BY]->(adr) edges reusing the governed patterns' SF-tethered sources, and a ProvenanceEvent per ADR (performedBy="rosetta-research:author-adrs" — honest plugin-run attribution). It runs after Provenance so the GOVERNS targets (ContextPattern, 08L) and ordinary or governed-external CITED_BY source identities (09L) are established; the ADR file (<NN>L-<product>-adrs.cypher, generally source-artifacts-prefix + 1, e.g. 10g) loads after them. Each family carries 3-7 corpus-baseline ADRs, one per major irreversible architectural decision shared across patterns (not one-per-pattern). This is the sustainable, plugin-authored path the transitional hand-authored db/seeds/10g-data-360-adrs.cypher converges toward; v0.13.0 builds the path but does not retire 10g. Ratifying DT: docs/decision-traces/d360-adr-authoring-plugin-path.md (Option 1, conditional on the structural-constraint precondition); operationalized by E3-S2-WP11.

The ADR emit is born behind the three structural-constraint layers that closed the v0.12.0 enum drift, not free-form runtime authoring: (1) templated emit — commands/author-adrs.md ships concrete MERGE-on-qualifiedKey templates with "STOP and surface; do NOT substitute a close-enough value" language on every enum-valued field (status, GOVERNS scope); (2) static self-gate — Stage 7 (validate) hard-fails on ADR shape, GOVERNS contract, and provenance-coverage violations and refuses to ship a non-conformant bundle; (3) live-graph gate — scripts/neo4j/d360-invariants.sh gains INV-D16 (ADR shape), INV-D17 (GOVERNS contract), and INV-D18 (ADR provenance coverage), enforced at load time alongside INV-D1…D15. No db/schema/ change — the existing ADR label and GOVERNS contract are used as-is.

Guidance-corpus profile (v0.15.0)

--profile=guidance/waf runs the pipeline over the Salesforce Well-Architected Framework corpus instead of a product family. The profile is one file, skills/product-family-research/references/profiles/waf.md; the rules that use it sit in delimited <!-- BEGIN if-profile guidance --> blocks in each command and reference. Without the flag, nothing changes.

  • One run per pillar pair. The PRODUCT_FAMILY argument names the pair (waf-trust, waf-reliability, waf-operational-excellence, waf-resource-and-cost-optimization, waf-fairness). Trust runs first in bootstrap mode; the rest run in extension mode.
  • Local corpus (0.15.2). The run is a Claude Code session in the checkout. It reads the corpus in place from outputs/tools/waf-capture/<run-id>/normalized/ (Markdown plus manifest.json), with no upload and no Drive (docs/decision-traces/waf-local-corpus-run.md, RATIFIED 2026-10-01). Stage output goes to outputs/plugins/rosetta-research/<run-id>/bundle/.
  • Domain split. Everything a WAF run mints is salesforce:waf-core, platform facts included (0.15.4). A platform object, engine function or semantic entity already in the graph for the same fact is reused, never re-minted.
  • Gates. Up to 40 patterns in either mode; ≥2 ADDRESSES / ≥0 REFERENCES / ≥2 RECOMMENDS per pattern; ≥3 evidenceAnchors per pattern; 3–12 ADRs; every file in the pair consumed; no web sources.
  • Draft only. --hard-promote is refused.
/rosetta-research:run-all waf-trust --dataset=waf-core@1 --profile=guidance/waf --bootstrap --target-patterns=30

Ratified by docs/decision-traces/rosetta-research-v0.15.0-guidance-corpus-profile.md and docs/decision-traces/waf-core-domain-key.md (platform Epic E8, E8-S1-WP2).

Data 360 text-only profile (v0.20.0)

--profile=product-docs/data360 is the revised Data 360 authoring path. It accepts exactly one immutable, registered text-only derivative release. Stage 1 verifies its manifest, exact qualified scope-inventory hash, d360-core@2 lineage, complete retained/excluded reconciliation, and every derivative blob, then seals those bytes. Stages 2–7 read only that sealed snapshot.

The profile refuses d360-core@2 as authoring input, supplemental links, tables/table rows, graphics/OCR, visual-dependent passages, web/search/Drive sources, additional datasets, wrong versions, excluded anchors, and stale or unscoped caches. It requires no companion, trusted-reviewer list, or visual receipt. Exclusion is not acceptance, and its complete retained-scope coverage is not full-corpus coverage.

The authorized publication is registered as d360-text-only@1, manifest sha256:14111f89d51531a042f963e94f7a2dfc3a07f7673d8d7ae49fd49fd1a7907a4e, with its exact inventory version and hash. The profile still fails before content reads on any mismatch. See skills/product-family-research/references/profiles/data360.md.

Since v0.23.0 the profile's pins are a list: d360-text-only@1 stays WP41's pin, unchanged, and d360-text-only@2 is registered as pending (not yet published; a run on it refuses). @2 keeps the same derivative and scope inventory and adds tech-note members: SME-approved Markdown Rosetta Tech Notes, placed after the articles and before the inventory, outside block reconciliation, cited only through the DT-RX-048 external endpoint (rosetta-meta DT-RX-055 T4, T7, T8; platform E3-S4-WP57). Publishing @2 and installing its runtime pin are operator acts on Vernon's separate go.

Reference profile (v0.27.0)

--profile=reference/d360-mcp-kb is the first profile of kind reference. It runs over d360-mcp-kb@1, the Data 360 MCP knowledge base: 3,421 pages, almost all per-object reference pages. The profile is one file, skills/product-family-research/references/profiles/d360-mcp-kb.md, and the rules that use it sit in <!-- BEGIN if-profile reference --> blocks in the commands and references. Without the flag, nothing changes.

/rosetta-research:run-all data-360 --dataset=d360-mcp-kb@1 --profile=reference/d360-mcp-kb [--bootstrap] --target-patterns=<N up to 60>

The mode is the operator's choice: pass --bootstrap or leave it out for extension mode. The run's N and mode wait on Vernon's go (dt-pa-011 § "After the merge").

  • Entry. PRODUCT_FAMILY is data-360. The run names exactly one --dataset=d360-mcp-kb@1. --kb and --hard-promote are refused. --target-patterns=N accepts 1..60 in bootstrap or extension mode.
  • Local run. The profile runs as a local Claude Code session in the operator's checkout, normally run-all in one session, with output under outputs/plugins/rosetta-research/<run-id>/. Stage 1 seals the verified page bytes in its run folder's working/corpus-cache/<sha256-hex> (MANIFEST corpus_cache). Stages 2–7, the generator and Stage 7's re-derivation read only that cache, re-verify each hash and never refetch. A stage that cannot read the cache, such as a fresh Claude.ai chat, stops.
  • Practice lane. The default pipeline, up to 60 patterns. The default gates hold: ≥3 ADDRESSES, ≥3 REFERENCES, ≥3 RECOMMENDS, ≥2 cross-pattern edges and an SF tether per pattern, 3–7 ADRs, and the BusinessIntent coverage gate (v0.25.0). The product-docs BusinessIntent synthesis and its ≤2 rubric do not apply.
  • Catalog lane. Stage 3 runs a generator in the run's working/tools/ that executes the profile's spec. It mints one PlatformObject per documented object: 972 standard DMOs, 165 connector types and 801 standard mapping templates, 1,938 in all. The generator emits no edge. Stage 5 adds one SourceArtifact per cataloged or reused page, with one CITED_BY, the catalog lane's only edge. No model authors a catalog fact. Field lists, mapping field pairs and connector parameters stay in the release.
  • Key space. salesforce:rosetta-core, token data-360-mcp-kb, letter h; references/uid-allocation.md records h for this profile, and the next product family takes i. Each template-matched page holds one number N from 1001, in code point order of Source path across the three families, for po-h-N and sa-h-N. An existing object with the same apiName is reused, never re-minted, so the run needs a restored content snapshot; a reused page leaves po-h-N as a gap and keeps sa-h-N.
  • Stage 7. It re-derives and gates every catalog node. Before the build it counts the run's nodes and edges against the content:ingest limits; over a limit, or the builder's "split the run" refusal, is a pause, never a Cypher fix. It draws a 25-node sample (12 DMO, 8 standard-mapping, 5 connector) whose seed, population and draw come from the research run id by the profile's gates.sample; the commit waits for a named go on it (catalog_sample_go). MANIFEST records one disposition per page and the coverage figure.
  • Statuses. Patterns land draft; ADRs and BusinessIntents land proposed.

0.27.1. The replacement run committed d360-mcp-kb@1 on 2026-10-30 (eventId data-360-data-360-bootstrap-stage1-20261030-160351), so a further run over @1 is extension mode under its own ruling. The patch folds in the four profile defects that run recorded, each as Vernon ruled it there:

  • Gate (f). The paraphrase check runs on catalog descriptions. A catalog name and label are page-identity strings copied from the H1, exempt like SourceArtifact titles; a label must instead start with a letter or digit and contain no ", { or }.
  • Connector H1 debris. The title rule drops the Connector"}') or "}') prefix seven @1 connector pages open with. The connector family's keyPins keeps the four connector-connector-… slugs ingested on 2026-10-30, and a page whose key is already in the graph is reused by that key, so no key changes and no ingested string is rewritten.
  • Classes. classTable adds Data Action Target → endpoint (DataCloud), Named Credential → endpoint (SalesforcePlatform) and External Client App → interface (SalesforcePlatform).
  • VocabularyTerm terms. vt_term makes a term unique graph-wide, and the dry run cannot see a clash. Stage 3 checks every term against the graph, in bootstrap mode too, and reuses an existing one by qualifiedKey (MANIFEST vocabulary_reused); Stage 7 repeats the check before the commit.

Ratified by util/plugins/decision-traces/dt-pa-011-research-reference-profile.md (RATIFIED 2026-10-30, Q-A-1 to Q-I-1), under rosetta-meta DT-RX-064 (platform E3-S4-WP67).

Bootstrap mode (v0.8.0)

All eight slash commands accept an opt-in --bootstrap flag that signals a foundational run: the graph is initialized from a clean slate rather than extended on top of existing coverage. The flag is parsed from $ARGUMENTS by literal-token match — pass it exactly once at any stage (or once at the orchestrator) and the mode propagates through the cumulative bundle's MANIFEST.md.

What changes in bootstrap mode:

  • Stage 1 (intake). Step 5 (existing-coverage inventory) is skipped; research-notes.md records "Bootstrap mode — no prior graph content assumed." Corpus consultation, glossary capture, and alias-table normalization run normally.
  • Stage 3 (author-nodes) and Stage 5 (provenance). UID ranges allocate from the canonical first slot per node label (vt-<letter>-001, sa-<letter>-001, etc.), contiguous, with no header comment claiming continuation of any prior range.
  • Stage 4 (author-patterns). Cross-pattern wiring (INTEGRATES_WITH / BUILDS_ON) targets only patterns authored within the same bundle — no MATCH against an assumed pre-existing graph node. Bundles with fewer than 3 patterns cannot satisfy the ≥2 within-bundle wiring requirement; the plugin halts with a pause-and-ask.
  • Stage 7 (validate). Three additional invariants fire: (a) every MATCH resolves to a node authored within the bundle (with the narrow canonical governed RTN citation exception, and from 0.28.0 each vocabulary_reused term); (b) UID ranges per node label are contiguous 001..N; (c) header text and inline comments do not claim continuation of any prior range (soft warning).
  • Bundle. Filename embeds bootstrap infix (rosetta-research-<product>-bootstrap-stage7-<ts>.zip); MANIFEST.md records mode: bootstrap.

What does not change: the v0.4.0+ corpus tethering, scope discipline, glossary normalization, alias-table normalization, five-field identity, ProvenanceEvent emission, and producer-only contract all apply identically. Bootstrap mode affects how the run interprets prior graph state; it does not relax any constitutional or content-quality guard.

Omit the flag for normal extension runs (the v0.7.0 default).

Evidence inventory: dataset releases (v0.16.0)

Since 0.16.0 the inventory is a frozen, numbered rosetta-ugc dataset release (contract X-C6). The inventory CSV it replaced left main at the E9 switch. Ratified by util/plugins/decision-traces/dt-pa-009-rosetta-research-ugc-dataset-manifests.md.

  • --dataset=<id>@<n|latest> is required on every run that does not name a knowledge base with --kb (v0.26.0; § "Knowledge base release lists (v0.26.0)"). There is no default. The release must be in the pin registry in skills/product-family-research/references/datasets.md (d360-core@1, d360-core@2, d360-mcp-kb@1 (since 0.25.1), d360-text-only@1 and waf-core@1; rtn-core@1 was retired in 0.23.0); adding a pin is a reviewed plugin patch.
  • Stage 1 verifies and freezes it. The served manifestSha256, the hash recomputed over items[] (RFC 8785) and the registered pin must agree. The verified manifest goes into the bundle as corpus/<id>@<n>.manifest.json; Stages 2–7 read only that copy.
  • Live or from a file. A local session fetches it with ROSETTA_API_KEY (always with a User-Agent; Cloudflare refuses Python's default). A session that cannot reach the API passes --dataset-file=<path>, made with make ugc-manifest DATASET=<id>@<n> OUT=<path> in a checkout.
  • Nothing else changes. Each item's attributes carries the old CSV columns verbatim, so the filters, routing, phase mapping and Document name identity below work as before. No CSV fallback exists.
  • Tech Notes (v0.17.0; dataset members since v0.23.0). --dataset is repeatable (since v0.17.0). Since v0.23.0 there is no Tech Note dataset: an SME-approved note version is a member of the product releases that include it (rosetta-meta DT-RX-055). An item with Scope = RTN from a registered release that is not engagement-scoped is primary evidence, exactly as SF is, once the content:ingest dry run proves its approval; a note that is not provably approved is refused, never counted as KV. Curators include notes in datasets from the console; the make rtn-* importer was retired. Since v0.21.0 the note document is an external citation endpoint only; the plugin never clones or updates its governed SourceArtifact.

Evidence-corpus discipline (v0.4.0+, refined v0.5.0, v0.6.0, v0.9.0)

The evidence-corpus contract described here was finalized at v0.9.0 and carries forward unchanged; since v0.16.0 it applies to the pinned dataset release (above), whose item attributes carry the CSV columns:

  • Product Line filter (added v0.5.0). Stage 1 filters the inventory to items whose Product Line matches the $ARGUMENTS product family before applying the scope and relevance filters.
  • Scope-aware admissibility. The Scope attribute maps to the rosetta-platform domain hierarchy: SF rows ground canonical content, KV rows are admissible only as supporting citations alongside ≥1 SF source, NTO rows are out of scope for this plugin entirely (they belong to rosetta-archaeology).
  • Corpus-first source inventory. Stage 1 consults the inventory before any web research; web sources are admitted only to fill documented Corpus Coverage Gaps.
  • evidenceSources on every canonical content node (v0.9.0). v0.6.0 required evidenceSources on every authored ContextPattern; v0.9.0 extends the contract to every inheritable-label canonical content node — VocabularyTerm, SemanticEntity, PlatformObject, EngineFunction, BusinessIntent. Stage 4 (patterns) and Stage 3 (other nodes) require ≥1 SF-scoped corpus reference, or an explicit corpusGap=true operator-acknowledged liability marker. Stage 5 emits (SourceArtifact)-[:CITED_BY]->(node) edges to every cited canonical node, not just patterns. Stage 7 (validate) mirrors the per-pattern gate onto all five sibling labels.
  • corpusInventoryRef / corpusScope / corpusGap on every SourceArtifact. Stage 5 marks every source's origin and scope tier in the graph, with the same pair echoed in the ProvenanceEvent payload for C-6 audit.
  • Per-row INGESTED tracking retired in v0.5.0. v0.4.0 emitted an evidence-ingestion-delta.csv for the operator to apply on PR merge; the source CSV no longer carries an INGESTED column, so the delta artifact is dropped. Sessions are now independent.
  • Glossary + product-name-alternatives normalization (added v0.6.0). Two operator-curated reference tables at docs/evidence/glossary.csv (verbatim definitions for terms cited as VocabularyTerm, with a default Type filter that excludes general business jargon) and docs/evidence/product-name-alternatives.csv (canonical-product alias graph for Stage 2 product-reference normalization and Stage 3 PlatformObject.alternateNames authoring). VocabularyTerm.aliases and PlatformObject.alternateNames are new node properties added in v0.6.0.

Full protocol: skills/product-family-research/references/evidence-corpus.md.

Bundle regeneration after future edits is one Make target away: make plugin-bundle-rosetta-research. See the util/plugins/README.md "Bundles are derived" note.

Installation

When you run claude from a rosetta-platform checkout, this plugin is auto-discovered via .claude/settings.json. The /rosetta-research:* slash commands become available automatically; first-run users get a "trust this folder?" prompt, subsequent runs are silent. No install step beyond the trust prompt.

This is the right path for plugin authoring and repo-internal use. Cowork upload (next section) is the right path for production research sessions where the user is iterating on uploads.

Claude (web / Cowork)

  1. Open a Cowork chat.
  2. Customize → Plugins → + → upload the current rosetta-research-<version>.zip regenerated by make plugin-bundle-rosetta-research.
  3. Confirm /rosetta-research:intake appears in the slash-command palette and that its argument-hint shows PRODUCT_FAMILY --dataset=ID@N|ID@latest … (v0.16.0 sanity check).

Claude Code (CLI)

The bundle follows the standard plugin layout (.claude-plugin/plugin.json, commands/, skills/), so it can also be loaded as a local Claude Code plugin:

mkdir -p ~/.claude/plugins
unzip -o util/plugins/rosetta-research/rosetta-research-<version>.zip \
  -d ~/.claude/plugins/

Restart your Claude Code session and the /rosetta-research:* commands become available. Refer to the Claude Code plugin documentation for marketplace-style registration if you prefer a managed install path.

The plugin reads existing content and submits its bundle through the rosetta connector (MCP) when the session has it, or over REST with a key (ROSETTA_API_KEY to read; a platform admin's key, ROSETTA_INGEST_KEY, to submit). It never reaches into your local checkout, your Neo4j, or your MySQL.

Inputs every session expects

Drop these in the chat's uploads area before invoking the slash command:

Stage Required uploads
1 — /rosetta-research:intake rosetta-platform-VERSION.zip; plus the verified <id>@<n>.manifest.json when the session cannot reach api.rosetta-design.com (--dataset-file, v0.16.0)
2 — /rosetta-research:extract repo zip + rosetta-research-<product>-stage1-*.zip
3 — /rosetta-research:author-nodes repo zip + Stage 2 bundle
4 — /rosetta-research:author-patterns repo zip + Stage 3 bundle
5 — /rosetta-research:provenance repo zip + Stage 4 bundle
6 — /rosetta-research:author-adrs repo zip + Stage 5 bundle
7 — /rosetta-research:validate repo zip + Stage 6 bundle
All — /rosetta-research:run-all repo zip (plus the manifest file as for Stage 1); --dataset (or --kb, v0.26.0) is passed once and travels in the bundle (v0.7.0 orchestrator runs Stages 1-7 in one chat; per-stage bundles produced as checkpoints; v0.8.0 --bootstrap flag propagates from the orchestrator invocation through every stage's bundle)

Produce the repo zip from a clean checkout:

cd ~/path/to/rosetta-platform
git archive --format=zip HEAD > /tmp/rp.zip

Each stage emits ONE cumulative zip — Stage 7's bundle contains everything Stages 1–6 produced plus the validation outputs. Re-upload that bundle as the prior-stage input to the next stage.

Delivering the output (v0.19.0)

The bundle is not applied to a checkout: since the switch a checkout has no db/seeds/, and content reaches the graph only through the ingestion API. Stage 7 (validate) builds the content:ingest bundle under outputs/plugins/rosetta-research/<run-id>/ingest/ and runs the delivery step itself:

  1. Dry run. MCP rosetta_ingest_content with dryRun: true (preferred), or the REST fallback to --ingest-url (default https://api.rosetta-design.com). A 422 lists every failure; the fix goes into the Cypher at the stage that wrote it, never into the bundle.
  2. Confirm. The plugin shows the plan and names the graph target, and waits for the operator's confirmation.
  3. Commit. The same bundle, committed. It lands at draft / proposed; an SME verdict in the review surface is the only way on.

When the session could not submit, or the operator stopped at the dry run, VALIDATION-CHECKLIST.md (inside the bundle at outputs/plugins/rosetta-research/<run-id>/VALIDATION-CHECKLIST.md) gives the steps. From a rosetta-platform checkout, with a platform admin's key in ROSETTA_INGEST_KEY:

make content-ingest-submit PAYLOAD=<bundle> URL=https://api.rosetta-design.com              # dry run
make content-ingest-submit PAYLOAD=<bundle> URL=https://api.rosetta-design.com COMMIT=yes   # commit, once the target is confirmed

There is no content PR, make seed-diff, make intake-validate or make prod-migrate step: those read or load seed files, which left main at the switch.

ADR-PA-008 compliance (v0.9.0)

ADR-PA-008 establishes that plugin runtime outputs (manifests, validation checklists, eval invocation scripts, run logs) land at outputs/plugins/rosetta-research/<run-id>/ in the repo root, gitignored, never auto-promoted.

v0.9.0 ships compliance. The bundle's internal layout now places every non-canonical artifact (MANIFEST.md, STATIC-ANALYSIS-REPORT.md, VALIDATION-CHECKLIST.md, research-notes.md, extraction.md, sources.md) under outputs/plugins/rosetta-research/<run-id>/ paths inside the bundle, where <run-id> is <product>-stage<N>-<timestamp> (extension) or <product>-bootstrap-stage<N>-<timestamp> (bootstrap). The run's Cypher sits at bundle-internal db/seeds/ paths per ADR-PA-002; since 0.19.0 it never lands in a checkout.

Tracker entry in util/plugins/README.md § "Migration to ADR-PA-008" drops rosetta-research from TODO to Complete at v0.9.0.

Constitutional alignment

The plugin operates within the rosetta-platform invariants (CLAUDE.md): C-2 (Cypher canonical for schema; since the switch the graph is the system of record for content, ADR-PL-024), C-4 (Make is the user surface), C-5 + metamodel v1.19.0 §5 + §6 (five-field identity plus projectId), C-6 (ProvenanceEvent on every mutation), C-7 (producer-only — it never imports from rosetta-app-server; submitting a bundle to its API is a runtime call, not an import).

The plugin never invokes make, cypher-shell, mysql, docker, or any command on your machine. In its own workspace it runs the repo snapshot's make content-ingest-build, and it submits only after you confirm the graph target.

Reporting issues

File against this repo with tag [plugin]. Include:

  • the bundle filename (carries the version),
  • which stage you were running,
  • the upload manifest the plugin echoed in its first response,
  • any failure the dry run listed (ingest/dry-run.json) or the builder's refusal text, and VALIDATION-CHECKLIST.md.

This page as Markdown — for pasting into Claude or another assistant · llms.txt