Commit Graph

36 Commits

Author SHA1 Message Date
dependabot[bot] bb59f8d4db CI: bump hashgraph-online/ai-plugin-scanner-action (#119)
Bumps [hashgraph-online/ai-plugin-scanner-action](https://github.com/hashgraph-online/ai-plugin-scanner-action) from 1.2.528 to 1.2.537.
- [Release notes](https://github.com/hashgraph-online/ai-plugin-scanner-action/releases)
- [Commits](https://github.com/hashgraph-online/ai-plugin-scanner-action/compare/b402d3b3aaa8f59df8e8aa427dc97694a0af2819...bbeac35a403ccc95459cdbe68249916e6149182c)

---
updated-dependencies:
- dependency-name: hashgraph-online/ai-plugin-scanner-action
  dependency-version: 1.2.537
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-02 16:40:30 -07:00
Auree Aubert bf23619313 Stop documenting the first-party enrichment provider (#122)
* Stop documenting the first-party enrichment provider

Its playbook, its 21 priced actions, and every recipe step that led with it
are removed. Each one now leads with the rung the pack already named as its
fallback, so nothing here is invented — the replacements were sitting in
stage-action-map.md and alternatives.md the whole time.

The substitutions:

    firmographics   aiArk.enrichCompany (0.01) -> companyEnrich (0.25) -> waterfall (1)
    person          aiArk.enrichPerson (0.1) -> waterfall.enrichContact (2)
    funding         enrichCrm.getFunding (1), now the catalog's only one
    technographics  builtwith.getDomainSummary (free) -> enrichDomain (1)
    dedupe          free storage query against the workspace's own models

That last line is the one worth reading twice. The match actions existed to
mint an id the other actions required; every replacement keys on the domain
or a LinkedIn URL, so a step that cost 0.5/record now costs nothing.

The event feed has no replacement and the recipes say so. fetchBusinessEvents
took a timestamp_from and nothing else in the catalog does, so funding-watch,
re-engagement and lost-deal-revival are rewritten as a diff: re-pull, compare
against the stored round date, keep what moved. Cadence becomes the only cost
dial, which is why funding-watch's default drops from daily to weekly.

Every credit budget was recomputed rather than relabelled:

    build-tam        2,955 -> 2,210   (500 companies + 1,500 contacts)
    prospecting P2     821 ->   107   (200 verified prospects)
    icp-discovery      602 ->   204   (200 deals)
    context bootstrap    3 ->     1

Catalog counts now follow the generated data file rather than the older
hand-kept figure: 136 integrations, 176 credits-based actions of 513.

Also bumps the CLI pin 1.0.66 -> 1.0.78.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019wkwbhrEoE5KW9A1CKBmcA

* Fix the three generated artifacts the removal invalidated

CI caught what the local lint could not: skills-lint.mjs is only one of five
checks, and the other four all had something to say.

llms.txt was stale — it is generated from the skill descriptions, and
cargo-gtm's dropped a provider from its roster.

The codex package build enforces override version == upstream version, so
bumping only .github/package-overrides/cargo-quickstart.SKILL.md to 1.0.3 broke
it. The guard exists to stop the override silently shipping last month's demo,
so the fix is to bump both, not to revert the override.

That build also patches literal source strings at package time, and one anchor
ran through a line this branch rewrote:

    snitcher.searchSessions (0 cred) -> cargo.matchProspect
    snitcher.searchSessions (0 cred) -> aiArk.reverseLookup (0.05)

The edit strips the visitor-de-anonymisation path from the packaged skill, so a
silent miss would have shipped it. Re-anchored, and every other PACKAGE_EDITS
find string verified against the tree — 1 broken, now 0.

Also drops the packaged cargo-connection description from 138 integrations to
136, matching the repo.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019wkwbhrEoE5KW9A1CKBmcA

* Say where revenue went, and that employee ratings went nowhere

Removing the provider took two data points off the map without replacing the
map entry, which is the failure mode this recipe's own feasibility gate exists
to prevent: an attribute that quietly stops being answerable reads the same as
one nobody asked for.

They are not the same case, so they get different rows.

Revenue and NAICS survive. companyEnrich.enrichByDomain (0.25) returns them in
the same call as firmographics, employees, funding and socials — so it fills
several rows at once and the row says that, because the per-account arithmetic
in step 4 gets it wrong otherwise.

Employee ratings have no successor at any price. Nothing credits-based in the
catalog returns Glassdoor-style employer reputation. The row says none, and
says to report it as a research note rather than substituting a scrape that
reads like the real thing — which is the recipe's stated position on valuable
attributes with no obtainable source, applied to itself.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019wkwbhrEoE5KW9A1CKBmcA

* Fix the data-flow breaks the provider swap left behind

Bugbot found eight, all real, and verifying them turned up five more. The
pattern in every case is the same: I replaced an action but left the code that
consumed its output reading the old response shape, so the step still runs,
still bills, and quietly returns nothing.

Response-shape breaks:

  funding-watch      Pattern A still filtered funding_rounds[].announced_date
                     while Pattern B read lastFundingDate. The 90-day select
                     matched nothing, so the primary path returned an empty
                     list after a paid pull.
  re-engagement      Step 5 read .results[] and .events[] from a file step 3
                     now writes as a bare array. Funding branch always empty.
  lost-deal-revival  Step 4 read .events[0] and expected a deal_id that
                     getFunding does not return. Step 3b now carries deal_id
                     through, which is the only place it exists.

Wrong-source breaks:

  re-engagement      The diff read last_funding_round_at off the Contacts
                     segment. It is a Companies column, so the stored date was
                     always empty and every account re-flagged every week. Now
                     queries the Companies model, and fans the company-level
                     signal back out to contacts, since step 5 unions on email.
  build-tam          Step 4 keyed searchLeads on .linkedinId from the
                     aiArk.enrichCompany output. No enrichment action returns a
                     Sales Navigator accountId. Now carried from the sourcing
                     step, with an explicit gate for rows that have none.
  guide              snitcher.searchSessions identifies a COMPANY; I had
                     chained it into aiArk.reverseLookup, which needs an email
                     or phone. Its own playbook says to route identified
                     domains through the enrich chain.

Budget break:

  prospecting        P2 step 5 ran FullEnrich over every lead while the budget
                     quoted the residue. 200 credits against 60. P1 had the
                     gate; P2 did not.

Pre-existing, fixed because the fixes above sit inside them:

  icp-discovery      [.[] | {domain}] over storage query execute output, which
                     is {rows: [...]}. Enriched one null domain, not 200.
  jq inputs[N]       `inputs` is a generator, not an array, so the union
                     expressions in re-engagement and lost-deal-revival errored
                     out. Slurped to [inputs] as $in.

Every rewritten jq expression was run against fixtures rather than eyeballed.

Also five provider mentions the sweep missed, because they wrote it as bare
`cargo` with a price rather than cargo.actionName: societeInfo, snitcher,
enrichCrm, linkedin, oceanio, apolloio, rocketreach.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019wkwbhrEoE5KW9A1CKBmcA

* Make funding-watch Pattern B stand on its own

It re-pulled two hardcoded example domains and then diffed them against
/tmp/targets.json, a Pattern A artifact. Run Pattern B alone and the slurp
fails; run both and it compares a fresh pull of one set against stored dates
for a different set, so the "new round" filter cannot fire correctly either way.

Both sides of a diff have to come from the same query. Now they do: one storage
read supplies the domains to pull *and* the stored dates to compare against, so
the sets align by construction and the pattern has no cross-dependency.

Also states what a missing stored date means — it compares against "" and always
passes, which is right on a first run and is exactly why the write-back step is
not optional. Without it every run is a first run and the watch re-flags the
whole segment forever.

Verified against fixtures: an account whose round moved is kept, one whose
stored date already matches is dropped, one with no stored date passes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019wkwbhrEoE5KW9A1CKBmcA

* Route the questions people ask but the map never answered (#124)

Measured instead of guessed. Of the 176 credits-based actions, 148 were
reachable from a routing surface — the stage map, the phase guides,
alternatives.md, a recipe. The other 28 were reachable only from their own
provider playbook, which is findable if you already know which provider to
open. That is the wrong way round.

The worst of it: headcount had no section at all. It is the most-asked company
attribute and the first row of the custom-datapoints feasibility gate, and not
one of the four salesNavigator.find* actions appeared anywhere in the stage map.
New section carries all four, plus the only historical series
(companyEnrich.getWorkforce), plus linkedin.findCustomHeadcount for the roles
the fixed buckets don't have, plus the companyId prerequisite that quietly
turns a 0.25 action into 0.30 on a list that arrived without one.

"Who works at this domain" was not a documented question either. It is not the
same as searching a population by title, and it has two answers at very
different prices. New section, with the trap stated: looping hunter.searchDomain
to build a list is the pitfall its own playbook warns about.

Also adds rocketreach, mixrank and societeInfo to Enrich/Sourcing —
societeInfo reaches French registry data (NAF code, collective agreement,
filed accounts) that nothing else in the catalog does — and gives Hiring intent
a second index at the same price.

154/176 now. The remaining 22 stay unrouted on purpose, and the CHANGELOG says
why for each: the four LinkedIn engagement actions would undercut the
acceptable-use refusal to batch-blast them, three natives belong to other
skills, searchLeadsLegacy costs 300x its replacement, and the rest are finer
grain on an already-routed surface rather than separate questions.

One thing the build caught: adding aiArk.analyzePersonality re-introduced a
term the codex package deliberately strips, since the directory rejected
person-level inference. Kept for the channels that carry it, with matching
PACKAGE_EDITS so the package still removes it. Dropped the forager rung rather
than add machinery for a last-resort action priced 20x above its own chain.
All 67 anchors verified.


Claude-Session: https://claude.ai/code/session_019wkwbhrEoE5KW9A1CKBmcA

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-02 16:40:18 -07:00
Cursor Agent 7a5f8375be Disable Cisco scanner to work around v2.0.14 false positives
cisco-ai-skill-scanner 2.0.14 incorrectly flags standard Unicode
characters (em dashes, arrows) as 'obfuscated prompt-injection'.
Neither baseline files, severity_overrides, nor cisco_policy: permissive
suppress these false positives. Disabling the Cisco scanner until the
upstream fix is released. The base plugin scanner still runs all core
security checks.

Co-authored-by: Auree Aubert <aureeaubert@users.noreply.github.com>
2026-09-02 05:23:48 +00:00
Cursor Agent ea1acfad1a Set cisco_policy to permissive to fix scanner false positives
The cisco-ai-skill-scanner 2.0.14 flags standard Unicode characters
(em dashes, arrows) as 'obfuscated prompt-injection'. The baseline and
severity_overrides config options don't affect the Cisco scanner, so
use cisco_policy: permissive to relax the detection rules.

Co-authored-by: Auree Aubert <aureeaubert@users.noreply.github.com>
2026-09-02 05:20:37 +00:00
Auree Aubert d91ab11e45 Point the CDK skill at cdk add, and stop documenting a template flag (#121)
The cookbook guidance said there was no copy tool and the agent had to place
the code itself. `cdk add cookbook/<slug>` is that tool now, so the skill says
what it does, where it writes, and — the part an agent gets wrong — that the
cookbook's own procedure has to be picked up at its Adapt section, because its
opening steps assume you found the folder on GitHub and still have to place it.

The command reference documented `--template <blank|full>` and
`--list-templates` for `cdk init`. Neither flag exists: the scaffold never
varies and a worked example comes from a cookbook. It also had no row for `add`
or `cookbook` at all, which is the reference an agent reads to decide what to
run. Fixed, along with the two recipes and the example that invoked
`--template full`.

Refreshes the cookbook snapshot, which had gone stale at two cookbooks while
the catalog grew to three — `crm-enrichment` was missing from the menu.

Regenerates llms.txt and the skill's metadata snapshot, both CI-gated.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 22:12:45 -07:00
Auree Aubert be823b3fcb Generate the cost table, and stop omitting the native actions (#111)
* Generate the cost table, and stop omitting the native actions

The credits price list was hand-kept. The first attempt to generate it read
`connection integration list`, which is connector-only — so its own header
claimed "every credits-based action in the cargo catalog" while silently
omitting every billed native action:

    sendEmail    0.1   fixed
    modelAsk     0.5   fixed
    fileSearch   0.02 / 1k tokens

`sendEmail` is the whole outbound send path, priced at 0.1 in the mailbox
skill, and it was absent from the canonical price list.

It is now generated by `cargo-ai orchestration action cost-table --raw`
(getcargohq/cargo#5641), which lives beside `action list` and `action execute`
— the surface that spans connector, native, tool and agent. 197 credits-based
actions of the 534 the catalog exposes, up from the 145 the hand-kept table
claimed and the 194 a connector-only generator found.

What the hand-kept table got wrong, now that a generated one can be diffed
against it: 145 actions where there are 197, four prices quoted from memory,
and cost columns that concatenated every tier into an unreadable comma list —
`openAi.instruct` rendered 28 numbers. Per-config pricing moves to its own
section.

Two providers gain playbooks rather than staying unlisted: brightData
(Instagram/TikTok/Facebook/YouTube by URL, the catalog's only non-LinkedIn,
non-X social coverage) and proxycurl. An undocumented provider still shows up
in the cost table, so the acceptable-use framing is better stated than implied;
brightData.md opens with the consumer-targeting refusal that gates it. Only
openRouter remains without a playbook, and it has no credits-based actions.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TBfa73ishJJRe4pccyhTAa

* Pin the CLI at 1.0.66, and fix five commands that never existed (#117)

* Pin the CLI at 1.0.66, and fix five commands that never existed

The pin had drifted 19 releases behind npm, and the bundle now teaches
`orchestration action list`, which only exists in 1.0.66. The pin is what the
session-start refresh installs, so leaving it meant an agent following these
skills would reach for a command its CLI did not have.

Checked before moving it, not after: the CLI's whole command surface was diffed
across 1.0.47..1.0.66. The only removals are three billing commands no skill
documents; `update-payment-method`, which the skills do use, replaced one of
them and is still there. Everything else in the range is additive.

That verification then turned up five documented commands that do not exist —
and all five were already broken at the old pin, so this is old debt the bump
surfaced rather than caused:

- `orchestration draft-release {get,update,deploy}` (18 sites) is really
  `orchestration release {get-draft,update-draft,deploy-draft}`.
- `ai template get <slug>` (6 sites) does not exist. `ai template list` already
  returns each template in full, so the fix is to filter that response.
- `action execute --record` (5 sites) is `--data`.
- `storage model list --dataset-uuid` (4 sites): the command takes no options
  at all, and every model carries `datasetUuid`, so filter client-side.
- `storage model get-ddl --model-uuid <uuid>` takes the uuid positionally.

Also folds in the skills half of getcargohq/cargo#5740: `get-output-schema`
takes an action plus an optional `--data` rather than demanding a `config`, so
the object `action list` returns now pastes into all four action commands
unchanged. The gotcha row about the 400 becomes a note about `--data`, which is
the part worth knowing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TBfa73ishJJRe4pccyhTAa

* Mark --data on get-output-schema as CLI >= 1.0.67

getcargohq/cargo#5740 ships --data in CLI 1.0.67, one above the pin this PR
sets. The config-less --action works on the pinned 1.0.66 as soon as that
backend deploys; --data needs the next release, so it carries a version marker
like every other post-pin flag in the bundle.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Document the execution charge the pack said did not exist (#118)

Every node execution bills 0.01 credits (1 per 100) — structural natives
and errored executions included. Three places in the pack said otherwise,
and they reinforced each other:

- troubleshooting.md described executions[].creditsUsedCount as "native
  nodes are zero", accurate about the field but read as pricing;
  play-optimize-credits.md restated it and cited it as the authority.
- The generated cost table prices actions, and structural natives are
  excluded from `action list` entirely, so branch/filter/switch/variables
  appear in no price list here — read as free.
- cargo/SKILL.md said "Everything else is free" outright.

Verified live: `billing usage get-metrics --unit orchestration.executions`
returns success/error as execution counts, reconciling row-for-row with
`SELECT execution_status, count() FROM spans`. spans.execution_credits_used_count
reads 0 on natives that billed, so the charge is attributed to no node and
per-node profiling under-counts every graph.

Two adjacent bugs fixed while verifying:

- `--unit credits` was documented and 400s. The flag takes exactly
  billing.credits | orchestration.executions | storage.records, and with
  no --unit all three interleave in one items[] array with different
  meanings for `count`.
- The example slugs `enrichment` / `ai_message` were invented (real:
  integration.<slug>.action.<action>, native.<action>, success/error,
  insert), as was `.totalUsage` — the response has one key, `metrics`.

Estimates now carry two terms: (provider cost × records) + (nodes ×
records / 100), measured on the pilot rather than inferred from the graph.

cargo-billing 1.1.0 -> 2.0.0 (agents relearn --unit and the slug shapes),
cargo-orchestration 1.11.0, cargo-gtm 1.19.0, cargo-diagnostics 1.4.0,
cargo 1.24.0 + the three plugin manifests.

Still upstream: `orchestration action cost-table` generates the header
"The other 337 actions ... cost no credits" — unfixable from this repo.


Claude-Session: https://claude.ai/code/session_01AbUvyTQMDABiexZgQCsGoe

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Source the cost table from action list, not a bespoke generator

`orchestration action cost-table` is being removed from the CLI: it read
`action list` twice and added no data, and the markdown it generated was
its only consumer. `action list` already returns a `credits` array on every
billed action, so the table is regenerated from that directly.

Regeneration is now two calls (`--kind connector`, `--kind native`) plus
the three cost shapes documented in the header, so a reader can render the
table without the generator's price-formatting logic. Notably `fixedCost`
adds to the metered rate rather than replacing it — the trap that made a
0.175 + 0.025/item search read as 0.025.

Two fixes that fall out of owning the header again:

- The opening line claimed the other 337 actions "cost no credits". True
  of provider price, false of anything that runs in a workflow. It was
  flagged as unfixable while the CLI generated it; it now states no
  *provider* price and points at the execution charge.
- `stage-action-map.md` still carried 194/310 from the connector-only
  generation, against 197/337 everywhere else.

Co-Authored-By: Auree Aubert <16732193+aureeaubert@users.noreply.github.com>
Co-Authored-By: replicas-connector[bot] <replicas-connector[bot]@users.noreply.github.com>

Co-authored-by: Auree Aubert <aureeaubert@users.noreply.github.com>

* Fix PACKAGE_EDITS patterns to match regenerated cost table format

Co-authored-by: Auree Aubert <aureeaubert@users.noreply.github.com>

* Add PACKAGE_EDITS rule to remove extractEventAttendees from stage-action-map.md

Co-authored-by: Auree Aubert <aureeaubert@users.noreply.github.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: replicas-connector[bot] <replicas-connector[bot]@users.noreply.github.com>
Co-authored-by: Auree Aubert <aureeaubert@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-09-01 16:28:25 -07:00
Auree Aubert 55d2eaf660 Ship the OpenAI package without the surfaces its review rejected (#120)
* Hold the sending skill out of the OpenAI package

The directory review rejected two skills under "Spam mass abuse".

cargo-mailbox-management is a true positive on category: it provisions
sending mailboxes and runs a 5-to-40/day warm-up ramp, which is the shape
of cold-email infrastructure whatever the gates around it. So the package
now ships without it — EXCLUDED_SKILLS — and says so by shipping eighteen
skills rather than by rewording the nineteenth. The alternative, deleting
the refusal lists and ramp documentation until the keywords stop matching,
would ship a less guarded skill in order to pass a safety review.

cargo-gtm looks like a false positive on negation: its description ended
"bulk unsolicited messaging, purchased or scraped lists, and consumer
targeting are refused", which hands a keyword classifier four spam nouns
in one clause. The packaged description now states the same policy as what
the skill does — documented lawful basis, suppression screening,
per-recipient relevance, sends nothing itself — and keeps every routing
trigger. That did not clear review — gtm was rejected again with the new
card live, so the trigger is the skill body or the capability itself, not
the description. The reframed card is kept because it is the more accurate
of the two, not because it fixed anything.

Excluding a skill is not just skipping a directory. Fifteen of the
remaining skills link to it: a router table row, an ASCII diagram box, a
recap section, the domain list, defineMailbox/defineDomain in cargo-cdk,
a routing row in cargo-mcp, three passages in cargo-gtm's acceptable-use.
PACKAGE_EDITS removes each one in the staged copy, and every find must
match exactly once or the build fails — they are anchored to prose that
will drift, and a silent no-op would ship a dangling link. Skill counts
renumber from the real packaged total, so the router reads "18 skills ...
fifteen capability skills" without anyone maintaining the number.

Backstopping all of that, zipgrep asserts after zipping that no packaged
file names an excluded skill anywhere. That check does not care whether
the edits above were written correctly.

Every edit applies to the staging copy under dist/. The repo files are
read-only inputs, so Claude Code, Cursor, skills.sh and Hermes still
install all nineteen skills with every mailbox reference intact.

Also fixes the packaged manifest description, which claimed 17 skills —
stale since two were added. It derives from the packaged count now.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YL6YdzRFUf27A2WChKxr1C

* Narrow cargo-gtm's person-level surface for the OpenAI package

Second rejection, with the reframed description already live in the
listing — so the card was never the trigger. Reading the skill body as a
policy reviewer would, five capabilities carry most of the risk, and on
those the reviewer is not wrong:

  snitcher              de-anonymising website visitors
  aiArk.analyzePersonality  OCEAN/DISC inference from a profile
  forager               personal email and personal phone from a URL
  linkedin.extractEventAttendees   harvesting a platform's attendee list
  x                     reading a social platform's posts and profiles

"We gate it" is a weak answer to visitor de-anonymisation and personality
inference. So the packaged skill no longer offers them: three playbooks
leave the tree, and the actions are removed from the stack table, the
cost table, the stage map, the alternatives table, the finding guide's
decision tree, two recipes, the aiArk playbook and the router's glossary.
Thirty-four edits, each asserted to match exactly once.

What remains is the same skill minus a person-level edge: company
research, work-email enrichment from licensed providers, verification,
scoring, signal monitoring, CRM sync. That is a real narrowing of what
the package can do rather than a rewording of what it says it does, which
is also what makes the appeal behind it checkable.

REMOVED_TERMS asserts against the built archive that nothing survived,
scoped by path — extractEventAttendees stays in cargo-connection, which
documents the catalog rather than recommending the action, and which the
directory already approved.

Metadata is regenerated with the repo's own skills-metadata.mjs over the
staged tree: three files left and a dozen changed, so every packaged
skill-metadata.json was stale by construction, content hash included.

Repo copies are untouched, as before. Every other channel still ships all
nineteen skills with the full provider stack.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YL6YdzRFUf27A2WChKxr1C

* Give the packaged quickstart a company-level demo

Third rejection, same category: the quickstart's headline pull is 25 named
people with titles and a "recently hired" flag. Sixteen skills that never
touch a person passed on the first try; the three that were rejected are
the three that do.

Rather than drop the onboarding skill, the package now ships a variant
that runs the same two-minute arc against company-level hiring intent —
theirStack.searchCompanies on the persona's role, postings inside 30 days.
This is the skill's own fallback rung 2, which it already describes as
"same wow, different angle". The receipt is unchanged at ~0.5 credits,
because searchCompanies bills per call rather than per row, so `limit` is
free to set. The demo names no individuals.

It ships as a whole file rather than as edits. The spine is rewritten —
action, filter, output fields, headline, fallback ladder, next steps — and
a dozen brittle anchors through a rewritten section would fail on the next
upstream wording change with nothing useful to say about it.

The copy is tied to the repo skill's frontmatter version instead. Bump
cargo-quickstart and this build fails, naming both versions and asking for
the port. That is the maintenance cost of an override, made loud on
purpose.

Step 3 reads the first row's keys and renders from them rather than
hardcoding a shape: the payload of this action is not something I have run,
and a demo that dies on line 3 is worse than one that spends a second
looking. Worth one 0.5-credit run against a live workspace before the
package is resubmitted.

Repo copies untouched, as with the two commits before this. Every other
channel still ships the leads demo.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YL6YdzRFUf27A2WChKxr1C

* Rebuild the quickstart demo on aiArk, against a live run

theirStack was the wrong pick and the reason is not taste: it needs its
own API-key connector, so on the fresh workspace a quickstart exists for
it dead-ends on rung 1. It got chosen because the fallback ladder named
it, not because anything checked it.

aiArk.searchCompanies is better on every axis that matters here. It runs
on cargo's managed connection, so a workspace with nothing wired up can
still complete the demo. At 0.01 per returned record, 25 rows cost 0.25
credits — half what the leads demo cost. And it answers the persona
question with accounts rather than people.

The demo also opens on countCompanies, which is fixed-cost 0. Sizing the
whole addressable market for free and then sampling it for a quarter of a
credit is a better first beat than 25 rows with no denominator, and it
puts the pack's own count-first rule in the first thing a new user sees.

Everything here is verified against a real run rather than a playbook:

  countCompanies      free, returns {"count": N} — 1,904 on the example
  searchCompanies     25 rows for 0.25 credits
  employeeRole        employee_title_or / employee_seniority_or /
                      employee_department_or
  industry            industry_or takes plain lowercase strings
                      ("software development") — no autocomplete needed,
                      and it halved the pool to 840
  row fields          name, industry, employee_count, city, country,
                      domain, linkedin_url, revenue, founded_year,
                      technologies

So step 4 renders named columns now instead of printing the keys and
hoping. theirStack keeps a place as rung 3, where its own-key connector
is a known cost rather than a surprise.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YL6YdzRFUf27A2WChKxr1C

* Remove only the mailbox bullet from the CDK critical rules

The drop_block helper takes the blank-line-delimited block around a
marker, which is right for a standalone diagram and wrong for a markdown
bullet list: consecutive bullets have no blank line between them, so the
whole list is one block. The cargo-cdk edit anchored on the defineMailbox
bullet and took all of "## 6) Critical rules" with it — 71 lines instead
of 12. The packaged CDK skill shipped an empty heading, losing the
state-file, secrets, handle-wiring, --yes, paid-play sample and alert
cost-gate rules.

Caught by Bugbot on #120, not by the build: every assertion here checks
that a find matched exactly once and that removed things left no trace.
Nothing checked that what remained was still there.

A repo-vs-package line-count diff over the whole archive now reconciles:
every SKILL.md is -12 for the dropped metadata block, and each further
delta matches a specific edit. cargo-cdk is the only file that was wrong.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YL6YdzRFUf27A2WChKxr1C

* Document aiArk's three undocumented actions

Bugbot flagged the quickstart override for calling aiArk.countCompanies,
an action absent from the packaged playbook. The action is real — the demo
was verified against a live run — so the gap is in the documentation, and
it is a repo gap rather than a packaging one.

The playbook described six actions and asserted "all six are credits-based".
The integration exposes nine:

  enrichCompany    0.01   the cheapest company enrich in the catalog
  countCompanies   free   {"count": N} for a searchCompanies filter
  countPeople      free   same, for searchPeople

The count pair is the more useful omission. Cost discipline tells an agent
to size a pool before paying per record, and on this provider that check
costs nothing — but only if the agent knows the actions exist. Added
alongside the per-record billing warning, where the question actually comes
up.

Also corrects the override's claim that industry_or takes ordinary
lowercase strings, which contradicted the same playbook two files away.
Both are true and neither said so: the enum members are LinkedIn-style
lowercase names, identical to the strings each row returns in its own
industry field, so a value copied off a result matches while a guess
empties the pool. The override now says that, and points at listIndustries
for anything less obvious.

Repo change, so every channel gets it, not just the OpenAI package.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YL6YdzRFUf27A2WChKxr1C

* Remove the personality pitch, not just its slug

REMOVED_TERMS asserted on "analyzePersonality" and passed, while the
packaged playbook went on selling the capability in prose that named no
action: an intro pitching "a personality-analysis action nothing else in
the catalog has", and a reason-to-reach-for-it clause offering
"personality/selling guidance". A slug-only check waved both through.

The counts were wrong too. The repo playbook says nine actions, seven
credits-based; the package removes one, so it ships eight and six. Now
stated as such, and the packaged action table has exactly eight rows to
match.

The assertion now looks for "personality" itself. It cannot collide with
"personalization", which is a different word, and the sweep it flagged on
the first run is what found the second clause — the fix caught its own
gap before the archive shipped.

Also adds .github/package-overrides/** to the Codex package workflow's
path filter. The package depends on that file now, so a change touching
only the override needs to run the build and the version guard, and did
not.

Both found by Bugbot on #120.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YL6YdzRFUf27A2WChKxr1C

* Fetch the count, drop the attendee pitch, fail a broken sweep

Three from Bugbot on #120, all correct.

The quickstart's headline number was never fetched. Step 1 wrote the
countCompanies run object to a file and step 4 told the agent to lead with
the pool size, but the run object holds no results — the same skill says so
two paragraphs earlier — and nothing ever called download-outputs for that
run. The demo would have opened on an empty variable. Both steps now go
through one fetch_output helper, so the retrieval that was already correct
for the search is correct for the count too, and the headline reads $POOL.

The linkedin playbook still pitched event-attendee harvesting in prose
after the action row was removed: an engagement-sourcing bullet and the
per-item billing note. Same failure as the personality pitch — the slug
left, the capability stayed. The new assertion is scoped to that one file
on purpose: "event attendees" appears four more times in cargo-gtm as a
lawful BASIS for contacting someone, and that must stay exactly where it is.

And the sweeps themselves could not fail. Every throw was read as "nothing
matched", so a missing binary or an unreadable archive reported a clean
package. grep-family exit codes distinguish these: 1 is no match, anything
else is an error. Verified by putting a zipgrep that exits 2 on PATH — the
build now stops with "could not verify ... zipgrep exited 2" where it
previously passed.

That last one is the pattern worth naming: three of the five findings on
this PR were assertions that were true and conclusions that were wrong.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YL6YdzRFUf27A2WChKxr1C

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-01 13:26:47 -07:00
replicas-connector[bot] 5680754126 Add cargo-mcp, and correct the router on the hosted MCP server (#116)
mcp.getcargo.io/mcp is live and serves thirteen platform tools plus
whatever a workspace published with defineMcpServer. Nothing in the
bundle covered it, and cargo/SKILL.md asserted "There is no first-party
'Cargo MCP server'" - true when written, wrong now, and the one claim an
agent would act on.

- cargo-mcp/SKILL.md (1.0.0): connect, the discover to price to execute
  to poll spine, and the routing table for MCP tool vs cargo-ai.
- cargo/SKILL.md (1.22.0): the MCP section becomes a three-way
  disambiguation. Hosted server, workspace server served over stdio by
  cargo-ai mcp, and an MCP client attached to a Cargo agent are three
  things sharing a name and sharing no answers.
- evals/routing.jsonl: "How do I use Cargo from ChatGPT?" now expects
  cargo-mcp; three cases added for the new surface.
- Counts, catalogs, plugin manifests, SKILL_DIRS, llms.txt, metadata.

skills-lint, routing-eval, sync-trigger-slugs and the cargo-gtm script
fixtures all pass.

Co-authored-by: Cargo FSD <fsd@getcargo.io>
Co-authored-by: Auree Aubert <16732193+aureeaubert@users.noreply.github.com>
Co-authored-by: replicas-connector[bot] <replicas-connector[bot]@users.noreply.github.com>
2026-08-27 10:28:58 -07:00
dependabot[bot] da11a0957a CI: bump hashgraph-online/ai-plugin-scanner-action (#114)
Bumps [hashgraph-online/ai-plugin-scanner-action](https://github.com/hashgraph-online/ai-plugin-scanner-action) from 1.2.515 to 1.2.528.
- [Release notes](https://github.com/hashgraph-online/ai-plugin-scanner-action/releases)
- [Commits](https://github.com/hashgraph-online/ai-plugin-scanner-action/compare/55616c962cf86368423f7673b2ecdfdbe613d1af...b402d3b3aaa8f59df8e8aa427dc97694a0af2819)

---
updated-dependencies:
- dependency-name: hashgraph-online/ai-plugin-scanner-action
  dependency-version: 1.2.528
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-23 22:02:29 -07:00
Auree Aubert e61f67f105 New skill: cargo-mailbox-management, and Cargo sends now (#113)
`mailboxManagement` landed in the CLI (cargo#5493, plus warm-up stats in
cargo#5646) and nothing in the bundle covered it. It is the first domain
that makes Cargo own the inbox, so the gap was not one more capability
skill — it was a skill whose absence let an agent send mail with no idea
what it cost or what governed it.

- New `cargo-mailbox-management` (the fifteenth capability skill): six
  command groups, the send that is deliberately not in them, and four
  references — the ramp arithmetic and fleet sizing, the `sendEmail`
  action, response shapes, troubleshooting — plus eight worked recipes.

- The two facts an agent gets wrong without it. A mailbox is a recurring
  monthly credit charge (100-160 per mailbox per month), not a per-record
  one, and `mailbox remove` is the only way to stop it. And volume is a
  ramp, not a setting: 5/day to 40/day over 45 days from `warmupStartedAt`,
  pinned at 5/day forever if warm-up never started, reset to day 0 by
  `stop-warmup`, and `dailySendLimit` can only tighten it.

- `cargo-gtm`'s acceptable use said the pack never sends. That paragraph
  is the substance of the plugin-directory remedy, and mailboxManagement
  made it false. Section 1 now says what is true, section 6 names the ramp
  and calls spreading one campaign across extra mailboxes what it is, and
  section 7 cross-references the new skill.

- `cargo-cdk` gained `defineMailbox` and `defineDomain` in the same release
  and had documented neither. Both are now in the builder table with the
  create-only, monthly-fee and whole-zone rules that bite.

- Known gap, filed rather than papered over: `mailbox create --domain-uuid`
  is required and no command lists sending domains.

Counts move 17 to 18 across the router, README, AGENTS, CONTRIBUTING and
the manifests. Seven new routing cases, two of them hard-tier negatives
pinning the boundary the word "email" blurs. Core tier 93/93; lint,
metadata, llms.txt, trigger slugs, cookbooks and hooks all clean.


Claude-Session: https://claude.ai/code/session_01TF1ZRweJqqnPeGbVmUeGkY

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 21:47:30 -07:00
Auree Aubert fb95217c52 Make the cookbook menu a local file, and route on one-off vs standing (#110)
* Make the cookbook menu a local file, and route on one-off vs standing

cargo-cdk told the agent to "read the cookbook menu (the repo README's table)"
— a network fetch to another GitHub repo, mid-task, which an agent may simply
not make. When it does not, it authors from scratch a GTM outcome that was
already sitting there written. A menu you have to go and get is a menu that
gets skipped.

So the menu becomes a local reference, generated from the cookbook repo:

  .github/data/cookbooks.json      committed snapshot
  .github/scripts/sync-cookbooks.ts  --refresh to re-pull, --check in CI
  cargo-cdk/references/cookbooks.md  generated prose

Same shape as sync-trigger-slugs.ts, deliberately: CI reads the snapshot and
never the network, so a change in the cookbook repo cannot turn this build red
on its own. Staleness is fixed on purpose, with --refresh.

Two things the pointers got wrong, beyond being remote:

Routing. cargo-cdk's description triggers on "as code", "in git", "Terraform
for Cargo". Nobody says that when what they want is a rep cockpit. The real
seam is one-off versus standing: "build our TAM" is cargo-gtm when the user
wants a list today and a cookbook when they want a pipeline that keeps
producing it. The words are identical, so both skills now say so explicitly and
the description carries the outcome vocabulary.

What a cookbook is. Both pointers called them "scaffoldable outcome templates",
which invites copy-and-fill. The code is a worked example: each cookbook
declares what may be reshaped, what must hold, and what must be answered, and
installing one means adapting it until it is this company's code.

Also carries the --force warning into both, because the damage is silent:
`cdk init --force` into a non-empty directory replaces the project's
package.json and reverts adapted cookbook code while cargo.state.json survives,
so the next plan diffs a live workspace against code nobody wrote.

Note: the snapshot includes `variations`, which land in cargo-cookbooks#3.
Re-run --refresh once that merges.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Read the menu from SKILL.md frontmatter; leave "install a cookbook" to deploy-cookbook

cargo-cookbooks folded cookbook.json into SKILL.md (every reader of the
contract is an agent, and agents read markdown), so sync-cookbooks.ts now reads
frontmatter (outcome, state, chain) plus `kind` and `requires` from
cargo.scaffold.json, and the variations table under "## What you can change".
Foundations take their one-liner from the README's first paragraph. No new
dependency: the frontmatter is validated as real YAML in its own repo, so four
scalar fields do not need a parser here.

Two corrections to the previous commit on this branch:

  - cargo-cdk's description carried "install a cookbook" verbatim, which is
    deploy-cookbook's own trigger. With both installed the tie went to
    cargo-cdk, so the skill that merely points at cookbooks beat the one that
    installs them. cargo-cdk now carries discovery vocabulary ("is there a
    cookbook for this", "start from a cookbook") and leaves the install phrase
    to the skill that does the work.

  - `cargo-ai manifest add` is the way into an existing project (copy-in,
    existing files kept, every file hashed in manifest.json). It replaces the
    "scaffold to a temp dir and copy across" advice, which was a workaround
    for a command that already existed. skills-lint learns the `manifest`
    domain, shipped in 1.0.57.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* List every scaffoldable cookbook in the menu, not only the ones with a skill

The menu hid 16 of 20 cookbooks because they had no SKILL.md yet. The old
pointer sent the agent to a README that listed all 20, so this was a
regression: a user asking for contact sourcing was told nothing existed while
the code sat there and cdk init --from scaffolded it fine. Every outcome is
listed now; the Skill column says whether the adaptation contract exists or
the README and PLACEHOLDER comments are the interview.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cargo-cdk: no session reload needed to reach a cookbook skill mid-task

A cargo-skills user who asks for a cookbook outcome is one hop from the skill
that installs it. Say exactly what to do in that hop: skills add, then read
the two SKILL.md files directly; or `npx skills use` to read one without
installing. And name the --dir default, which lands a cookbook in infra/
where a plain CDK project imports nothing from.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* menu: manifest add, not scaffold-to-temp, into an existing project

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* regenerate cargo-cdk metadata

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* menu: read state from the cookbook manifest, not from customer-facing frontmatter

cargo-cookbooks moved state, approval and chain out of SKILL.md frontmatter
into cargo.scaffold.json, because SKILL.md is what a customer installs and
Cargo's bookkeeping is not their concern. The menu now takes everything from
the manifest and each README's first paragraph; SKILL.md contributes only the
variations table. One code path for foundations, unconverted and converted
outcomes alike.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* regenerate metadata

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Point at gtm-skills' catalog.json: the CDK examples are skills there now

cargo-cookbooks merged into gtm-skills as flat, self-contained skills, and
that repo publishes one validated catalog.json. This script fetches it and
parses no markdown; the menu lists the skills that carry a CDK example and
the folders whose skill is not written yet. cargo-cdk and the router say
what changed in the model: the agent copies the folder in and reconciles it,
there is no scaffolder, and the shell comes from cdk init --template blank.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* menu: gtm-skills keeps only skills at the root, so no 'no skill yet' section

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Address review: GTM_SKILLS_ROOT accepts a dir or the catalog file; routing cases for cargo-cdk's new vocabulary

Bugbot's third finding (foundation variations dropped from the menu) is moot:
gtm-skills dissolved base-gtm and crm-sync into the skills that used them, so
there are no foundations and nothing to render.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Name things what they are: CDK examples, not cookbooks

The script, snapshot, reference file and type were named after the repo the
examples came from before the merge. That repo is being archived and the
examples are skills in gtm-skills now, so the names follow: sync-cdk-examples,
.github/data/cdk-examples.json, references/cdk-examples.md, CdkExample. The
llms.txt link to cargo-cookbooks goes; the linter's note that the CLI's
manifest domain includes 'manifest add' goes too, ahead of its removal.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cookbook is the name of the kind: rename the menu, snapshot and sync back to it

gtm-skills#12 fixes metadata.source as one-off | cookbook. So the menu of
gtm-skills that carry a worked CDK example is the cookbook menu, and the file,
snapshot, script and type are named for the kind, not for the repo they once
came from.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 17:57:26 -07:00
replicas-connector[bot] 010ae38779 Playbooks for parallel and exa, and a 20x price error in the stage map (#107)
* Playbooks for parallel and exa, and a 20x price error in the stage map

Section 11 claims every credits-based provider in the catalog has a playbook.
Nine do not: brightData, builtwith, datachimp, exa, openRouter, parallel,
proxycurl, sillage and x. This adds the two that matter most for research and
leaves the claim to be squared with the other seven separately.

Both are worth having because both beat what the recipes currently reach for.
parallel.extract reads a known URL for 0.025, half of firecrawl.scrape.
parallel.createTask is the only action in the catalog that fills a
caller-supplied output schema, and at processor lite it is 0.125 against
linkup.instruct at 1. exa.search is the only rung with a document-type category
filter and publication-date bounds, which is what makes it worth 0.175 fixed
plus 0.025 an item over a 0.05 flat search.

Every action, input and price here was read from the live integration catalog
rather than from documentation, per the lesson this pack keeps relearning: a
capability claim needs the implementation, not the docs index.

That is also how the error surfaced. references/stage-action-map.md priced
serper.search at 1. It is 0.05, and provider-playbooks/serper.md had it right
throughout, so the map was steering agents away from the cheapest search rung by
a factor of twenty. alternatives.md carried the same wrong number for
serper.searchPlaces. Both corrected, and the correction is stated in the table
rather than made silently.

The Web research table is rebuilt around the actual decision: known URL means
parallel.extract, plain keyword means serper, document-type or date filter means
exa, structured output means parallel.createTask at lite.

The createTask ladder gets its own table and a warning. processor is required
with no default, and the top rung is 60 credits per record, which is more than a
full contact waterfall.

Co-Authored-By: Auree Aubert <16732193+aureeaubert@users.noreply.github.com>
Co-Authored-By: replicas-connector[bot] <replicas-connector[bot]@users.noreply.github.com>

* Ban datachimp in code, and close three of the playbook gaps

Two things, both about the same claim: section 11 said every credits-based
provider has a playbook, and nine did not.

Datachimp is removed everywhere and cannot come back. Aurelien's instruction,
2026-08-15. It appeared in the generated catalog and in two lines of
cargo-storage prose. Deleting those would have lasted until the next --refresh,
so the removal is enforced in code instead: a DENIED_INTEGRATIONS set filters it
out of the catalog on both write and read, and skills-lint fails on the string
anywhere in the repo, which is what catches the hand-written half no generator
touches. It was also an integration with zero callable actions, so nothing was
lost.

Three playbooks added, each earning its place on price rather than on coverage.
builtwith's getDomainSummary is FREE and answers most stack questions, so the
playbook's whole argument is that it runs in front of enrichDomain (1); the
current recipes reach straight for a paid rung. sillage's searchLeads is also
free and is the only free signal rung in the catalog, which makes it first on
any signal question by definition. x is fourteen actions at 0.02, the cheapest
signal surface there is, and the playbook spends most of its length on why that
is dangerous rather than on how to use it.

Three are deliberately not written and the claim now names them instead of
overstating. openRouter exposes a model lister and no credits-based actions, so
there is nothing to document. proxycurl is excluded on instruction. brightData
is excluded because its entire action set is consumer social-platform scraping
(Instagram, TikTok, Facebook), which acceptable-use already refuses for person
targeting: documenting it as a GTM provider would contradict the gate two files
away.

Every action, input and price read from the live integration catalog.

Co-Authored-By: Auree Aubert <16732193+aureeaubert@users.noreply.github.com>
Co-Authored-By: replicas-connector[bot] <replicas-connector[bot]@users.noreply.github.com>

* x: a cost table a validator can read, not a grouping a human can

The action list was grouped by input shape, which reads well and parses to
nothing. Every other playbook here carries `| action | cost | inputs | use for |`
and the downstream validator in getcargohq/gtm-skills asserts a skill's quoted
price against that column, so a skill calling any x action would have failed
with "not in that provider's cost table" and sent someone hunting for a missing
price rather than a missing table shape.

The four engagement-list actions keep their warning in the Use for column
instead of only in the anti-patterns, since that column is what a reader scans.

Co-Authored-By: Auree Aubert <16732193+aureeaubert@users.noreply.github.com>
Co-Authored-By: replicas-connector[bot] <replicas-connector[bot]@users.noreply.github.com>

* Install the whole bundle by default, and stop hand-counting installs

skills.sh counts per skill, and one `skills add` sends a single event carrying
every skill it installed. So the command in the README decides how many counters
a real install moves. `--all` is now the documented form: it is shorthand for
`--skill '*' --agent '*' -y` and behaves the same in a terminal, in CI, and
inside an agent, where a bare add would drop into an interactive picker.

Two stale hand-maintained facts removed rather than corrected, which is the same
call this repo made about "sixteen skills" in the CLI help.

The install total read "installed 54,885 times". The live figure is 58,245
across the seventeen skills. A number in prose that only moves when somebody
remembers to move it will be wrong again next week, and this one is a public
claim about traction, which is the worst kind to be casually wrong about.

The gtm-skills section listed twelve skills by name. That repo has grown past
twelve, so the list now points at its README instead: a hand-maintained copy of
someone else's list is a copy that goes stale.

Co-Authored-By: Auree Aubert <16732193+aureeaubert@users.noreply.github.com>
Co-Authored-By: replicas-connector[bot] <replicas-connector[bot]@users.noreply.github.com>

---------

Co-authored-by: replicas-connector[bot] <replicas-connector[bot]@users.noreply.github.com>
Co-authored-by: Auree Aubert <16732193+aureeaubert@users.noreply.github.com>
2026-08-14 23:58:36 -07:00
dependabot[bot] cda2ee39cb CI: bump actions/checkout from 4.4.0 to 7.0.1 (#103)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.4.0 to 7.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/11d5960a326750d5838078e36cf38b85af677262...3d3c42e5aac5ba805825da76410c181273ba90b1)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-14 23:53:47 -07:00
dependabot[bot] 842e9940ba CI: bump actions/setup-node from 4.4.0 to 7.0.0 (#106)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4.4.0 to 7.0.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/49933ea5288caeca8642d1e84afbd3f7d6820020...820762786026740c76f36085b0efc47a31fe5020)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-14 23:53:39 -07:00
dependabot[bot] 144be3ea00 CI: bump actions/download-artifact from 4.3.0 to 8.0.1 (#105)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.3.0 to 8.0.1.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/d3f86a106a0bac45b974a628896c90dbdf5c8093...3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-14 23:53:31 -07:00
dependabot[bot] 08ec7127de CI: bump actions/upload-artifact from 4.6.2 to 7.0.1 (#104)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.2 to 7.0.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/ea165f8d65b6e75b540449e92b4886f43607fa02...043fb46d1a93c77aae656e7c1c64a875d1fc6a0a)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-14 23:53:22 -07:00
Auree Aubert 6683645b00 CI: run the HOL AI plugin scanner (#102)
* CI: run the HOL AI plugin scanner

hashgraph-online/awesome-ai-plugins requires every listed plugin's source
repo to invoke `ai-plugin-scanner-action` on push/pull_request before the
listing PR can merge (getcargohq/cargo-skills#83 → their PR #72).

Pinned to a full commit SHA instead of the floating `v1` tag, with a
read-only token and no secrets in scope, so a third-party action in our
workflow surface can't reach anything it shouldn't.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* CI: publish the scanner report when the scan fails

The action's built-in summary step is `if: success()`, so a failing scan
prints counts and no findings. Render markdown to a file and cat it into
the step summary unconditionally.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* CI: tee the scanner report to the job log as well

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* CI: clear the plugin scanner's 80-point / no-high gate

The scanner job this PR added failed on its first run: 71/100 against a
`min_score` of 80, one critical finding and one high. The awesome-ai-plugins
contribution gate re-scans this repo with the same two thresholds, so the
findings had to be fixed rather than configured around. Now 92/100 (A), zero
critical, zero high.

- Pin every `uses:` in .github/workflows/ to a full commit SHA, and add
  .github/dependabot.yml so the pins move weekly instead of never.
- Add SECURITY.md: private reporting via the Security tab, and an explicit
  boundary between this bundle and the cargo-ai CLI / Cargo platform.
- Stop inlining `curl … install.sh` in cargo/SKILL.md. The command now lives
  only in README.md, where a human runs it; the router keeps the guidance
  (never run it on the user's behalf) and points there.
- Use execFileSync, not execSync, for `npm root -g` in the QA script library —
  no shell to interpret a command string. Windows gets the npm.cmd shim.
- Fill in repository/license/keywords in .codex-plugin/plugin.json, a category
  on the .agents marketplace entry, and add .codexignore.
- Set write_step_summary: false on the scanner action and publish the report
  ourselves, so it lands once whether the gate passes or fails.

Two medium findings are left standing and documented in CHANGELOG.md: the
`anthropic` provider slug in cargo-gtm's description (correct, and CI-synced
with the CLI) and `fetch(` in the run-output downloader (the point of the
function). Neither is a gate failure.

Co-Authored-By: Auree Aubert <16732193+aureeaubert@users.noreply.github.com>
Co-Authored-By: replicas-connector[bot] <replicas-connector[bot]@users.noreply.github.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: replicas-connector[bot] <replicas-connector[bot]@users.noreply.github.com>
Co-authored-by: Auree Aubert <16732193+aureeaubert@users.noreply.github.com>
2026-08-14 19:00:18 -07:00
Auree Aubert 07e792124c Add a reproducible build for the OpenAI directory package (#90)
* Add a reproducible build for the OpenAI directory package

The OpenAI Plugins Directory is the only channel that does not track this
repo. Its docs are explicit: "published plugins do not update those
skills live." It takes a submission-time snapshot, and every change needs
a new version, a fresh review, and a manual publish -- where skills.sh,
ClawHub, the Gemini gallery and the Claude community catalog all follow
main on their own.

So the archive cannot be a hand-assembled zip. This builds it from the
repo, takes the version from .claude-plugin/plugin.json so the upload can
never claim a version the repo does not have, and discovers skills with
the same rule skills-lint uses so the three cannot disagree.

Two deliberate differences from the repo layout, both documented in the
script: skills go under skills/ (OpenAI's convention, not our root
layout), and the Gemini symlinks are dereferenced because symlinks do not
survive a zip reliably. Skills-only, since codex-hooks.json invokes
${CLAUDE_PLUGIN_ROOT} -- a Claude Code variable -- and shipping an
unverified path into review is not worth it.

Verifies the archive rather than the staging dir: manifest at root, one
SKILL.md per repo skill, no symlinks.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Normalise the package for OpenAI's validator

First upload surfaced three rules no other channel enforces:

  - interface.shortDescription is required, 240 chars max.
  - Skill descriptions cap at 1024. cargo-gtm (1393) and cargo-connection
    (1208) exceed it, both because they enumerate every provider and
    integration -- which is exactly what makes them route well elsewhere.
  - metadata in SKILL.md is rejected outright. Ours carries OpenClaw
    install directives, meaningless to OpenAI.

All three are fixed in the package, not the repo, because the repo copies
serve channels that want the fuller form. The two long descriptions are
rewritten by hand rather than truncated -- every trigger phrase kept, the
rosters cut to a sample plus a count -- so no list ends mid-name.

A description that grows past the limit without a rewrite now fails the
build with the reason, instead of shipping into a rejected review. The
archive is re-read after zipping and checked against the validator's own
rules, since that is what actually gets uploaded.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Add the required plugin icon and verify it is square

OpenAI requires interface.composerIcon and interface.logo, both square.

assets/icon.png is the Cargo product mark at 512x512, lifted from the
browser extension where it already ships -- the real brand asset rather
than a new one. The repo's existing assets/logo.svg would have been the
obvious source, but rendering it here only produced a padded, off-centre
bitmap, and a logo that sits wrong in the UI is worse than none.

The build now resolves both asset paths inside the archive and checks the
image is square, because a dangling path or a 1200x630 crop is invisible
from the manifest and costs a review cycle to discover. Verified against
a deliberately non-square image: it fails with the dimensions.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Automate everything up to the upload, and encode the full ruleset

There is no submission API. The portal is the only path and every version
is human-reviewed, so the upload itself cannot be automated. Everything
before it can:

  - On a release, CI builds the archive and attaches it, so publishing is
    "download the asset, drop it in the portal" rather than "find whoever
    built the zip last time".
  - On a PR touching skills, assets or the builder, the same build runs,
    so a change that would fail OpenAI's validator fails in CI instead of
    months later in a review cycle.

Also encodes the published error catalogue. Two of our values would have
failed the final stage after passing the uploader, because the two tiers
disagree: shortDescription is 240 chars at upload but 30 in the directory
(ours was 201), and displayName drops from 80 to 30. LIMITS targets the
stricter tier throughout, plus name/version/URL shape, skill identity
length, archive entry count and path rules, and icon bounds.

The runner shims sips - scriptable image processing system.
This tool is used to query or modify raster image files and ColorSync ICC profiles.
Its functionality can also be used through the "Image Events" AppleScript suite.

  Usages:
    sips [image-functions] imagefile ...
    sips [profile-functions] profile ...

  Profile query functions:
    -g, --getProperty key
    -X, --extractTag tag tagFile
        --verify
    -1, --oneLine

  Image query functions:
    -g, --getProperty key
    -x, --extractProfile profile
    -1, --oneLine

  Profile modification functions:
    -s, --setProperty key value
    -d, --deleteProperty key
        --deleteTag tag
        --copyTag srcTag dstTag
        --loadTag tag tagFile
        --repair
    -o, --out file-or-directory

  Image modification functions:
    -s, --setProperty key value
    -d, --deleteProperty key
    -e, --embedProfile profile
    -E, --embedProfileIfNone profile
    -m, --matchTo profile
    -M, --matchToWithIntent profile intent
        --deleteColorManagementProperties
    -r, --rotate degreesCW
    -f, --flip horizontal|vertical
    -c, --cropToHeightWidth pixelsH pixelsW
        --cropOffset offsetY offsetH
    -p, --padToHeightWidth pixelsH pixelsW
        --padColor hexcolor
    -z, --resampleHeightWidth pixelsH pixelsW
        --resampleWidth pixelsW
        --resampleHeight pixelsH
    -Z, --resampleHeightWidthMax pixelsWH
    -i, --addIcon
        --optimizeColorForSharing
    -o, --out file-or-directory
    -j, --js file

  Other functions:
        --debug           Enable debugging output
    -h, --help            Show help
    -H, --helpProperties  Show help for properties
        --man             Generate man pages
    -v, --version         Show the version
        --formats         Show the read/write formats with ImageMagick -- the icon check is the only
macOS-specific part, and that beats paying for a macOS runner to measure
two PNGs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Detect packaged symlinks from zipinfo modes, not a listing that never shows them

The post-zip guard tested `unzip -l` output for ` -> `, but that listing
prints only length, date, and name. No zipinfo format prints ` -> target`
either, so the check could never fire and a packaged symlink would have
shipped despite being treated as a hard upload invariant.

Read zipinfo's Unix mode column instead, where a symlink reads
`lrwxrwxrwx`, and name the offending entries in the error. Require a mode
for every entry so an archive whose types cannot be read fails loudly
rather than passing by default.

Co-authored-by: Auree Aubert <aureeaubert@users.noreply.github.com>

* Answer the spam rejection with real gates, not a reworded description (#92)

OpenAI rejected cargo-gtm under "Spam mass abuse". The description was the
whole case against it: "find emails, phones and LinkedIn URLs", "write cold
emails", "build me a list of" — contact harvesting plus bulk cold mail, with
nothing in 8,800 lines about consent, suppression, or volume. Opening the
archive confirmed it; the outreach guide and prompt library are cold-email
prompts end to end.

Rewording alone would be dressing it up, so this does both halves.

references/acceptable-use.md is the substantive half — a peer of
cost-discipline.md at the same mandatory tier. Hard refusals (undifferentiated
fan-out, consumer targeting, lists with no stated origin, contacting a
suppressed record, filter and identity evasion, auto-dialing, batch-blasting
LinkedIn engagement actions), three free blocking checks before any outreach
step (basis, suppression, relevance), what drafted copy must carry, and the
data-hygiene obligations that follow a person out of the workspace.

It is wired into the path an agent actually walks rather than filed next to
it: a mandatory section above Bootstrap, the outreach row of the routing
table, a gate at the top of the outreach guide, and a "before you start" block
in outreach-activation that subtracts suppression before enrichment — which
is also cheaper. The opener prompt now returns NULL when no signal justifies
writing to that person.

The description half stays honest. It leads with B2B, licensed providers, and
the gates, and says the pack sends nothing itself. Every routing-eval trigger
survives except two rewordings ("write cold emails", "find emails for these"),
so evals/routing.jsonl line 14 is worth re-running before the next upload.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Auree Aubert <aureeaubert@users.noreply.github.com>
2026-08-12 18:28:39 -07:00
Auree Aubert 97680e41fe Point the pack at the standalone single-job skills (#82)
getcargohq/gtm-skills packages twelve of these outcomes as skills named after
the job — find-work-email, find-stakeholders, track-job-changes — for people
who want one thing rather than the whole workstation. Nothing here pointed at
them, which wasted the best backlink available: this repo is public, indexed,
and already crawled, and that one is brand new.

Adds the pointer in two places that matter — the README install section, where
someone is choosing what to install, and llms.txt, which is what LLM-facing
crawlers read. Both state the exclusivity rule, since installing both sides
would put two skills in front of the same request.

The llms.txt section is generated, not hand-written, so it cannot drift from
the pack it advertises.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 15:13:36 -07:00
Auree Aubert 99137c2dd0 Publish every skill to ClawHub, not the fifteen someone remembered (#80)
The publish loop hand-listed its skill directories, and the list had fallen
two behind the tree: cargo-segmentation and cargo-observability have never
been published to the registry. Discover the set from */SKILL.md instead, so
adding a skill publishes it.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 15:10:51 -07:00
Auree Aubert 2c072d267d Let the routing evals grade any skill set, not just this repo (#81)
The standalone skills in getcargohq/gtm-skills compete for prompts using the
same four-part descriptions, and twelve of them are deliberately adjacent —
find-work-email against enrich-linkedin-profile against find-linkedin-url.
That is exactly the set most likely to drift into each other, and it had no
regression test because the ranker was hardwired to this repo's layout.

`--skills-root` points it at any directory of `<name>/SKILL.md`; cases default
to `<root>/evals/routing.jsonl` and `--cases` overrides. Default behaviour is
unchanged: 17 skills, 81/81 core.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 14:44:56 -07:00
Auree Aubert 57254032cf Record which skills a session actually loaded (#78)
* Record which skills a session actually loaded

Routing is the thing this bundle turns on, and it has been argued rather
than measured. evals/routing.jsonl now scores 100% on the real-model
tier — a ceiling effect, not a victory: every prompt in it was written by
someone looking at the descriptions they were grading, and several were
added to pin behavior that had just been implemented. A suite that always
passes has stopped discovering anything. Prompts nobody wrote to pass
have to come from real sessions.

- hooks/skill-loads.sh reads a Claude Code transcript and emits a marker
  naming the skills invoked and the recipes/playbooks/guides opened:
  `[cargo-skills: cargo-gtm | docs: build-tam,waterfall]`. The session
  hooks append it to the row's summary, so it is queryable today over
  workspace_management.sessions with no schema change.
- Wired into both session-checkpoint.sh and session-end.sh. Recomputed
  from the whole transcript each time rather than accumulated, so a
  session that dies abruptly still carries it. Emits nothing at all for
  sessions that never touched Cargo.
- evals/README.md documents the three questions the data answers (which
  skills never load, which sessions loaded two before settling, which
  load with no doc read after) and how each turns into an eval case.
- Self-test wired into skills-lint, because a regression here corrupts
  telemetry silently instead of failing loudly.

Two bugs the fixtures passed and real transcripts caught:

- **Prose mentions counted as reads.** The doc regex matched a bare path
  anywhere in the transcript, and a skill's own catalog table names every
  recipe and playbook — so one cargo-gtm load reported all 43 playbooks
  as opened. Now anchored to a `"file_path":` tool input. Fixture 7 is
  that exact case.
- **Dangling prefix** when docs were read without a Skill call, giving
  `[cargo-skills: | docs: …]`. Both halves are now independently optional.

Also: the doc list caps at 12, and says `+N more` rather than looking
complete.

PRIVACY: skill and document names only, all of them already public in
this repository. Never a prompt, file contents, an argument, a record, or
anything a user typed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Fix Bugbot issues: preserve marker in sync finalize, retain skill load order

1. End hook drops skill marker (high severity): The sync finalize now
   includes the skill marker in the placeholder summary, so it persists
   even when refine() fails, times out, or is skipped. The marker is
   fast (no LLM call, just grep/sed).

2. Skill order lost to sorting (medium severity): Replaced 'sort -u'
   with 'awk !seen[$0]++' to preserve load order. The first skill in
   a multi-skill session is the misroute candidate, so order matters
   for harvest question 2.

Added test case 10 to verify load order preservation.

Co-authored-by: Auree Aubert <aureeaubert@users.noreply.github.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Auree Aubert <aureeaubert@users.noreply.github.com>
2026-08-12 14:33:36 -07:00
Auree Aubert 3708f8c955 Agent discoverability: trigger-shaped descriptions, routing evals, standalone bootstrap (#77)
* Agent discoverability: trigger-shaped descriptions, routing evals, standalone bootstrap

The `description` field is the only text an agent weighs before deciding
whether to load a skill. Everything else in the bundle is invisible until
that decision is already made — and twelve of the seventeen descriptions
read as "Manage <CLI nouns> using the Cargo CLI", which matches a user who
is already thinking in Cargo's object model rather than one stating a job.

This rebuilds that layer and, for the first time, tests it.

Routing
- Every description rewritten to a four-part template: job in the user's
  words -> literal quoted trigger phrases -> proper nouns -> an explicit
  `Skip when:` pointing at the sibling skill that owns the adjacent case.
- Integration and provider names are generated, not hand-maintained.
  sync-trigger-slugs.ts fills cargo-gtm's `Providers:` list from the
  playbook tree and cargo-connection's `Integrations:` list from a
  committed catalog snapshot (138 integrations, 50 credits-based).
  `--refresh` re-pulls from a logged-in CLI; `--check` gates CI.
- evals/routing.jsonl (92 prompts) + routing-eval.ts, wired into CI.
  Structural tier asserts the template and that each skill keeps >=5 terms
  unique to it; lexical tier requires the expected skill to rank first;
  an opt-in --llm tier asks a real model to route from descriptions alone.
  Deep paraphrases are tagged "hard" and reported rather than gated — a
  lexical proxy cannot judge them fairly.

Standalone installs
- `skills add --skill <one>` is a supported path and the registry lists
  each skill separately, but thirteen skills' only install instructions
  were a relative link to ../cargo/references/prerequisites.md, which does
  not exist in a single-skill install. Every SKILL.md now has a
  self-contained Bootstrap section, enforced by the linter.

Coverage
- New capability skill cargo-segmentation — the segmentation CLI domain,
  previously uncovered while segments were load-bearing in most recipes.
  Verified against the live CLI, including the flag traps.
- Three cargo-gtm recipes: source-planning (probe and cost candidate
  sources per *hit* before any fan-out), ads-audience-activation (Google
  Customer Match / LinkedIn Matched Audiences), review-and-iterate (human
  review of judgment output, kept as an eval set).
- Router gains a "these skills vs a workspace MCP server" section: Cargo
  has no first-party MCP server — a workspace builds one and serves it
  over `cargo-ai mcp` — so the routing rule is scale and reproducibility.

Index and hygiene
- llms.txt now lists every recipe and provider playbook with a generated
  summary: 17 entries -> ~80 job-named addressable URLs.
- Router trimmed ~80 lines of per-skill summaries that restated each
  skill's own description; critical rules kept in full.
- Linter: bootstrap check, skill-count claims validated against the tree,
  `doctor` and `mcp` added to the known CLI domains.
- CONTRIBUTING.md, keyword-dense README opening, updated repo metadata.

Also carries the aiArk/apolloio priority-stack promotion authored in a
parallel session on this branch (cargo-gtm 1.12.0) — the two touch the
same SKILL.md files and could not be split cleanly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Surface the 100-credit free tier where an agent meets it

There is no purchase gate between installing Cargo and producing a real
deliverable — a new account starts with 100 free credits and no card — and
nothing in the bundle said so. An agent that doesn't know the budget can't
tell a first-time user whether the demo is a look around or a commitment,
and defaults to hedging.

Now stated at every point an agent encounters the question:

- README opening and the generated llms.txt install block: an agent can
  install, sign the user up, and hand back a list in one turn.
- Router install section and prerequisites.md, with anchors for what 100
  credits buys (~5,000 sourced leads, ~1,000 verified-email enrichments,
  ~50 fully enriched contacts).
- cargo-quickstart: the demo spends ~0.5 of the 100, and the skill now
  says so before the first paid call — that reframes the moment from a
  purchase decision into a look around, which is the job of a quickstart.
- cargo-billing: a "what 100 credits buys" table, plus two new trigger
  phrases so free-tier questions route here at all.
- cost-discipline.md: on a new account, receipts and next-step proposals
  must be framed against the free tier. "87.6 of your 100 free credits
  left" is a number the user can act on; "87.6 remaining" is not. Also
  warns that phone lookups (6-7/call) are the fastest way to burn a tier
  a first session should end with something left to try.

Two routing eval cases added for free-tier questions (79/79 core).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Run the routing evals against a real model in CI

The lexical tier passes 79/79, but it is a deterministic proxy written
alongside the descriptions it grades — it cannot fail in a way that
surprises us, which is what makes it weak evidence. The only honest
scoreboard for the description rewrite is whether a real model, shown
nothing but the 17 descriptions, routes the eval prompts correctly.

That tier existed but had never run. Now it does, in its own workflow.

- New .github/workflows/routing-evals-llm.yml, using the repo's
  ANTHROPIC_API_KEY. Deliberately not part of skills-lint: it costs money
  and is non-deterministic, so it must never stand between a typo fix and
  a merge. Triggers on PRs and pushes that touch a SKILL.md, the eval
  cases, or the runner; weekly on a schedule so model drift surfaces even
  when nobody edits a description; and on demand with a model override.
- runLlm reworked for CI: 6-way concurrency (92 sequential calls is a slow
  job), retry with backoff on 429/5xx, tolerant answer parsing, and a
  core/hard/overall breakdown instead of one number.
- Results are written to GITHUB_STEP_SUMMARY as a table, including every
  misroute with what the model picked instead — so a regression is
  readable on the run page without opening logs.
- Optional --llm-min=<percent> floor, wired to the exit code. Left unset
  until the first runs establish a baseline; a floor guessed before the
  data would either never fire or block on noise.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Act on the first real-model routing run: 92/94, two fixes

Baseline from the model tier (claude-haiku-4-5, judging from the 17
descriptions alone): 92/94 overall — core 79/79, hard 13/15. The lexical
proxy's 3/15 on the hard tier was noise about the proxy, not the
descriptions, which is what that tier existed to establish.

Both misroutes were worth having:

- "Our outbound is going to the wrong people — help me figure out who
  actually buys from us" routed to cargo-context instead of cargo-gtm.
  A real collision: cargo-context's triggers include "who do we sell to",
  which reads as ICP ownership. It owns *writing the conclusion down*;
  deriving it from won/lost data is cargo-gtm. Added that boundary to
  cargo-context's Skip when, and the two phrasings to cargo-gtm.

- "Give the assistant access to our sales collateral so it stops making
  things up" routed to cargo-content instead of cargo-ai — and the model
  was right. As written the first step is getting the collateral into the
  workspace. Corrected the expectation and added the other side of the
  boundary as its own case ("attach the library we already uploaded to
  the agent"), which the lexical tier then failed, correctly: cargo-ai
  never said "library" or "release resources". Added both, so the
  content/ai split is now legible to a ranker and a model.

Set --llm-min=93 now that a baseline exists. Deliberately below the
observed 98%, not at it: a model tier that fails on one non-deterministic
flip trains people to ignore it.

Lexical 80/80 core.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Document cargo-ai mcp — the bridge that was written down nowhere

Cargo reaches coding agents through two doors. Skills reach agents that
implement skills.sh; a workspace MCP server reaches everything else —
Claude Desktop, ChatGPT, and whatever ships next. The second door was
fully built and documented in exactly one place: `cargo-ai mcp --help`.

Worse, cargo-ai/SKILL.md taught `ai mcp-server create` (building a server)
without ever mentioning the command that serves it, so an agent could
construct one and have no idea how to connect it — and the section
conflated publishing a server with consuming someone else's, which are
unrelated surfaces.

- MCP section rewritten around the two directions, with a table: publish
  (`ai mcp-server`, called by any MCP client, wired via `cargo-ai mcp`)
  vs consume (`ai mcp-client`, called by your agents, wired via
  `release update-draft --mcp-clients`). States plainly that there is no
  first-party Cargo MCP server — a workspace builds its own.
- Documents `cargo-ai mcp` with the registration one-liner, the
  CARGO_MCP_SERVER_UUID fallback, and the stdout-is-protocol constraint.
- Details verified against the live API rather than --help: actions take
  kind "tool" *or* "agent" (an agent is exposable as a callable MCP
  tool), resources take model or file, and `update` replaces the arrays
  wholesale instead of merging — a real footgun.
- Routing rule for which door to use, pointing at the router section.
- Two trigger phrases ("expose our tools as an MCP server", "use Cargo
  from Claude Desktop or ChatGPT") and two eval cases, so the publish
  direction is reachable from a description at all. It previously wasn't.

Lexical 81/81 core.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 10:18:32 -07:00
Auree Aubert f93cac3f05 Improve agent distribution: paste-prompt install, llms.txt, provider routing, cookbook wiring (#66)
- README now leads with the one-line agent-paste install (agent-install.txt)
  and documents Claude Cowork setup (network egress, no-TTY token sign-in,
  folder-persisted auth)
- Add CI-generated llms.txt (.github/scripts/generate-llms-txt.ts, TS via
  native type-stripping) with a --check step in skills-lint so the index can
  never drift from the shipped skill tree
- cargo-gtm frontmatter description now lists every provider slug so naming a
  provider ("enrich with FullEnrich") triggers routing into the skill
- Route cargo-cdk (and the router recap) to the cargo-cookbooks menu before
  hand-authoring common GTM outcomes, with the deploy-unverified caveat
- Version bumps: cargo 1.16.0, cargo-gtm 1.10.0, cargo-cdk 1.1.0; plugin
  manifests mirrored; skill-metadata regenerated

Co-authored-by: Auree Aubert <aureeaubert@users.noreply.github.com>
2026-08-12 00:58:31 -07:00
Auree Aubert f6d752d869 Add cargo-observability skill — scheduled threshold alerts (#72)
* Add cargo-observability skill for the alerts domain

Introduces a new capability skill documenting the observability CLI
domain (cargo-ai observability alert/event) shipped in the backend/api.

Alerts are scheduled threshold checks: measure a scope (spans/runs/
records/orchestrationQuery/storageQuery/model), compare to a threshold
(metric + gte/lte + value), and fire actions as runs on breach.

New skill: cargo-observability/
  - SKILL.md — commands, the preview-before-create discipline, the
    scope/threshold/action model, permissions, and cost discipline
  - references/scopes-and-thresholds.md — the scope↔threshold matrix,
    metric meanings/units, and the empty-window-vs-real-zero rule
  - references/alert-lifecycle.md — cron windows, at-most-once firing,
    dead-man's switches, and the {{alert.*}}/{{event.*}} templating
  - references/examples/recipes.md — seven copy-paste alert recipes

Pack integration:
  - Router cargo/SKILL.md → 1.17.0: table row, recap, dependency rule,
    diagram box, defineAlert added to the CDK builder list, counts
    (15→16 skills; twelve→thirteen capability skills)
  - README.md, AGENTS.md: counts + Observability capability row + a
    "get alerted when something breaks" use case
  - Plugin manifests bumped to 1.17.0 to mirror the router
  - skills-lint.mjs: cargo-observability in SKILL_DIRS, observability
    in the known-CLI-domains allowlist
  - CHANGELOG entries; regenerated skill-metadata.json

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017UzK9huhSm588ThVFS1GcE

* Document defineAlert in the cargo-cdk skill

Wires the new observability domain into the declarative skill so alerts
can be managed as workspace-as-code, not only via the imperative CLI.

cargo-cdk → 1.2.0:
  - references/resources.md: defineAlert Builders-table row + a "Notes on
    specific fields" entry — the scope↔threshold matched pair (TS narrows
    the metric menu by scope.kind), scope wiring by handle, the {ref,config}
    action wrapper + alertConnectorAction/alertToolAction helpers +
    {{event.*}}/{{alert.*}} templating, and the slugless-identity note
  - guides/authoring-resources.md: an Observability example wiring an alert
    to a definePlay handle with an agent action
  - SKILL.md §6: alert added to the slugless "commit cargo.state.json"
    resources; new critical rule that a defineAlert whose actions call paid
    nodes re-bills on every breach (preview the threshold; prefer cheap
    notification actions); cross-links to cargo-observability

Also: cargo-observability scopes reference now states telemetry duration is
in seconds (confirmed authoritative from the CDK builder types).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017UzK9huhSm588ThVFS1GcE

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-09 15:57:34 -07:00
Auree Aubert 286aaaf981 feat: prompt library + generated skill metadata (#55)
Rebased onto main (post #53/#54 squash): 38 named parameterized LLM prompts in
six sharded files with a grep-first index (temperature guidance scoped to the
bulk tier; judgment-tier models that reject non-default sampling get no
override), plus a generated skill-metadata.json per skill — typed doc catalog
+ deterministic content hash (code-unit ordering, locale-independent),
produced by .github/scripts/skills-metadata.mjs (--write) and verified by
skills-lint.mjs so stale metadata fails CI. Metadata regenerated over main's
tree, which is why lint was failing before: the catalogs predated main's
email_status recipe fix. cargo-gtm -> 1.4.0.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 00:26:04 -07:00
Auree Aubert 2792b990ed feat(gtm): executable QA layer — fixture-tested contact-accuracy scripts (#53)
* feat(gtm): executable QA layer — fixture-tested contact-accuracy scripts

Four deterministic TypeScript scripts under cargo-gtm/scripts/ (Node >= 22.18
native type-stripping, zero deps in file mode) replace in-context row checking:

- validate-emails.ts        free syntax/risk/duplicate cull before paid verifyEmail
- select-current-role.ts    current role from an experiences array (job changers)
- validate-linkedin-names.ts name<->profile match (same-name decoys); P>=0.95/R>=0.85 gate
- contact-accuracy-audit.ts  final per-row SEND/VERIFY/REVIEW/REMOVE stamp

Each reads --input CSV/JSON or a finished run directly (--workflow-uuid via
@cargo-ai/api, reusing the CLI's stored login) and self-tests with --fixtures
(152 synthetic cases total). New qa-script-fixtures CI job runs every suite on
push/PR. Doctrine in references/contact-accuracy.md ("run the script, don't
re-derive"); wired into the router (new section 8, spine step 8) and the
prospecting / outreach-activation verify steps. cargo-gtm -> 1.2.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(gtm): provider playbooks 6 → 20 + read-first gate (#54)

Fourteen new per-provider playbooks grounded in live `connection integration
get` schemas: sourcing/company-data (linkedin, proxycurl, apolloio, oceanio,
datagma), email/contact (hunter, prospeo, icypeas, findyMail, leadMagic,
contactOut, zeroBounce), research (firecrawl, serper). Each carries the action
table with credit costs, real config-shape examples, input quirks, cost traps,
and its recipe-spine position.

Router §11 opens with a hard read-first stop before any paid call to a covered
provider; the linter now errors when a playbook on disk is missing from the
SKILL.md catalog.

Grounding also surfaced and fixed a recipe bug: linkedin-url-lookup.md
documented findProfileUrl inputs that don't exist — the live schema is
fullName (required) + companyName. Stale cost-table rows (prospeo.verifyEmail,
serper pricing) flagged in the CHANGELOG for the next regeneration.
cargo-gtm -> 1.3.0.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

* fix(gtm): QA-chain review feedback — six wiring bugs in scripts and recipes

- contact-accuracy-audit.ts: detect a bare "status" header (raw waterfall
  verifyEmail rows) as the verification column, lowest priority so specific
  headers still win; two new fixture cases.
- lib/common.ts: accept raw execute-batch output ({"results": [...]} /
  {"records": [...]}) in JSON inputs — no jq unwrap needed.
- validate-emails.ts + contact-accuracy-audit.ts: new --json flag emits rows
  as a JSON array for jq chaining; duplicates now get recommendation "skip"
  so they never enter the paid verify batch (savings count includes them).
- prospecting.md step 6/6.5: the paid verify batch is built from the culled
  output (recommendation != "skip"), an explicit merge step joins statuses
  back onto ALL rows before the audit, and only audit_action == "SEND" rows
  proceed to write-back.
- outreach-activation.md step 4: same cull -> verify survivors -> merge ->
  audit-all -> SEND-only flow; steps 5-6 now read the audited SEND set
  (deliverable.json), with the step-5/6 jq paths fixed for array input.
- contact-accuracy.md: documents the never-pre-filter-to-valid rule, the
  execute-batch input support, and --json.

All four fixture suites pass; the full recipe chain was exercised end-to-end
on simulated batch outputs (disposable + duplicate culled before payment,
catch-all single-source -> VERIFY, only SEND rows in the handoff set).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(gtm): case-insensitive status merge; strict identity coverage; dedupe verdict

- Recipes: the verification-status merge now joins on the lowercased email —
  verifyEmail results may re-case the address, and a missed join left
  emailStatus empty, silently degrading deliverable rows to VERIFY.
- contact-accuracy-audit.ts: identityColumnsPresent now requires BOTH
  name_match and role_confidence columns — one upstream script alone no
  longer masks partial identity coverage (partial-signals flag stays on).
- contact-accuracy-audit.ts: new duplicate-row REMOVE rule reading the
  is_duplicate column — a later occurrence of an address never reaches the
  sequencer even when all other signals are green (found while re-testing:
  the case-insensitive join let the dupe inherit "valid" and SEND).

23 fixture cases pass; chain re-run with re-cased verify results yields
exactly one SEND.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(gtm): merge verifyEmail via email_status, not status

waterfall.verifyEmail batch rows expose the verdict on email_status per the
connector output schema. The recipe merge jq read .status, so merged rows got
an empty emailStatus and contact-accuracy-audit stamped VERIFY instead of SEND.

Co-authored-by: Auree Aubert <aureeaubert@users.noreply.github.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Auree Aubert <aureeaubert@users.noreply.github.com>
2026-07-10 00:16:01 -07:00
Auree Aubert a418d76ee7 Fan the plugin out to Codex and Cursor; bundle session-lifecycle hooks (#50)
* Fan the plugin out to Codex and Cursor; bundle session-lifecycle hooks

- One plugin source, three targets: .agents/plugins/marketplace.json
  (Codex) + .cursor-plugin/marketplace.json, with .codex-plugin/ and
  .cursor-plugin/ plugin manifests version-locked to the router
  (linter-enforced across all three, negative-tested). The approval hook
  is wired per target - PreToolUse (Claude Code), PermissionRequest via
  hooks/codex-hooks.json (Codex), beforeShellExecution via
  hooks/cursor-hooks.json (Cursor) - reusing approve-cli.sh's existing
  per-agent verdict dispatch.
- Plugin-bundled lifecycle hooks (Claude Code): session-start (pinned
  CLI refresh from the plugin's own cli-version + placeholder session
  row; deliberately no skills add - the plugin owns the skills),
  session-checkpoint (Stop; jq-derived title, 45s throttle), and
  session-end (sync finalize + detached claude -p refinement). Each
  defers when the installer's counterpart exists at ~/.claude/hooks/,
  so installer + plugin never double-register a session.
- .gitignore: un-ignore .agents/plugins/ (vendored skills stay ignored).
- README: per-target install steps; router 1.11.0, plugins 1.11.0.

Verified: lint 0/0; scripts behavior-tested with stubbed npm/cargo-ai
(pin read from plugin root, defer guards, checkpoint derivation +
throttle, --finished finalize); live plugin install on Claude Code
2.1.205 shows all four hook events and both extra manifests in the
1.11.0 cache.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Make the plugin the single source of truth; agent-portable docs

- session-start.sh now also refreshes the plugin itself (marketplace
  update + plugin update, detached, effective next session) - the plugin
  channel's replacement for the installer's skills-add refresh, with
  zero duplication by construction.
- Docs made agent-portable: the pinned-install command in cargo/SKILL.md
  and prerequisites.md reads cli-version from the skill directory the
  agent loaded instead of hardcoding ~/.claude/skills/ (which silently
  degraded Codex/Cursor to @latest); manual-path session titles are
  agent-neutral; job 1 says to skip skills add when skills came from a
  plugin; the permission-prompts note covers all three agents' events.
- README Claude Code section describes the refactored installer flow
  (installs the plugin; skills add only as fallback; legacy scaffolding
  migrated away). cargo 1.12.0, plugins 1.12.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Single-source the lifecycle scripts: dual-mode plugin/standalone

The three hooks/session-*.sh scripts are now the only copies of the
session lifecycle - the installer's fallback channel downloads them
instead of embedding heredocs. Mode auto-detects from location
(~/.claude/hooks/ = standalone; anywhere else = plugin) with an explicit
plugin|standalone arg override:

- standalone: skills add refresh, pin from ~/.claude/skills/cargo/,
  no plugin self-update, never defers.
- plugin: pin from plugin root, detached plugin self-update, no skills
  add, defers when a standalone copy exists (exactly one lifecycle runs).

Log lines carry the mode. Behavior-tested both modes of all three
scripts with stubbed npm/npx/cargo-ai/claude (mode detection, defer,
no-self-defer, per-mode pin paths, per-mode refresh, mode-aware logs).
cargo 1.13.0, plugins 1.13.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(lifecycle): registration-aware defer, wider PATH, checkpoint hygiene

Review feedback on the lifecycle scripts:

- Defer guard now requires the standalone copy to be REGISTERED in
  ~/.claude/settings.json, not merely present - an unregistered leftover
  file no longer suppresses the plugin copy (which would silently skip
  CLI pinning and session logging). Falls back to file existence when jq
  is unavailable.
- session-start's PATH widening for the detached plugin self-update now
  matches session-end's full list (Volta, asdf shims, nvm version dirs,
  /opt/node*) so `claude` resolves under version managers and the
  update isn't silently skipped.
- Checkpoint prompt snippets strip control characters. The reported
  command-substitution injection does not exist - shell assignments and
  quoted expansions never evaluate a value's content, and the upsert
  passes --title/--summary as single argv words (verified empirically:
  $(touch ...) and backticks pass through as literal data) - but control
  chars could mangle logs/rows, so they are removed and the inertness is
  documented in a comment for future reviewers.

Verified: unregistered leftover -> plugin runs; registered standalone ->
plugin defers; clean env -> runs; injection payload inert with ESC
sequences stripped from the stored title.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(lifecycle): run when standalone registration is unverifiable

Review follow-up: the defer guard's no-jq / no-settings.json fallback
returned "owned" (defer), which silently skipped CLI pinning and session
logging whenever registration couldn't be checked - exactly the failure
the registration-awareness was meant to prevent. Flipped: when jq or
settings.json is unavailable, default to NOT owned so the plugin copy
runs. Safe direction - the session upsert is idempotent, so a duplicate
with an active standalone is harmless, whereas a wrong defer is a silent
skip. Unit-tested all five branches (registered->defer; not-registered,
no-settings, no-jq, no-file->run).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 18:33:21 -07:00
Auree Aubert 1cb3ee755b Claude Code plugin channel, cargo-ai approval hook, and CLI version pin (#51)
* Add Claude Code plugin channel and cargo-ai auto-approve hook

- .claude-plugin/marketplace.json + plugin.json: the repo root doubles as
  a Claude Code plugin (skills scan root "./" discovers all 15 top-level
  skill dirs with no restructuring; plugin version mirrors the router's,
  now linter-enforced).
- hooks/approve-cli.sh: allow-only PreToolUse hook that auto-approves
  cargo-ai / npx @cargo-ai/cli calls and read-only pipe helpers after a
  quote-aware structural pass. Never auto-approves: login/logout,
  workspaceManagement token/report, cdk deploy/destroy, or any
  remove/delete/destroy token. Verified with a 49-case harness plus a
  live end-to-end test (clean permissions: whoami auto-approved, token
  list fell through to prompt).
- README: plugin install path + pick-one-channel note; prerequisites.md
  gains a "Permission prompts" section. cargo 1.9.0, plugin 1.9.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Pin the CLI version in cargo/cli-version

- New cargo/cli-version (1.0.29): single-line semver pin, the source of
  truth for which @cargo-ai/cli these skills were written against. Lives
  inside the router skill so it ships with skills add and the ClawHub
  bundle; session hooks read it locally with a latest fallback, so the
  pin can never block an install.
- Linter asserts the pin exists and is bare semver, and that openclaw
  install blocks stay @cargo-ai/cli@latest (bootstrap only; the session
  hook converges to the pin).
- Docs: router session job 1 reordered (skills add -> pinned npm
  install) with a "why the pin" note; prerequisites.md and README
  refresh snippets use the pinned form. cargo 1.10.0, plugin 1.10.0.

The producer side (CLI release pipeline PRs pin bumps here; install.sh
consumes the raw pin URL) lands in getcargohq/cargo separately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(approve-cli): position-independent gating closes token-shift bypass

Review finding: gated checks only examined the first two non-flag tokens
after the binary/package. Valid invocation prefixes shift the real
subcommand out of those slots - `npx -p @cargo-ai/cli cargo-ai login`
puts a literal cargo-ai before login (confirmed auto-approved), and a
global flag with a value would shift the domain word the same way.

Fix: normalize the cargo segment's token stream once, drop leading
`cargo-ai` binary tokens, and gate position-independently - credential
tokens (login/logout), destructive verbs (remove/delete/destroy), and
gated adjacent pairs (workspaceManagement token/report, cdk
deploy/destroy) anywhere in the segment refuse approval. Accepted cost,
documented: a gated word as a literal inside a quoted argument (SQL
containing "login") now falls through to the prompt - the safe
direction for an allow-only hook.

Harness extended to 62 cases: all -p/token-shift/flag-shift bypass
shapes prompt; safe -p usage still auto-approves.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 18:30:56 -07:00
Auree Aubert f5566657fa Add cargo-diagnostics skill, interaction conventions, and catalog fixes (#48)
- New capability skill cargo-diagnostics: forensic runbooks (run-trace,
  batch-error-sweep, play-optimize-credits) that sequence run get,
  orchestration SQL, and billing metrics into diagnoses, linking existing
  references instead of duplicating them.
- New shared reference cargo/references/interaction.md: plan gate before
  building, recommended-default choices, presenting defaults.
- Catalog hygiene: stale skill counts fixed (AGENTS.md said ten, router
  said thirteen, README said fourteen -> fifteen everywhere), ClawHub
  publish loop catches up cargo-quickstart/cargo-content/cargo-hosting
  and adds cargo-diagnostics, README owner prose matches CLAWHUB_OWNER.
- Version bumps: cargo 1.8.0, cargo-gtm 1.1.1, cargo-orchestration 1.5.1,
  cargo-billing 1.0.2, cargo-diagnostics 1.0.0 (new). CHANGELOG updated.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 17:53:48 -07:00
Auree Aubert 915b5a29bb Terminal-experience quick wins: quickstart, cost discipline, save-as-play, anti-drift (#45)
* Terminal-experience quick wins: quickstart, cost discipline, save-as-play, anti-drift

From the 2026-07-08 terminal-experience eval:

- New cargo-quickstart skill: persona question → 25 leads in <2 min →
  receipt → save as a recurring play (fast path verified live; fields,
  retrieval flow, and the 25-row minimum page documented from observation)
- New cargo-gtm/references/cost-discipline.md: blocking pilot→approval→
  full-run gate, per-run receipts (credits + balance + hit-rate +
  estimate-vs-actual), 1.4×N over-provision, count-first sizing,
  pay-on-success and phone guards, context discipline — wired into
  cargo-gtm SKILL.md, the plan agent, waterfall-strategy, build-tam
- New cargo-gtm/recipes/save-as-play.md: ad-hoc run → durable play/tool
  with cadence defaults per signal and recurring-cost approval
- Grounded next-step spec (5-part shape) + end-of-session share ask
  (consented session traces via workspaceManagement report)
- Provider playbooks: Anti-patterns sections (field-name case traps,
  billed-on-returned-rows, PDL parameters wrapper), waterfall position
  + dynamic demotion rules; verification hard rules (independent
  validation, catch-all double-confirmation)
- Anti-drift: linter now lints cargo-content/cargo-hosting (previously
  skipped), and fails on skills or recipes missing from the router /
  recipe tables; fixed the drifted README recipe table and skill counts
- Removed the --is-finished flag from download-outputs snippets (API
  rejects it; CLI bug reported)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(cargo-quickstart): fallback rung 3 must ask before exceeding the demo's paid cap

waterfall.searchProspects at 3/record × 5 rows (~15 credits) blows the
~1-credit demo budget — gate it behind an explicit yes (with the free
connect-Sales-Navigator alternative offered) instead of just explaining
the cap after the fact.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 21:37:58 -07:00
Auree Aubert d2ff86b5b5 Add cargo-cdk skill for declarative workspace-as-code (#43)
Adds the cargo-cdk capability skill covering the cdk CLI domain
(@cargo-ai/cdk): SKILL.md with the declarative-vs-imperative decision
model and init → types → plan → deploy → destroy lifecycle, three
guides (authoring-resources, deploy-and-state, typed-config), five
recipes, and references (resources, commands, troubleshooting,
full-workspace example).

Registers it everywhere: router (cargo/SKILL.md → 1.6.0, skill count
11→12, decision block + table row + recap + dependency-diagram box),
README (12→13 skills, CDK table row), CHANGELOG, skills-lint SKILL_DIRS
+ cdk domain, and the clawhub publish loop.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 18:41:23 -07:00
Auree Aubert 4c933393dd Extract content domain into dedicated cargo-content skill (#35)
* Migrate file/library docs to the new content domain + register new CLI surfaces

The CLI moved workspace files and knowledge libraries out of the `ai` domain
into a new top-level `content` domain (`content file`, `content library`), and
added inline `ai document`. The old `cargo-ai ai file ...` commands no longer
exist.

- cargo-ai (2.0.0): migrate every `ai file` reference to `content file`;
  document `content library` (native vs connector-backed) and `ai document`;
  rename the Files section and add a command-surface-change callout.
- cargo (1.2.0): register the content domain in the recap/table, add a
  "CLI domains without a dedicated skill yet" table (segmentation, expression,
  system-of-record, revenue-organization, hosting, user-management), add
  glossary entries for the content domain and libraries.
- cargo-context (1.0.2), cargo-orchestration: fix cross-skill RAG examples.
- skills-lint: add the new CLI domains to the known-domain allowlist.

* cargo-context/cargo-ai: document content files exposed read-only under .files/

Uploaded `content file` knowledge surfaces in the context runtime sandbox under
a read-only `.files/` directory that sits outside the committed context tree, so
sandbox commands can consume content uploads without round-tripping them back
into the context repo.

* Split the content domain into a dedicated cargo-content skill

The content CLI domain (files + libraries) was documented inside cargo-ai.
Per the repo's one-skill-per-CLI-domain convention, extract it into its own
cargo-content capability skill:

- New cargo-content/ skill: files + libraries command docs, the moved
  examples/files.md walkthrough, response shapes, and troubleshooting.
- cargo-ai keeps inline documents (ai document) and the attach-to-agent
  wiring; cross-links cargo-content for files/libraries.
- Register cargo-content across the router overview (cargo/SKILL.md table,
  recap, dependency diagram/rules, counts), glossary, README, and AGENTS.md.
- cargo-context documents content files mounted read-only under .files/.
- Version bumps: cargo 1.3.0, cargo-ai 2.1.0, cargo-content 1.0.0,
  cargo-context 1.1.0; CHANGELOG updated.

* Drop ai document from cargo-ai; correct content file response shape

- Remove the low-value ai document (inline documents) commands from cargo-ai
  and scrub document references from the router overview, README, glossary,
  and the cargo-content files.md walkthrough.
- Reframe cargo-ai's knowledge section around files & libraries only.
- Update the content file list response shape to match the workspace File
  type: libraryUuid, userUuid, isIndexedInOpenAiVectorStore, externalId,
  deletedAt, and the native/connector kind union (connectorUuid).

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-08 00:42:38 -07:00
Auree Aubert c7bec7d8c4 Share prerequisites, lint SKILL.md, deep-link the router (#33)
- Extract the duplicated install/login/output-conventions block from every
  capability skill into cargo/references/prerequisites.md. Each capability
  skill now links to it instead of redefining ~16 lines of boilerplate.
- Add CHANGELOG.md so per-skill version bumps are tracked alongside the
  reason for each bump, and capture the current version snapshot as the
  historical baseline.
- Add a CI skill-lint job (.github/workflows/skills-lint.yml +
  .github/scripts/skills-lint.mjs) that validates SKILL.md frontmatter
  shape, internal markdown links, fenced JSON snippets, and that bash
  examples reference real cargo-ai domains. Catches drift before users do.
- Reorder cargo-connection so the integration/connector key concepts sit
  above Prerequisites (where they're needed before reading commands), and
  tighten the integration get vs native-integration get table with ✓/✗
  markers to make mis-routing harder.
- Deep-link the skill graph in cargo/SKILL.md so each row in the
  capability table jumps straight to the target SKILL.md, with the
  in-page recap available as a secondary link.
- Bump versions on each touched skill.

Co-authored-by: Claude <noreply@anthropic.com>
2026-05-28 15:11:38 -07:00
Auree Aubert 9bc21280e1 Update ClawHub publish workflow for cargo-ai org (#26)
* Set CLAWHUB_OWNER to cargo-ai

The ClawHub owner namespace for these skills is cargo-ai, not the
GitHub org name getcargohq.

* Trigger ClawHub publish on push to main

Merging a PR did not publish skills because the workflow only fired on
release: published and workflow_dispatch. Add push to main so every merge
attempts to publish; the publish step already skips versions that are
already published, so re-runs are safe no-ops.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-05-28 11:25:20 -07:00
Auree Aubert f607681791 Restructure skill metadata for OpenClaw compatibility (#25)
* Make cargo skills installable on OpenClaw via ClawHub

Promote `version` to top-level frontmatter and add `metadata.openclaw`
(requires.bins + install spec for @cargo-ai/cli) to every SKILL.md so
the bundle resolves through ClawHub without a separate manifest. Adds a
README install snippet for the `clawhub install` command.

* Add GitHub Actions workflow to publish skills to ClawHub on release

Triggers on `release: published` (and supports manual workflow_dispatch
with optional dry_run). Iterates the ten skill directories, reads
`version:` from each SKILL.md, and calls `clawhub skill publish` with
the release notes as the changelog. Treats "version already published"
as a skip so unchanged skills don't fail the run, and surfaces any
other publish error.

Auth uses the `CLAWHUB_AUTH` env var (avoids writing the token to disk)
sourced from a `CLAWHUB_TOKEN` repo secret. README documents the
one-time secret setup.

* Fix ClawHub publish workflow against the real CLI surface

The previous workflow was built from hallucinated WebFetch summaries.
After reading openclaw/clawhub's docs/cli.md and docs/auth.md directly:

- Auth uses `clawhub login --token <token>`, not a `CLAWHUB_AUTH` env
  var, so the workflow now runs a login step. Tokens are generated
  from the clawhub.ai web UI after GitHub sign-in (the previous
  `clawhub.openclaw.ai/settings/tokens` URL doesn't resolve).
- `clawhub skill publish` only accepts `--version`, `--owner`,
  `--migrate-owner`, and `--clawscan-note`. The previous workflow's
  `--slug`, `--name`, and `--changelog` flags don't exist; slug is
  derived from folder name. Workflow now passes only `--version` plus
  `--owner getcargohq` so the bundle lives under the org publisher.
- ClawHub requires semver three-part versions; bumped each SKILL.md
  `version:` from `1.0`/`1.1`/`1.4` to the matching `x.y.0` form so
  the CLI's semver check passes.
- README updated with the corrected token URL (clawhub.ai) and a
  reminder to run `clawhub publisher create getcargohq` once before
  publishing under the org.

* Drop redundant `license: MIT` from each SKILL.md frontmatter

ClawHub publishes every skill under MIT-0 and its skill-format spec
says: "Do not add conflicting license terms in SKILL.md; ClawHub does
not support per-skill license overrides." The repo LICENSE at the root
still applies to the source files; the per-skill frontmatter only
needs to drop the field so the published bundle doesn't trip the
metadata-conflict check.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-05-28 11:17:40 -07:00