agentskeptic 0.1.3 → 0.1.5

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/README.md CHANGED
@@ -7,7 +7,9 @@
7
7
 
8
8
  AgentSkeptic answers with read-only SQL at verification time—not with trace success flags or chat narratives.
9
9
 
10
- Teams ship agent and automation workflows where traces, tool responses, and success flags look green while the database row is missing, stale, or wrong. AgentSkeptic closes that gap by comparing structured tool activity to read-only SQL against your SQLite or Postgres at verification time: it tells you whether observed state matched expectations derived from what the workflow claimed—not whether a step narrative sounded successful. It is a snapshot check, not proof of causality or execution.
10
+ Teams ship agent and automation workflows where traces, tool responses, and success flags look green while the database row is missing, stale, or wrong. AgentSkeptic compares structured tool activity to read-only SQL against your SQLite or Postgres at verification time and reports whether observed state matched expectations derived from what the workflow claimed—not whether the step narrative read as successful.
11
+
12
+ Use it when you need persisted rows checked against declared tool parameters at verification time before customer-facing actions, compliance evidence, or CI gates.
11
13
 
12
14
  ### Pasteable terminal proof (bundled demo)
13
15
 
@@ -50,7 +52,7 @@ steps:
50
52
  }
51
53
  ```
52
54
 
53
- [Why traces are not database truth](https://agentskeptic.com/database-truth-vs-traces)
55
+ [Database truth vs traces](https://agentskeptic.com/database-truth-vs-traces)
54
56
  <!-- discovery-acquisition-fold:end -->
55
57
 
56
58
  **One-sentence value:** Read-only SQL checks that your database **at verification time** matches **expectations derived from structured tool activity**—not whether a trace step “succeeded.”
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "appendix": {
16
16
  "slug": "/database-truth-vs-traces",
17
- "visitorProblemAnswer": "Teams ship agent and automation workflows where traces, tool responses, and success flags look green while the database row is missing, stale, or wrong. AgentSkeptic closes that gap by comparing structured tool activity to read-only SQL against your SQLite or Postgres at verification time: it tells you whether observed state matched expectations derived from what the workflow claimed—not whether a step narrative sounded successful. It is a snapshot check, not proof of causality or execution.",
17
+ "visitorProblemAnswer": "Teams ship agent and automation workflows where traces, tool responses, and success flags look green while the database row is missing, stale, or wrong. AgentSkeptic compares structured tool activity to read-only SQL against your SQLite or Postgres at verification time and reports whether observed state matched expectations derived from what the workflow claimed—not whether the step narrative read as successful.\n\nUse it when you need persisted rows checked against declared tool parameters at verification time before customer-facing actions, compliance evidence, or CI gates.",
18
18
  "intentPhrases": [
19
19
  "green trace wrong database row agent workflow",
20
20
  "trace says success but CRM row missing",
@@ -38,7 +38,12 @@
38
38
  "Green LangGraph or agent trace but wrong or missing Postgres row",
39
39
  "OpenAI-style tool loop reported success; CRM or SQLite state does not match",
40
40
  "CI passed on workflow logs; database side effect never showed up",
41
- "Need a gate before production: read-only verification, not more log volume"
41
+ "Need a gate before production: read-only verification, not more log volume",
42
+ "Green dashboards still happen when an AI agent writes wrong CRM data and you need read-only SQL before you trust the row.",
43
+ "When automation reports success while database records disagree with declared tool parameters until read-only verification, treat trace color as non-authoritative.",
44
+ "Debugging Postgres after a LangGraph run requires row-level truth at verification time beyond trace completion flags alone for customer-facing data.",
45
+ "When a Stripe webhook returns OK you still need the ledger database row to match before finance treats settlement as final and read-only SQL verifies persisted state.",
46
+ "CI can stay green on workflow logs while the database side effect is missing until a read-only gate surfaces ROW_ABSENT before production."
42
47
  ],
43
48
  "indexableGuides": [
44
49
  {
@@ -65,6 +70,45 @@
65
70
  "path": "/guides/pre-production-read-only-sql-gate",
66
71
  "navLabel": "Pre-production read-only SQL gate",
67
72
  "problemAnchor": "Need a gate before production: read-only verification, not more log volume"
73
+ },
74
+ {
75
+ "path": "/guides/ai-agent-wrong-crm-data",
76
+ "navLabel": "AI agent wrong CRM data read-only check",
77
+ "problemAnchor": "Green dashboards still happen when an AI agent writes wrong CRM data"
78
+ },
79
+ {
80
+ "path": "/guides/automation-success-database-mismatch",
81
+ "navLabel": "Automation success vs database mismatch",
82
+ "problemAnchor": "When automation reports success while database records disagree with declared tool parameters until read-only verification"
83
+ },
84
+ {
85
+ "path": "/guides/debug-postgres-after-langgraph",
86
+ "navLabel": "Debug Postgres after LangGraph runs",
87
+ "problemAnchor": "Debugging Postgres after a LangGraph run requires row-level truth at verification time beyond trace completion flags alone"
88
+ },
89
+ {
90
+ "path": "/guides/stripe-webhook-database-alignment",
91
+ "navLabel": "Stripe webhook OK vs database alignment",
92
+ "problemAnchor": "When a Stripe webhook returns OK you still need the ledger database row to match before finance treats settlement as final"
93
+ },
94
+ {
95
+ "path": "/guides/ci-green-missing-database-side-effect",
96
+ "navLabel": "CI green but missing database side effect",
97
+ "problemAnchor": "CI can stay green on workflow logs while the database side effect is missing until a read-only gate surfaces ROW_ABSENT before production"
98
+ }
99
+ ],
100
+ "indexableExamples": [
101
+ {
102
+ "path": "/examples/wf-complete",
103
+ "navLabel": "Bundled verified workflow (wf_complete)",
104
+ "problemAnchor": "Bundled wf_complete demo: read-only SQL matched the expected contacts row under the packaged registry at verification time.",
105
+ "embedKey": "wf_complete"
106
+ },
107
+ {
108
+ "path": "/examples/wf-missing",
109
+ "navLabel": "Bundled inconsistent workflow (wf_missing)",
110
+ "problemAnchor": "Bundled wf_missing demo: ROW_ABSENT when structured tool activity implied a row read-only SQL did not find at verification time.",
111
+ "embedKey": "wf_missing"
68
112
  }
69
113
  ],
70
114
  "shareableTerminalDemo": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentskeptic",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Green agent traces and tool success flags often hide missing or wrong database rows. AgentSkeptic runs read-only SQL at verification time against persisted state vs structured tool activity—not chat narratives.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -38,6 +38,7 @@
38
38
  "sync:public-product-anchors": "node scripts/public-product-anchors.cjs",
39
39
  "distribution:consumer-pipeline": "node scripts/distribution-consumer-pipeline.mjs",
40
40
  "check:discovery-acquisition": "node scripts/validate-discovery-acquisition.mjs",
41
+ "verify:web-marketing-copy": "node scripts/validate-discovery-acquisition.mjs && node --test test/visitor-problem-outcome.test.mjs && npm run build -w agentskeptic-web && node scripts/run-website-vitest-with-reuse.mjs",
41
42
  "check:public-product-anchors": "node scripts/public-product-anchors.cjs --check",
42
43
  "test:commercial-layer": "node scripts/validate-commercial-funnel.mjs",
43
44
  "build:website": "npm run build && npm run build -w agentskeptic-web",
@@ -117,6 +117,39 @@ function validateIndexableGuides(discovery) {
117
117
  }
118
118
  }
119
119
 
120
+ /**
121
+ * @param {Record<string, unknown>} discovery
122
+ */
123
+ function validateIndexableExamples(discovery) {
124
+ const ex = /** @type {{ path: string; navLabel: string; problemAnchor: string; embedKey: string }[]} */ (
125
+ discovery.indexableExamples
126
+ );
127
+ if (!Array.isArray(ex)) {
128
+ throw new Error("discovery-acquisition: indexableExamples must be an array");
129
+ }
130
+ if (ex.length !== 2) {
131
+ throw new Error("discovery-acquisition: indexableExamples must have length exactly 2");
132
+ }
133
+ if (ex[0].path !== "/examples/wf-complete" || ex[1].path !== "/examples/wf-missing") {
134
+ throw new Error(
135
+ "discovery-acquisition: indexableExamples paths must be /examples/wf-complete then /examples/wf-missing",
136
+ );
137
+ }
138
+ if (ex[0].embedKey !== "wf_complete" || ex[1].embedKey !== "wf_missing") {
139
+ throw new Error(
140
+ "discovery-acquisition: indexableExamples embedKey order must be wf_complete then wf_missing",
141
+ );
142
+ }
143
+ for (let i = 0; i < ex.length; i++) {
144
+ const row = ex[i];
145
+ const nl = String(row.navLabel);
146
+ const pa = String(row.problemAnchor);
147
+ if (nl.includes("`") || pa.includes("`")) {
148
+ throw new Error(`discovery-acquisition: indexableExamples[${i}] must not contain backtick`);
149
+ }
150
+ }
151
+ }
152
+
120
153
  /**
121
154
  * @param {string} baseLlms
122
155
  * @param {Record<string, unknown>} discovery
@@ -136,6 +169,13 @@ function appendDiscoveryLlmsAppendix(baseLlms, discovery, canonicalOrigin) {
136
169
  out += `- ${origin}${String(g.path)}\n`;
137
170
  }
138
171
  }
172
+ const examples = /** @type {{ path: string }[] | undefined} */ (discovery.indexableExamples);
173
+ if (Array.isArray(examples) && examples.length > 0) {
174
+ out += "\n## Indexable examples\n";
175
+ for (const ex of examples) {
176
+ out += `- ${origin}${String(ex.path)}\n`;
177
+ }
178
+ }
139
179
  const demo = discovery.shareableTerminalDemo;
140
180
  if (demo && typeof demo.title === "string" && typeof demo.transcript === "string") {
141
181
  out += `\n## ${demo.title}\n\n\`\`\`text\n${demo.transcript}\n\`\`\`\n`;
@@ -182,6 +222,7 @@ function validateDiscoveryAcquisition(root) {
182
222
  );
183
223
  }
184
224
  validateIndexableGuides(discovery);
225
+ validateIndexableExamples(discovery);
185
226
  return discovery;
186
227
  }
187
228
 
@@ -191,5 +232,6 @@ module.exports = {
191
232
  appendDiscoveryLlmsAppendix,
192
233
  validateDiscoveryAcquisition,
193
234
  validateIndexableGuides,
235
+ validateIndexableExamples,
194
236
  discoveryPaths,
195
237
  };
@@ -125,6 +125,7 @@ function buildDiscoveryPayload(root) {
125
125
  relatedQueries: llms.relatedQueries.map(String),
126
126
  demandMoments: /** @type {string[]} */ (discovery.demandMoments).map(String),
127
127
  indexableGuides: /** @type {unknown} */ (discovery.indexableGuides),
128
+ indexableExamples: /** @type {unknown} */ (discovery.indexableExamples),
128
129
  shareableTerminalDemo: {
129
130
  title: String(demo.title),
130
131
  transcript: String(demo.transcript),
@@ -137,7 +138,7 @@ function buildDiscoveryPayload(root) {
137
138
  * @param {Record<string, unknown>} payload
138
139
  */
139
140
  function discoveryObjectFromAppendix(payload) {
140
- const ap = /** @type {{ slug: string; visitorProblemAnswer: string; intentPhrases: string[]; notFor: string[]; relatedQueries: string[]; demandMoments: string[]; indexableGuides?: { path: string; navLabel: string; problemAnchor: string }[]; shareableTerminalDemo?: { title: string; transcript: string } }} */ (
141
+ const ap = /** @type {{ slug: string; visitorProblemAnswer: string; intentPhrases: string[]; notFor: string[]; relatedQueries: string[]; demandMoments: string[]; indexableGuides?: { path: string; navLabel: string; problemAnchor: string }[]; indexableExamples?: { path: string; navLabel: string; problemAnchor: string; embedKey: string }[]; shareableTerminalDemo?: { title: string; transcript: string } }} */ (
141
142
  payload.appendix
142
143
  );
143
144
  const out = {
@@ -156,6 +157,9 @@ function discoveryObjectFromAppendix(payload) {
156
157
  if (Array.isArray(ap.indexableGuides)) {
157
158
  Object.assign(out, { indexableGuides: ap.indexableGuides });
158
159
  }
160
+ if (Array.isArray(ap.indexableExamples)) {
161
+ Object.assign(out, { indexableExamples: ap.indexableExamples });
162
+ }
159
163
  return out;
160
164
  }
161
165