@thirdfy/agent-cli 0.2.31 → 0.2.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ All notable changes to `@thirdfy/agent-cli` are documented here. The format is b
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.2.32] - 2026-07-23
8
+
9
+ ### Fixed
10
+
11
+ - `doctor certify execution` now keys live catalog and fixture rows by normalized action id (kebab/snake). Catalog `place-hyperliquid-perps-order` (and siblings) overwrite fixtures so required write actions resolve `source=catalog` instead of failing with `CATALOG_SCHEMA_UNAVAILABLE` / write-policy mismatch.
12
+
7
13
  ## [0.2.31] - 2026-07-23
8
14
 
9
15
  ### Added
package/README.md CHANGED
@@ -40,10 +40,9 @@ Run without global install:
40
40
  npx @thirdfy/agent-cli --help
41
41
  ```
42
42
 
43
- ## What's new in v0.2.31
43
+ ## What's new in v0.2.32
44
44
 
45
- - Validates action `--params` against catalog `paramsSchema` locally on `preflight`, `run`, and `wallet execute` before HTTP writes. Failures return `PARAMS_SCHEMA_INVALID` with field-level errors.
46
- - Adds `doctor certify execution` for a no-write certification report (CLI version, command availability, venue schema matrix, authority inputs). EarnClaw passes `--no-write`, `--run-mode`, `--schema-digest`, and `--required-actions` for fail-closed pack certification.
45
+ - Fixes `doctor certify execution` so live catalog schemas win when action names differ only by kebab vs snake case (Hyperliquid place/cancel/leverage and the same pattern on other venues).
47
46
 
48
47
  Older versions: see [CHANGELOG.md](./CHANGELOG.md) and [GitHub Releases](https://github.com/thirdfy/agent-cli/releases).
49
48
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thirdfy/agent-cli",
3
- "version": "0.2.31",
3
+ "version": "0.2.32",
4
4
  "description": "Thirdfy Agent CLI for onboarding, governance preflight, execute-intent, and status polling.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -76,9 +76,10 @@ export function computeActionSchemaDigest(actions) {
76
76
  }
77
77
 
78
78
  function mergeCatalogWithFixtures(liveActions) {
79
+ // Key by normalized action id so catalog kebab-case overwrites fixture snake_case.
79
80
  const byAction = new Map();
80
81
  for (const fixture of VENUE_WRITE_ACTION_FIXTURES) {
81
- byAction.set(fixture.action, {
82
+ byAction.set(normalizeActionKey(fixture.action), {
82
83
  action: fixture.action,
83
84
  aliases: fixture.aliases,
84
85
  provider: fixture.provider,
@@ -90,10 +91,12 @@ function mergeCatalogWithFixtures(liveActions) {
90
91
  for (const row of liveActions || []) {
91
92
  const action = String(row?.action || '').trim();
92
93
  if (!action) continue;
93
- const existing = byAction.get(action);
94
- byAction.set(action, {
94
+ const key = normalizeActionKey(action);
95
+ const existing = byAction.get(key);
96
+ const aliases = Array.isArray(row.aliases) ? row.aliases : existing?.aliases || [];
97
+ byAction.set(key, {
95
98
  action,
96
- aliases: Array.isArray(row.aliases) ? row.aliases : existing?.aliases || [],
99
+ aliases,
97
100
  provider: row.provider || row.providerId || existing?.provider || null,
98
101
  paramsSchema: row.paramsSchema || existing?.paramsSchema || null,
99
102
  requiredParams: Array.isArray(row.requiredParams) ? row.requiredParams : existing?.requiredParams || [],
@@ -104,9 +107,9 @@ function mergeCatalogWithFixtures(liveActions) {
104
107
  }
105
108
 
106
109
  function resolveCatalogRow(catalogByAction, action) {
107
- const direct = catalogByAction.get(action);
108
- if (direct) return direct;
109
110
  const normalized = normalizeActionKey(action);
111
+ const direct = catalogByAction.get(normalized) || catalogByAction.get(action);
112
+ if (direct) return direct;
110
113
  for (const row of catalogByAction.values()) {
111
114
  if (normalizeActionKey(row.action) === normalized) return row;
112
115
  for (const alias of row.aliases || []) {
@@ -117,9 +120,11 @@ function resolveCatalogRow(catalogByAction, action) {
117
120
  }
118
121
 
119
122
  function runSchemaCompatibilityChecks(catalogByAction, actionsToCheck, { requireLiveCatalog = false } = {}) {
120
- const fixturesByAction = new Map(VENUE_WRITE_ACTION_FIXTURES.map((fixture) => [fixture.action, fixture]));
123
+ const fixturesByAction = new Map(
124
+ VENUE_WRITE_ACTION_FIXTURES.map((fixture) => [normalizeActionKey(fixture.action), fixture]),
125
+ );
121
126
  return actionsToCheck.map((actionName) => {
122
- const fixture = fixturesByAction.get(actionName) || null;
127
+ const fixture = fixturesByAction.get(normalizeActionKey(actionName)) || null;
123
128
  const catalogRow = resolveCatalogRow(catalogByAction, actionName);
124
129
  const liveSchema = catalogRow?.source === 'catalog' ? catalogRow.paramsSchema : null;
125
130
  const schema = requireLiveCatalog ? liveSchema : catalogRow?.paramsSchema || fixture?.paramsSchema || null;