agentskeptic 1.0.4 → 1.2.0

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.
Files changed (186) hide show
  1. package/README.md +15 -17
  2. package/config/marketing.json +186 -0
  3. package/dist/actionableFailure.d.ts.map +1 -1
  4. package/dist/actionableFailure.js +80 -0
  5. package/dist/actionableFailure.js.map +1 -1
  6. package/dist/assurance/buildAssuranceOutput.d.ts +29 -0
  7. package/dist/assurance/buildAssuranceOutput.d.ts.map +1 -0
  8. package/dist/assurance/buildAssuranceOutput.js +53 -0
  9. package/dist/assurance/buildAssuranceOutput.js.map +1 -0
  10. package/dist/assurance/checkStale.d.ts +7 -0
  11. package/dist/assurance/checkStale.d.ts.map +1 -1
  12. package/dist/assurance/checkStale.js +14 -3
  13. package/dist/assurance/checkStale.js.map +1 -1
  14. package/dist/assurance/runAssurance.d.ts.map +1 -1
  15. package/dist/assurance/runAssurance.js +26 -3
  16. package/dist/assurance/runAssurance.js.map +1 -1
  17. package/dist/bootstrap/executeBootstrapPack.d.ts.map +1 -1
  18. package/dist/bootstrap/executeBootstrapPack.js +3 -2
  19. package/dist/bootstrap/executeBootstrapPack.js.map +1 -1
  20. package/dist/cli/lockOrchestration.js +1 -1
  21. package/dist/cli/runFunnelAnonSet.js +1 -1
  22. package/dist/cli.js +37 -5
  23. package/dist/cli.js.map +1 -1
  24. package/dist/cliArgv.d.ts.map +1 -1
  25. package/dist/cliArgv.js +4 -2
  26. package/dist/cliArgv.js.map +1 -1
  27. package/dist/cliOperationalCodes.d.ts +1 -0
  28. package/dist/cliOperationalCodes.d.ts.map +1 -1
  29. package/dist/cliOperationalCodes.js +1 -0
  30. package/dist/cliOperationalCodes.js.map +1 -1
  31. package/dist/commercial/licensePreflight.d.ts.map +1 -1
  32. package/dist/commercial/licensePreflight.js.map +1 -1
  33. package/dist/commercial/verifyWorkloadClassify.d.ts +2 -7
  34. package/dist/commercial/verifyWorkloadClassify.d.ts.map +1 -1
  35. package/dist/commercial/verifyWorkloadClassify.js +1 -1
  36. package/dist/commercial/verifyWorkloadClassify.js.map +1 -1
  37. package/dist/commercial/verifyWorkloadClassify.test.js +7 -0
  38. package/dist/commercial/verifyWorkloadClassify.test.js.map +1 -1
  39. package/dist/crossing/crossingDecisionReadyFooter.d.ts +1 -1
  40. package/dist/crossing/crossingDecisionReadyFooter.d.ts.map +1 -1
  41. package/dist/crossing/crossingDecisionReadyFooter.js +1 -1
  42. package/dist/crossing/crossingDecisionReadyFooter.js.map +1 -1
  43. package/dist/debug-ui/app.css +42 -0
  44. package/dist/debug-ui/app.js +202 -12
  45. package/dist/debug-ui/index.html +11 -4
  46. package/dist/debug-ui/urlState.d.ts +15 -0
  47. package/dist/debug-ui/urlState.js +92 -0
  48. package/dist/debugCorpus.test.js +33 -7
  49. package/dist/debugCorpus.test.js.map +1 -1
  50. package/dist/debugServer.js +1 -1
  51. package/dist/debugServer.js.map +1 -1
  52. package/dist/debugServer.test.js +12 -6
  53. package/dist/debugServer.test.js.map +1 -1
  54. package/dist/debugUiUrlState.test.d.ts +2 -0
  55. package/dist/debugUiUrlState.test.d.ts.map +1 -0
  56. package/dist/debugUiUrlState.test.js +49 -0
  57. package/dist/debugUiUrlState.test.js.map +1 -0
  58. package/dist/decisionGate.d.ts.map +1 -1
  59. package/dist/decisionGate.js +2 -5
  60. package/dist/decisionGate.js.map +1 -1
  61. package/dist/discovery-payload-v1.json +23 -27
  62. package/dist/failureOriginCatalog.d.ts.map +1 -1
  63. package/dist/failureOriginCatalog.js +16 -0
  64. package/dist/failureOriginCatalog.js.map +1 -1
  65. package/dist/firstFiveMinutesChecklist.d.ts +11 -0
  66. package/dist/firstFiveMinutesChecklist.d.ts.map +1 -0
  67. package/dist/firstFiveMinutesChecklist.js +18 -0
  68. package/dist/firstFiveMinutesChecklist.js.map +1 -0
  69. package/dist/funnel/workflowLineageClassify.d.ts +1 -1
  70. package/dist/funnel/workflowLineageClassify.js +1 -1
  71. package/dist/langGraphCheckpointTrustGate.d.ts.map +1 -1
  72. package/dist/langGraphCheckpointTrustGate.js +2 -5
  73. package/dist/langGraphCheckpointTrustGate.js.map +1 -1
  74. package/dist/operationalDisposition.d.ts +8 -0
  75. package/dist/operationalDisposition.d.ts.map +1 -1
  76. package/dist/operationalDisposition.js +8 -0
  77. package/dist/operationalDisposition.js.map +1 -1
  78. package/dist/pipeline.d.ts +1 -0
  79. package/dist/pipeline.d.ts.map +1 -1
  80. package/dist/pipeline.js +18 -18
  81. package/dist/pipeline.js.map +1 -1
  82. package/dist/publicDistribution.generated.d.ts +2 -2
  83. package/dist/publicDistribution.generated.d.ts.map +1 -1
  84. package/dist/publicDistribution.generated.js +7 -8
  85. package/dist/publicDistribution.generated.js.map +1 -1
  86. package/dist/quickVerify/runQuickVerify.js +1 -1
  87. package/dist/quickVerify/runQuickVerify.js.map +1 -1
  88. package/dist/quickVerify/verifyExecution.d.ts +1 -1
  89. package/dist/quickVerify/verifyExecution.d.ts.map +1 -1
  90. package/dist/quickVerify/verifyExecution.js +3 -2
  91. package/dist/quickVerify/verifyExecution.js.map +1 -1
  92. package/dist/reconciler.d.ts +6 -2
  93. package/dist/reconciler.d.ts.map +1 -1
  94. package/dist/reconciler.js +17 -11
  95. package/dist/reconciler.js.map +1 -1
  96. package/dist/registryDraft/createRegistryDraftAjv.d.ts +1 -1
  97. package/dist/registryDraft/createRegistryDraftAjv.js +1 -1
  98. package/dist/relationalInvariant.d.ts +13 -3
  99. package/dist/relationalInvariant.d.ts.map +1 -1
  100. package/dist/relationalInvariant.existsSql.test.js +1 -1
  101. package/dist/relationalInvariant.existsSql.test.js.map +1 -1
  102. package/dist/relationalInvariant.js +59 -39
  103. package/dist/relationalInvariant.js.map +1 -1
  104. package/dist/relationalInvariant.test.js +2 -2
  105. package/dist/relationalInvariant.test.js.map +1 -1
  106. package/dist/resolveExpectation.d.ts +18 -2
  107. package/dist/resolveExpectation.d.ts.map +1 -1
  108. package/dist/resolveExpectation.js +332 -1
  109. package/dist/resolveExpectation.js.map +1 -1
  110. package/dist/resolveExpectation.test.js +25 -0
  111. package/dist/resolveExpectation.test.js.map +1 -1
  112. package/dist/runComparison.d.ts.map +1 -1
  113. package/dist/runComparison.js +18 -3
  114. package/dist/runComparison.js.map +1 -1
  115. package/dist/schema-validation.test.js +29 -0
  116. package/dist/schema-validation.test.js.map +1 -1
  117. package/dist/schemaLoad.d.ts +1 -1
  118. package/dist/schemaLoad.d.ts.map +1 -1
  119. package/dist/schemaLoad.js +2 -0
  120. package/dist/schemaLoad.js.map +1 -1
  121. package/dist/sqlDialect.d.ts +8 -0
  122. package/dist/sqlDialect.d.ts.map +1 -0
  123. package/dist/sqlDialect.js +37 -0
  124. package/dist/sqlDialect.js.map +1 -0
  125. package/dist/stateWitness.d.ts +4 -0
  126. package/dist/stateWitness.d.ts.map +1 -0
  127. package/dist/stateWitness.js +383 -0
  128. package/dist/stateWitness.js.map +1 -0
  129. package/dist/stateWitness.test.d.ts +2 -0
  130. package/dist/stateWitness.test.d.ts.map +1 -0
  131. package/dist/stateWitness.test.js +120 -0
  132. package/dist/stateWitness.test.js.map +1 -0
  133. package/dist/telemetry/ossClaimOrigin.d.ts +1 -1
  134. package/dist/telemetry/ossClaimOrigin.js +1 -1
  135. package/dist/telemetry/verificationHypothesisContract.d.ts +1 -1
  136. package/dist/telemetry/verificationHypothesisContract.js +1 -1
  137. package/dist/types.d.ts +105 -2
  138. package/dist/types.d.ts.map +1 -1
  139. package/dist/types.js.map +1 -1
  140. package/dist/verificationConnections.d.ts +10 -0
  141. package/dist/verificationConnections.d.ts.map +1 -0
  142. package/dist/verificationConnections.js +190 -0
  143. package/dist/verificationConnections.js.map +1 -0
  144. package/dist/verificationDatabaseUrl.d.ts +11 -0
  145. package/dist/verificationDatabaseUrl.d.ts.map +1 -0
  146. package/dist/verificationDatabaseUrl.js +41 -0
  147. package/dist/verificationDatabaseUrl.js.map +1 -0
  148. package/dist/verificationDatabaseUrl.test.d.ts +2 -0
  149. package/dist/verificationDatabaseUrl.test.d.ts.map +1 -0
  150. package/dist/verificationDatabaseUrl.test.js +66 -0
  151. package/dist/verificationDatabaseUrl.test.js.map +1 -0
  152. package/dist/verificationDiagnostics.d.ts.map +1 -1
  153. package/dist/verificationDiagnostics.js +29 -8
  154. package/dist/verificationDiagnostics.js.map +1 -1
  155. package/dist/verificationDiagnostics.test.js +15 -0
  156. package/dist/verificationDiagnostics.test.js.map +1 -1
  157. package/dist/verificationPolicy.d.ts +2 -1
  158. package/dist/verificationPolicy.d.ts.map +1 -1
  159. package/dist/verificationPolicy.js +84 -0
  160. package/dist/verificationPolicy.js.map +1 -1
  161. package/dist/verificationPolicy.test.js +7 -0
  162. package/dist/verificationPolicy.test.js.map +1 -1
  163. package/dist/verificationUserPhrases.d.ts.map +1 -1
  164. package/dist/verificationUserPhrases.js +18 -0
  165. package/dist/verificationUserPhrases.js.map +1 -1
  166. package/dist/vitestMonorepoRoot.d.ts +10 -0
  167. package/dist/vitestMonorepoRoot.d.ts.map +1 -0
  168. package/dist/vitestMonorepoRoot.js +97 -0
  169. package/dist/vitestMonorepoRoot.js.map +1 -0
  170. package/dist/wireReasonCodes.d.ts +18 -0
  171. package/dist/wireReasonCodes.d.ts.map +1 -1
  172. package/dist/wireReasonCodes.js +18 -0
  173. package/dist/wireReasonCodes.js.map +1 -1
  174. package/package.json +29 -34
  175. package/schemas/assurance-output-v1.schema.json +81 -0
  176. package/schemas/openapi-commercial-v1.in.yaml +36 -3
  177. package/schemas/openapi-commercial-v1.yaml +37 -4
  178. package/schemas/tools-registry.schema.json +103 -0
  179. package/schemas/workflow-engine-result.schema.json +69 -1
  180. package/schemas/workflow-truth-report.schema.json +12 -0
  181. package/scripts/discovery-acquisition.lib.cjs +6 -17
  182. package/scripts/discovery-payload.lib.cjs +5 -3
  183. package/scripts/emit-primary-marketing.cjs +326 -0
  184. package/scripts/origin.cjs +52 -0
  185. package/scripts/public-product-anchors.cjs +3 -0
  186. package/scripts/validate-marketing.cjs +156 -0
@@ -72,12 +72,115 @@
72
72
  "items": { "$ref": "#/$defs/sqlRelationalCheck" }
73
73
  }
74
74
  }
75
+ },
76
+ {
77
+ "type": "object",
78
+ "additionalProperties": false,
79
+ "required": ["kind", "provider", "documentId", "indexName"],
80
+ "properties": {
81
+ "kind": { "const": "vector_document" },
82
+ "provider": { "type": "string", "enum": ["pinecone", "weaviate", "chroma"] },
83
+ "documentId": { "$ref": "#/$defs/stringSpec" },
84
+ "indexName": { "$ref": "#/$defs/stringSpec" },
85
+ "namespace": { "$ref": "#/$defs/stringSpec" },
86
+ "host": { "$ref": "#/$defs/stringSpec" },
87
+ "metadataEq": { "$ref": "#/$defs/requiredFieldsPointer" },
88
+ "expectPayloadSha256": { "$ref": "#/$defs/stringSpec" }
89
+ }
90
+ },
91
+ {
92
+ "type": "object",
93
+ "additionalProperties": false,
94
+ "required": ["kind", "bucket", "key"],
95
+ "properties": {
96
+ "kind": { "const": "object_storage_object" },
97
+ "bucket": { "$ref": "#/$defs/stringSpec" },
98
+ "key": { "$ref": "#/$defs/stringSpec" },
99
+ "endpoint": { "$ref": "#/$defs/stringSpec" },
100
+ "expectSizeBytes": { "$ref": "#/$defs/numberOrPointerSpec" },
101
+ "expectSha256": { "$ref": "#/$defs/stringSpec" },
102
+ "expectEtag": { "$ref": "#/$defs/stringSpec" }
103
+ }
104
+ },
105
+ {
106
+ "type": "object",
107
+ "additionalProperties": false,
108
+ "required": ["kind", "url"],
109
+ "properties": {
110
+ "kind": { "const": "http_witness" },
111
+ "method": { "type": "string", "enum": ["GET", "POST"] },
112
+ "url": { "$ref": "#/$defs/stringSpec" },
113
+ "expectedStatus": { "$ref": "#/$defs/numberOrPointerSpec" },
114
+ "assertions": {
115
+ "type": "array",
116
+ "items": { "$ref": "#/$defs/httpWitnessAssertion" }
117
+ }
118
+ }
119
+ },
120
+ {
121
+ "type": "object",
122
+ "additionalProperties": false,
123
+ "required": ["kind", "collection", "filterPointer", "requiredFields"],
124
+ "properties": {
125
+ "kind": { "const": "mongo_document" },
126
+ "collection": { "$ref": "#/$defs/stringSpec" },
127
+ "filterPointer": {
128
+ "type": "object",
129
+ "additionalProperties": false,
130
+ "required": ["pointer"],
131
+ "properties": {
132
+ "pointer": { "type": "string", "pattern": "^/" }
133
+ }
134
+ },
135
+ "requiredFields": { "$ref": "#/$defs/requiredFieldsPointer" }
136
+ }
75
137
  }
76
138
  ]
77
139
  }
78
140
  }
79
141
  },
80
142
  "$defs": {
143
+ "stringSpec": {
144
+ "oneOf": [
145
+ {
146
+ "type": "object",
147
+ "additionalProperties": false,
148
+ "required": ["const"],
149
+ "properties": { "const": { "type": "string", "minLength": 1 } }
150
+ },
151
+ {
152
+ "type": "object",
153
+ "additionalProperties": false,
154
+ "required": ["pointer"],
155
+ "properties": { "pointer": { "type": "string", "pattern": "^/" } }
156
+ }
157
+ ]
158
+ },
159
+ "numberOrPointerSpec": {
160
+ "oneOf": [
161
+ {
162
+ "type": "object",
163
+ "additionalProperties": false,
164
+ "required": ["const"],
165
+ "properties": { "const": { "type": "number" } }
166
+ },
167
+ {
168
+ "type": "object",
169
+ "additionalProperties": false,
170
+ "required": ["pointer"],
171
+ "properties": { "pointer": { "type": "string", "pattern": "^/" } }
172
+ }
173
+ ]
174
+ },
175
+ "httpWitnessAssertion": {
176
+ "type": "object",
177
+ "additionalProperties": false,
178
+ "required": ["jsonPointer", "value"],
179
+ "properties": {
180
+ "jsonPointer": { "type": "string", "minLength": 1 },
181
+ "value": { "$ref": "#/$defs/scalarOrPointer" }
182
+ }
183
+ },
81
184
  "tableSpec": {
82
185
  "oneOf": [
83
186
  {
@@ -414,6 +414,70 @@
414
414
  }
415
415
  }
416
416
  },
417
+ "verificationRequestVectorDocument": {
418
+ "type": "object",
419
+ "additionalProperties": false,
420
+ "required": ["kind", "provider", "documentId", "indexName"],
421
+ "properties": {
422
+ "kind": { "const": "vector_document" },
423
+ "provider": { "type": "string", "enum": ["pinecone", "weaviate", "chroma"] },
424
+ "documentId": { "type": "string", "minLength": 1 },
425
+ "indexName": { "type": "string", "minLength": 1 },
426
+ "namespace": { "type": "string" },
427
+ "host": { "type": "string", "minLength": 1 },
428
+ "metadataSubset": { "type": "object", "additionalProperties": true },
429
+ "expectPayloadSha256": { "type": "string", "minLength": 1 }
430
+ }
431
+ },
432
+ "verificationRequestObjectStorageObject": {
433
+ "type": "object",
434
+ "additionalProperties": false,
435
+ "required": ["kind", "bucket", "key"],
436
+ "properties": {
437
+ "kind": { "const": "object_storage_object" },
438
+ "bucket": { "type": "string", "minLength": 1 },
439
+ "key": { "type": "string", "minLength": 1 },
440
+ "endpoint": { "type": "string", "minLength": 1 },
441
+ "expectSizeBytes": { "type": "number", "minimum": 0 },
442
+ "expectSha256": { "type": "string", "minLength": 1 },
443
+ "expectEtag": { "type": "string", "minLength": 1 }
444
+ }
445
+ },
446
+ "httpWitnessResolvedAssertion": {
447
+ "type": "object",
448
+ "additionalProperties": false,
449
+ "required": ["jsonPointer", "value"],
450
+ "properties": {
451
+ "jsonPointer": { "type": "string", "minLength": 1 },
452
+ "value": { "type": ["string", "number", "boolean", "null"] }
453
+ }
454
+ },
455
+ "verificationRequestHttpWitness": {
456
+ "type": "object",
457
+ "additionalProperties": false,
458
+ "required": ["kind", "method", "url"],
459
+ "properties": {
460
+ "kind": { "const": "http_witness" },
461
+ "method": { "type": "string", "enum": ["GET", "POST"] },
462
+ "url": { "type": "string", "minLength": 1 },
463
+ "expectedStatus": { "type": "integer", "minimum": 100, "maximum": 599 },
464
+ "assertions": {
465
+ "type": "array",
466
+ "items": { "$ref": "#/$defs/httpWitnessResolvedAssertion" }
467
+ }
468
+ }
469
+ },
470
+ "verificationRequestMongoDocument": {
471
+ "type": "object",
472
+ "additionalProperties": false,
473
+ "required": ["kind", "collection", "filter", "requiredFields"],
474
+ "properties": {
475
+ "kind": { "const": "mongo_document" },
476
+ "collection": { "type": "string", "minLength": 1 },
477
+ "filter": { "type": "object", "additionalProperties": true },
478
+ "requiredFields": { "$ref": "#/$defs/requiredFieldsMap" }
479
+ }
480
+ },
417
481
  "effectOutcome": {
418
482
  "type": "object",
419
483
  "additionalProperties": false,
@@ -478,7 +542,11 @@
478
542
  { "$ref": "#/$defs/verificationRequestSqlRow" },
479
543
  { "$ref": "#/$defs/verificationRequestSqlRowAbsent" },
480
544
  { "$ref": "#/$defs/verificationRequestSqlEffects" },
481
- { "$ref": "#/$defs/verificationRequestSqlRelational" }
545
+ { "$ref": "#/$defs/verificationRequestSqlRelational" },
546
+ { "$ref": "#/$defs/verificationRequestVectorDocument" },
547
+ { "$ref": "#/$defs/verificationRequestObjectStorageObject" },
548
+ { "$ref": "#/$defs/verificationRequestHttpWitness" },
549
+ { "$ref": "#/$defs/verificationRequestMongoDocument" }
482
550
  ]
483
551
  },
484
552
  "status": {
@@ -624,6 +624,18 @@
624
624
  },
625
625
  {
626
626
  "$ref": "https://agentskeptic.com/schemas/workflow-engine-result.schema.json#/$defs/verificationRequestSqlRelational"
627
+ },
628
+ {
629
+ "$ref": "https://agentskeptic.com/schemas/workflow-engine-result.schema.json#/$defs/verificationRequestVectorDocument"
630
+ },
631
+ {
632
+ "$ref": "https://agentskeptic.com/schemas/workflow-engine-result.schema.json#/$defs/verificationRequestObjectStorageObject"
633
+ },
634
+ {
635
+ "$ref": "https://agentskeptic.com/schemas/workflow-engine-result.schema.json#/$defs/verificationRequestHttpWitness"
636
+ },
637
+ {
638
+ "$ref": "https://agentskeptic.com/schemas/workflow-engine-result.schema.json#/$defs/verificationRequestMongoDocument"
627
639
  }
628
640
  ]
629
641
  }
@@ -2,8 +2,6 @@
2
2
 
3
3
  const { existsSync, readFileSync, readdirSync } = require("node:fs");
4
4
  const { join } = require("node:path");
5
- const Ajv = require("ajv");
6
- const addFormats = require("ajv-formats");
7
5
 
8
6
  const PLACEHOLDER_KEYS = [
9
7
  ["{{ORIGIN}}", "ORIGIN"],
@@ -20,8 +18,7 @@ const PLACEHOLDER_KEYS = [
20
18
  */
21
19
  function discoveryPaths(root) {
22
20
  return {
23
- jsonPath: join(root, "config", "discovery-acquisition.json"),
24
- schemaPath: join(root, "config", "discovery-acquisition.schema.json"),
21
+ jsonPath: join(root, "config", "marketing.json"),
25
22
  };
26
23
  }
27
24
 
@@ -177,20 +174,12 @@ function appendDiscoveryLlmsAppendix(baseLlms, discovery, canonicalOrigin) {
177
174
  * @param {string} root
178
175
  */
179
176
  function validateDiscoveryAcquisition(root) {
180
- const { jsonPath, schemaPath } = discoveryPaths(root);
177
+ const { jsonPath } = discoveryPaths(root);
178
+ const { validateMarketing } = require("./validate-marketing.cjs");
179
+ validateMarketing(root);
181
180
  const discovery = JSON.parse(readFileSync(jsonPath, "utf8"));
182
- const schema = JSON.parse(readFileSync(schemaPath, "utf8"));
183
- const ajv = new Ajv({ allErrors: true, strict: true });
184
- addFormats(ajv);
185
- const validate = ajv.compile(schema);
186
- if (!validate(discovery)) {
187
- const msg = ajv.errorsText(validate.errors, { separator: "\n" });
188
- throw new Error(`discovery-acquisition: schema validation failed:\n${msg}`);
189
- }
190
- const anchorsPath = join(root, "config", "public-product-anchors.json");
191
- const anchors = JSON.parse(readFileSync(anchorsPath, "utf8"));
192
- const { normalize } = require("./public-product-anchors.cjs");
193
- const origin = normalize(anchors.productionCanonicalOrigin);
181
+ const { normalize } = require("./origin.cjs");
182
+ const origin = normalize(String(discovery.productionCanonicalOrigin));
194
183
  buildDiscoveryFoldBody(discovery, origin);
195
184
  const demo = discovery.shareableTerminalDemo;
196
185
  if (demo && String(demo.transcript).includes("```")) {
@@ -132,8 +132,10 @@ function buildDiscoveryPayload(root) {
132
132
  problemAnchor: padAnchor(path),
133
133
  embedKey: embedKeyForExamplePath(path),
134
134
  }));
135
- const anchorsPath = join(root, "config", "public-product-anchors.json");
136
- const anchors = JSON.parse(readFileSync(anchorsPath, "utf8"));
135
+ const pm = /** @type {{ productionCanonicalOrigin: string; identityOneLiner: string; gitRepositoryUrl: string; npmPackageUrl: string }} */ (
136
+ discovery
137
+ );
138
+ const anchors = pm;
137
139
  const canonicalOrigin = normalizeOrigin(anchors.productionCanonicalOrigin);
138
140
  const integrateUrl = `${canonicalOrigin}/integrate`;
139
141
  const learnHubUrl = `${canonicalOrigin}/guides`;
@@ -141,7 +143,7 @@ function buildDiscoveryPayload(root) {
141
143
  const { owner, repo } = parseGithubRepoFromUrl(anchors.gitRepositoryUrl);
142
144
  const llmsRaw = `https://raw.githubusercontent.com/${owner}/${repo}/refs/heads/${DISCOVERY_LLM_BRANCH}/llms.txt`;
143
145
  const llmsBlob = `https://github.com/${owner}/${repo}/blob/${DISCOVERY_LLM_BRANCH}/llms.txt`;
144
- const integratorVerificationSsotRaw = `https://raw.githubusercontent.com/${owner}/${repo}/refs/heads/${DISCOVERY_LLM_BRANCH}/docs/integrator-verification-ssot.md`;
146
+ const integratorVerificationSsotRaw = `https://raw.githubusercontent.com/${owner}/${repo}/refs/heads/${DISCOVERY_LLM_BRANCH}/docs/integrator-verification.md`;
145
147
  const openapiRaw = `https://raw.githubusercontent.com/${owner}/${repo}/refs/heads/${DISCOVERY_LLM_BRANCH}/schemas/openapi-commercial-v1.yaml`;
146
148
  const llms = /** @type {{ intentPhrases: string[]; notFor: string[]; relatedQueries: string[] }} */ (
147
149
  discovery.llms
@@ -0,0 +1,326 @@
1
+ "use strict";
2
+
3
+ const { readFileSync, writeFileSync, mkdirSync } = require("node:fs");
4
+ const { join, dirname } = require("node:path");
5
+ const { normalize, assertNextPublicOriginParity, MARKETING_PATH } = require("./origin.cjs");
6
+
7
+ const ROOT = join(__dirname, "..");
8
+
9
+ const OPENAPI_IN = join(ROOT, "schemas", "openapi-commercial-v1.in.yaml");
10
+ const OPENAPI_OUT = join(ROOT, "schemas", "openapi-commercial-v1.yaml");
11
+ const OPENAPI_PUBLIC = join(ROOT, "website", "public", "openapi-commercial-v1.yaml");
12
+ const LLMS_PUBLIC = join(ROOT, "website", "public", "llms.txt");
13
+ const LLMS_REPO_ROOT = join(ROOT, "llms.txt");
14
+ const README_PATH = join(ROOT, "README.md");
15
+ const PKG_PATH = join(ROOT, "package.json");
16
+
17
+ const README_START = "<!-- public-product-anchors:start -->";
18
+ const README_END = "<!-- public-product-anchors:end -->";
19
+ const DISCOVERY_README_START = "<!-- discovery-acquisition-fold:start -->";
20
+ const DISCOVERY_README_END = "<!-- discovery-acquisition-fold:end -->";
21
+ const DISCOVERY_README_TITLE_START = "<!-- discovery-readme-title:start -->";
22
+ const DISCOVERY_README_TITLE_END = "<!-- discovery-readme-title:end -->";
23
+
24
+ const TOKENS = [
25
+ "__IDENTITY_ONE_LINER__",
26
+ "__DISTRIBUTION_CONTACT_URL__",
27
+ "__DISTRIBUTION_INTEGRATE_URL__",
28
+ "__DISTRIBUTION_REPO_URL__",
29
+ "__DISTRIBUTION_NPM_URL__",
30
+ "__OPENAPI_SELF_URL__",
31
+ "__SERVERS_ORIGIN__",
32
+ ];
33
+
34
+ /**
35
+ * @param {string} haystack
36
+ * @param {string} needle
37
+ */
38
+ function countOccurrences(haystack, needle) {
39
+ let n = 0;
40
+ let i = 0;
41
+ while (true) {
42
+ const j = haystack.indexOf(needle, i);
43
+ if (j === -1) break;
44
+ n++;
45
+ i = j + needle.length;
46
+ }
47
+ return n;
48
+ }
49
+
50
+ function validateOpenapiTemplate() {
51
+ const template = readFileSync(OPENAPI_IN, "utf8");
52
+ for (const tok of TOKENS) {
53
+ const c = countOccurrences(template, tok);
54
+ if (c !== 1) {
55
+ throw new Error(`openapi template: token ${tok} must appear exactly once, found ${c}`);
56
+ }
57
+ }
58
+ }
59
+
60
+ function escapeYamlDoubleQuotedOneLiner(s) {
61
+ return String(s).replace(/\\/g, "\\\\").replace(/"/g, '\\"');
62
+ }
63
+
64
+ /**
65
+ * @param {Record<string, unknown>} anchors
66
+ */
67
+ function distributionSsotBlobUrl(anchors) {
68
+ const u = String(anchors.gitRepositoryUrl);
69
+ const m = u.match(/github\.com\/([^/]+)\/([^/#?]+)/i);
70
+ if (!m) throw new Error("emit-primary-marketing: cannot derive SSOT blob URL from gitRepositoryUrl");
71
+ const repo = m[2].replace(/\.git$/i, "");
72
+ return `https://github.com/${m[1]}/${repo}/blob/main/docs/public-distribution.md`;
73
+ }
74
+
75
+ /**
76
+ * @param {string} line
77
+ * @param {string} origin
78
+ * @param {string} slug
79
+ */
80
+ function expandCliFooterLine(line, origin, slug) {
81
+ const acquisitionUrl = `${origin}${slug}`;
82
+ const integrateUrl = `${origin}/integrate`;
83
+ let out = String(line)
84
+ .replace(/\{\{ORIGIN\}\}/g, origin)
85
+ .replace(/\{\{ACQUISITION_URL\}\}/g, acquisitionUrl)
86
+ .replace(/\{\{INTEGRATE_URL\}\}/g, integrateUrl);
87
+ if (out.includes("{{")) {
88
+ throw new Error(`emit-primary-marketing: unresolved placeholder in cliFollowupLines: ${line}`);
89
+ }
90
+ return out;
91
+ }
92
+
93
+ /**
94
+ * @param {Record<string, unknown>} anchors
95
+ * @param {Record<string, unknown>} discovery
96
+ */
97
+ function writePublicDistributionGenerated(anchors, discovery) {
98
+ const ssotUrl = distributionSsotBlobUrl(anchors);
99
+ const origin = normalize(anchors.productionCanonicalOrigin);
100
+ const slug = String(discovery.slug);
101
+ const cliLines = /** @type {string[]} */ (discovery.cliFollowupLines);
102
+ const expanded = cliLines.map((l) => expandCliFooterLine(l, origin, slug));
103
+ expanded.push(`Distribution contract (SSOT): ${ssotUrl}`);
104
+ if (expanded.length > 6) {
105
+ throw new Error(
106
+ `emit-primary-marketing: distribution footer exceeds 6 lines (${expanded.length}); shorten cliFollowupLines`,
107
+ );
108
+ }
109
+ const returnParts = expanded.map((line) => `${JSON.stringify(`${line}\n`)}`);
110
+ const pkgRaw = readFileSync(PKG_PATH, "utf8");
111
+ const pkgJson = JSON.parse(pkgRaw);
112
+ const cliSemver = String(pkgJson.version ?? "").trim();
113
+ if (!cliSemver) {
114
+ throw new Error("emit-primary-marketing: package.json missing version");
115
+ }
116
+ const body = `// Generated by npm run emit-primary-marketing — do not hand edit.
117
+
118
+ export const PUBLIC_DISTRIBUTION_SSOT_BLOB_URL = ${JSON.stringify(ssotUrl)};
119
+
120
+ export const PUBLIC_CANONICAL_SITE_ORIGIN = ${JSON.stringify(origin)};
121
+
122
+ export const AGENTSKEPTIC_CLI_SEMVER = ${JSON.stringify(cliSemver)};
123
+
124
+ export function formatDistributionFooter(): string {
125
+ return ${returnParts.join("\n + ")};
126
+ }
127
+ `;
128
+ writeFileSync(join(ROOT, "src", "publicDistribution.generated.ts"), body, "utf8");
129
+ }
130
+
131
+ /**
132
+ * @param {Record<string, unknown>} anchors
133
+ * @param {Record<string, unknown>} discovery
134
+ */
135
+ function writeAgentsMd(anchors, discovery) {
136
+ const url = distributionSsotBlobUrl(anchors);
137
+ const origin = normalize(anchors.productionCanonicalOrigin);
138
+ const slug = String(discovery.slug);
139
+ const acquisitionUrl = `${origin}${slug}`;
140
+ const dp = require("./discovery-payload.lib.cjs");
141
+ const { owner, repo } = dp.parseGithubRepoFromUrl(String(anchors.gitRepositoryUrl));
142
+ const branch = dp.DISCOVERY_LLM_BRANCH;
143
+ const llmsRaw = `https://raw.githubusercontent.com/${owner}/${repo}/refs/heads/${branch}/llms.txt`;
144
+ const openapiRaw = `https://raw.githubusercontent.com/${owner}/${repo}/refs/heads/${branch}/schemas/openapi-commercial-v1.yaml`;
145
+ const body = `# AGENTS
146
+
147
+ Normative **public distribution** and anchor sync: [\`docs/public-distribution.md\`](docs/public-distribution.md) (same content as ${url}).
148
+
149
+ ## Machine-readable product entrypoints
150
+
151
+ - Committed \`llms.txt\` at repo root (same bytes as site \`/llms.txt\` after prebuild sync).
152
+ - Raw GitHub \`llms.txt\`: ${llmsRaw}
153
+ - OpenAPI YAML (repo raw): ${openapiRaw}
154
+ - Acquisition page (canonical): ${acquisitionUrl}
155
+ `;
156
+ writeFileSync(join(ROOT, "AGENTS.md"), body, "utf8");
157
+ }
158
+
159
+ function syncPrimaryMarketing() {
160
+ const discoveryLib = require("./discovery-acquisition.lib.cjs");
161
+ discoveryLib.validateDiscoveryAcquisition(ROOT);
162
+ const pm = discoveryLib.loadDiscoveryAcquisition(ROOT);
163
+ const anchors = pm;
164
+ const discovery = pm;
165
+
166
+ validateOpenapiTemplate();
167
+
168
+ const escaped = escapeYamlDoubleQuotedOneLiner(anchors.identityOneLiner);
169
+ const canonicalOrigin = normalize(anchors.productionCanonicalOrigin);
170
+ const openapiSelfCanonical = `${canonicalOrigin}/openapi-commercial-v1.yaml`;
171
+
172
+ const envUrl = process.env.NEXT_PUBLIC_APP_URL;
173
+ const effectivePublicOrigin =
174
+ typeof envUrl === "string" && envUrl.trim() ? envUrl.trim() : anchors.productionCanonicalOrigin;
175
+ const publicOriginNormalized = normalize(effectivePublicOrigin);
176
+ const openapiSelfEffective = `${publicOriginNormalized}/openapi-commercial-v1.yaml`;
177
+
178
+ const integrateUrl = `${canonicalOrigin}/integrate`;
179
+
180
+ const template = readFileSync(OPENAPI_IN, "utf8");
181
+ let mid = template;
182
+ mid = mid.replace("__IDENTITY_ONE_LINER__", escaped);
183
+ mid = mid.replace("__DISTRIBUTION_CONTACT_URL__", canonicalOrigin);
184
+ mid = mid.replace("__DISTRIBUTION_INTEGRATE_URL__", integrateUrl);
185
+ mid = mid.replace("__DISTRIBUTION_REPO_URL__", anchors.gitRepositoryUrl);
186
+ mid = mid.replace("__DISTRIBUTION_NPM_URL__", anchors.npmPackageUrl);
187
+
188
+ const repoYaml = mid
189
+ .replace("__SERVERS_ORIGIN__", canonicalOrigin)
190
+ .replace("__OPENAPI_SELF_URL__", openapiSelfCanonical);
191
+ writeFileSync(OPENAPI_OUT, repoYaml, "utf8");
192
+
193
+ mkdirSync(dirname(OPENAPI_PUBLIC), { recursive: true });
194
+ const publicYaml = mid
195
+ .replace("__SERVERS_ORIGIN__", publicOriginNormalized)
196
+ .replace("__OPENAPI_SELF_URL__", openapiSelfEffective);
197
+ writeFileSync(OPENAPI_PUBLIC, publicYaml, "utf8");
198
+
199
+ const discoveryPayload = require("./discovery-payload.lib.cjs");
200
+ const discoveryPayloadObj = discoveryPayload.buildDiscoveryPayload(ROOT);
201
+ const llmsNormalized = discoveryPayload.renderLlmsTextFromPayload(discoveryPayloadObj);
202
+
203
+ mkdirSync(dirname(LLMS_PUBLIC), { recursive: true });
204
+ writeFileSync(LLMS_PUBLIC, llmsNormalized, "utf8");
205
+ writeFileSync(LLMS_REPO_ROOT, llmsNormalized, "utf8");
206
+
207
+ const pkgRaw = readFileSync(PKG_PATH, "utf8");
208
+ const pkg = JSON.parse(pkgRaw);
209
+ pkg.description = String(discovery.pageMetadata.description);
210
+ pkg.repository = { type: "git", url: anchors.gitRepositoryGitUrl };
211
+ pkg.homepage = `${canonicalOrigin}${String(discovery.slug)}`;
212
+ pkg.bugs = { url: anchors.bugsUrl };
213
+ pkg.keywords = anchors.keywords;
214
+ writeFileSync(PKG_PATH, JSON.stringify(pkg, null, 2) + "\n", "utf8");
215
+
216
+ let readme = readFileSync(README_PATH, "utf8");
217
+ if (!readme.includes(DISCOVERY_README_TITLE_START) || !readme.includes(DISCOVERY_README_TITLE_END)) {
218
+ throw new Error("README.md must contain discovery-readme-title markers");
219
+ }
220
+ const titleBody = `# ${String(discovery.readmeTitle)}`;
221
+ const titleBlock = `${DISCOVERY_README_TITLE_START}\n${titleBody}\n${DISCOVERY_README_TITLE_END}`;
222
+ const titleRe = new RegExp(
223
+ `${DISCOVERY_README_TITLE_START.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[\\s\\S]*?${DISCOVERY_README_TITLE_END.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`,
224
+ );
225
+ if (!titleRe.test(readme)) {
226
+ throw new Error("README: could not match discovery-readme-title region");
227
+ }
228
+ readme = readme.replace(titleRe, titleBlock);
229
+
230
+ if (!readme.includes(DISCOVERY_README_START) || !readme.includes(DISCOVERY_README_END)) {
231
+ throw new Error("README.md must contain discovery-acquisition-fold markers");
232
+ }
233
+ const foldBody = discoveryLib.buildDiscoveryFoldBody(discovery, canonicalOrigin);
234
+ const discBlock = `${DISCOVERY_README_START}\n${foldBody}\n${DISCOVERY_README_END}`;
235
+ const discRe = new RegExp(
236
+ `${DISCOVERY_README_START.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[\\s\\S]*?${DISCOVERY_README_END.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`,
237
+ );
238
+ if (!discRe.test(readme)) {
239
+ throw new Error("README: could not match discovery-acquisition-fold region");
240
+ }
241
+ readme = readme.replace(discRe, discBlock);
242
+
243
+ if (!readme.includes(README_START) || !readme.includes(README_END)) {
244
+ throw new Error("README.md must contain public-product-anchors markers");
245
+ }
246
+ const pl = discoveryPayloadObj.links;
247
+ const inner = [
248
+ anchors.identityOneLiner,
249
+ "",
250
+ `- **Repository:** ${anchors.gitRepositoryUrl}`,
251
+ `- **npm package:** ${anchors.npmPackageUrl}`,
252
+ `- **Canonical site:** ${canonicalOrigin}`,
253
+ `- **Integrate:** ${integrateUrl}`,
254
+ `- **OpenAPI (canonical):** ${openapiSelfCanonical}`,
255
+ `- **llms.txt (agents, site):** ${canonicalOrigin}/llms.txt`,
256
+ `- **llms.txt (repo, raw):** ${pl.llmsRaw}`,
257
+ `- **llms.txt (repo, blob):** ${pl.llmsBlob}`,
258
+ "",
259
+ ].join("\n");
260
+ const block = `${README_START}\n${inner}\n${README_END}`;
261
+ const re = new RegExp(
262
+ `${README_START.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[\\s\\S]*?${README_END.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`,
263
+ );
264
+ if (!re.test(readme)) {
265
+ throw new Error("README: could not match public-product-anchors region");
266
+ }
267
+ readme = readme.replace(re, block);
268
+ writeFileSync(README_PATH, readme, "utf8");
269
+
270
+ writePublicDistributionGenerated(anchors, discovery);
271
+ writeAgentsMd(anchors, discovery);
272
+ }
273
+
274
+ function validateForCheck() {
275
+ const discoveryLib = require("./discovery-acquisition.lib.cjs");
276
+ discoveryLib.validateDiscoveryAcquisition(ROOT);
277
+ validateOpenapiTemplate();
278
+ const pm = JSON.parse(readFileSync(MARKETING_PATH, "utf8"));
279
+ const required = [
280
+ "identityOneLiner",
281
+ "productionCanonicalOrigin",
282
+ "gitRepositoryUrl",
283
+ "gitRepositoryGitUrl",
284
+ "npmPackageUrl",
285
+ "bugsUrl",
286
+ "keywords",
287
+ ];
288
+ for (const k of required) {
289
+ if (pm[k] === undefined || pm[k] === null) {
290
+ throw new Error(`marketing: missing ${k}`);
291
+ }
292
+ }
293
+ if (!Array.isArray(pm.keywords) || pm.keywords.length === 0) {
294
+ throw new Error("marketing: keywords must be a non-empty array");
295
+ }
296
+ }
297
+
298
+ function main() {
299
+ validateForCheck();
300
+ if (process.argv.includes("--check")) {
301
+ return;
302
+ }
303
+ syncPrimaryMarketing();
304
+ }
305
+
306
+ /** @deprecated use syncPrimaryMarketing */
307
+ const syncPublicProductAnchors = syncPrimaryMarketing;
308
+ /** @deprecated use validateForCheck */
309
+ const validateAnchors = validateForCheck;
310
+
311
+ module.exports = {
312
+ validateAnchors,
313
+ syncPublicProductAnchors,
314
+ syncPrimaryMarketing,
315
+ assertNextPublicOriginParity,
316
+ normalize,
317
+ };
318
+
319
+ if (require.main === module) {
320
+ try {
321
+ main();
322
+ } catch (e) {
323
+ console.error(e instanceof Error ? e.message : e);
324
+ process.exit(1);
325
+ }
326
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+
3
+ const { readFileSync } = require("node:fs");
4
+ const { join } = require("node:path");
5
+
6
+ const ROOT = join(__dirname, "..");
7
+ const MARKETING_PATH = join(ROOT, "config", "marketing.json");
8
+
9
+ /**
10
+ * @param {string} s
11
+ */
12
+ function normalize(s) {
13
+ const t = String(s).trim();
14
+ if (!t) throw new Error("normalize: empty origin");
15
+ const u = new URL(t);
16
+ return u.origin;
17
+ }
18
+
19
+ function isLoopbackOrigin(raw) {
20
+ try {
21
+ const u = new URL(normalize(raw));
22
+ const h = u.hostname.toLowerCase();
23
+ return h === "localhost" || h === "127.0.0.1" || h === "::1" || h === "[::1]";
24
+ } catch {
25
+ return false;
26
+ }
27
+ }
28
+
29
+ function readProductionCanonicalOrigin() {
30
+ const pm = JSON.parse(readFileSync(MARKETING_PATH, "utf8"));
31
+ return String(pm.productionCanonicalOrigin);
32
+ }
33
+
34
+ function assertNextPublicOriginParity() {
35
+ const canonicalFromJson = readProductionCanonicalOrigin();
36
+ const skip = process.env.NODE_ENV !== "production" || process.env.VERCEL_ENV === "preview";
37
+ if (skip) return;
38
+ const url = String(process.env.NEXT_PUBLIC_APP_URL || "").trim();
39
+ if (!url) return;
40
+ if (normalize(url) !== normalize(canonicalFromJson)) {
41
+ if (process.env.VERCEL_ENV !== "production" && isLoopbackOrigin(url)) return;
42
+ throw new Error("NEXT_PUBLIC_APP_URL must equal productionCanonicalOrigin");
43
+ }
44
+ }
45
+
46
+ module.exports = {
47
+ normalize,
48
+ assertNextPublicOriginParity,
49
+ MARKETING_PATH,
50
+ /** @deprecated use MARKETING_PATH */
51
+ PRIMARY_MARKETING_PATH: MARKETING_PATH,
52
+ };
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ /** @deprecated Re-export — use `emit-primary-marketing.cjs` and `config/marketing.json`. */
3
+ module.exports = require("./emit-primary-marketing.cjs");