@vostride/agent-qa-ids 0.2.2 → 0.2.4

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 ADDED
@@ -0,0 +1,78 @@
1
+ <picture>
2
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vostride/agent-qa/main/docs/assets/readme/banner-dark.jpg">
3
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/vostride/agent-qa/main/docs/assets/readme/banner-light.png">
4
+ <img src="https://raw.githubusercontent.com/vostride/agent-qa/main/docs/assets/readme/banner-light.png" alt="agent-qa by vostride — a self-improving QA agent for your software factory" width="100%">
5
+ </picture>
6
+
7
+ <p align="center">
8
+ <strong>English</strong> · <a href="https://github.com/vostride/agent-qa/blob/main/README.zh-CN.md">中文</a>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/agent-qa"><img src="https://img.shields.io/npm/v/agent-qa?color=196872" alt="npm version"></a>
13
+ <a href="https://www.npmjs.com/package/agent-qa"><img src="https://img.shields.io/npm/dm/agent-qa?color=196872" alt="npm downloads per month"></a>
14
+ <a href="https://github.com/vostride/agent-qa/stargazers"><img src="https://img.shields.io/github/stars/vostride/agent-qa?color=196872" alt="GitHub stars"></a>
15
+ <a href="https://github.com/vostride/agent-qa/actions/workflows/ci.yml"><img src="https://github.com/vostride/agent-qa/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI"></a>
16
+ <a href="https://vostride.com/docs/agent-qa"><img src="https://img.shields.io/badge/docs-agent--qa-196872" alt="Documentation"></a>
17
+ <a href="https://github.com/vostride/agent-qa/blob/main/LICENSE.md"><img src="https://img.shields.io/badge/license-FSL--1.1--ALv2-196872" alt="License: FSL-1.1-ALv2"></a>
18
+ </p>
19
+
20
+ <p align="center">
21
+ <a href="https://vostride.com/agent-qa">Website</a> · <a href="https://vostride.com/docs/agent-qa">Docs</a> · <a href="https://vostride.com/demo/agent-qa">Demo</a> · <a href="https://vostride.com/blog">Blog</a> · <a href="https://vostride.com/changelog">Changelog</a>
22
+ </p>
23
+
24
+ **Your AI QA engineer, with memory.** Describe a user journey in plain language. agent-qa tests it on web, Android or iOS and keeps the evidence. Use the CLI, the dashboard, or your coding agent through MCP and skills.
25
+
26
+ - **memidex:** remembers facts and working procedures as reviewable files in your repository.
27
+ - **Self-improvement:** validates lessons from runs, retires stale knowledge, and uses your feedback to correct mistakes.
28
+
29
+ | Benchmark | Rank | Published result |
30
+ | --- | --- | --- |
31
+ | [AndroidWorld](https://vostride.com/benchmark/android-world) | **#1** | **100% pass@1** (116/116 tasks) |
32
+ | [AppControlBench](https://vostride.com/benchmark/app-control-bench) | **#1** | **99.6% completion** (114.5/115 points) |
33
+
34
+ Read the full benchmark reports, with run evidence and methodology, on [our blog](https://vostride.com/blog). Both used gpt-6-sol with memory and self-improvement off; AppControlBench gives half credit for partial completion.
35
+
36
+ ## See it in action
37
+
38
+ **Inspect a failure.** The demo catches a cart showing $29 instead of $53, with the failed step and its screenshot side by side.
39
+
40
+ <picture>
41
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vostride/agent-qa/main/docs/assets/readme/evidence-dark.png">
42
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/vostride/agent-qa/main/docs/assets/readme/evidence-light.png">
43
+ <img src="https://raw.githubusercontent.com/vostride/agent-qa/main/docs/assets/readme/evidence-light.png" alt="The dashboard shows the deliberate cart-total bug, its failed assertion, and recorded browser evidence" width="100%">
44
+ </picture>
45
+
46
+ **See what memory contributed.** Inspect the knowledge supplied to a run and trace it back to the steps that used it.
47
+
48
+ <picture>
49
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vostride/agent-qa/main/docs/assets/readme/knowledge-dark.png">
50
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/vostride/agent-qa/main/docs/assets/readme/knowledge-light.png">
51
+ <img src="https://raw.githubusercontent.com/vostride/agent-qa/main/docs/assets/readme/knowledge-light.png" alt="The Knowledge tab shows stored facts retrieved for the demo run" width="100%">
52
+ </picture>
53
+
54
+ **Run from your terminal.** Real output from the demo suite: checkout passes; the deliberate cart-total bug fails.
55
+
56
+ <picture>
57
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vostride/agent-qa/main/docs/assets/readme/cli-dark.png">
58
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/vostride/agent-qa/main/docs/assets/readme/cli-light.png">
59
+ <img src="https://raw.githubusercontent.com/vostride/agent-qa/main/docs/assets/readme/cli-light.png" alt="CLI output excerpt showing one passed test, one failed test, and eight of nine steps passing" width="100%">
60
+ </picture>
61
+
62
+ ## Get started
63
+
64
+ Requires Node.js 24+.
65
+
66
+ ```sh
67
+ npm install -D agent-qa
68
+ npx agent-qa init
69
+ ```
70
+
71
+ Follow the [quickstart](https://vostride.com/docs/agent-qa/quickstart) to connect a model and run the demo, or [set up with your coding agent](https://vostride.com/docs/agent-qa/agent-quickstart).
72
+
73
+ > [!NOTE]
74
+ > Early stage. Expect bugs. [Report an issue](https://github.com/vostride/agent-qa/issues) when something breaks.
75
+
76
+ ## License
77
+
78
+ [Functional Source License (FSL-1.1-ALv2)](https://github.com/vostride/agent-qa/blob/main/LICENSE.md).
package/dist/index.cjs CHANGED
@@ -20,12 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- APPROVED_SAAS_PLACEHOLDERS: () => APPROVED_SAAS_PLACEHOLDERS,
24
- APPROVED_SAAS_PLACEHOLDER_NAMES: () => APPROVED_SAAS_PLACEHOLDER_NAMES,
25
- APPROVED_SAAS_PLACEHOLDER_SLUGS: () => APPROVED_SAAS_PLACEHOLDER_SLUGS,
26
23
  CANONICAL_ID_WORDS: () => CANONICAL_ID_WORDS,
27
24
  ENTITY_ID_TYPES: () => ENTITY_ID_TYPES,
28
- LEGACY_OBSERVATION_ID_WORDS: () => LEGACY_OBSERVATION_ID_WORDS,
29
25
  generateCanonicalId: () => generateCanonicalId,
30
26
  generateHookId: () => generateHookId,
31
27
  generateObservationId: () => generateObservationId,
@@ -40,16 +36,13 @@ __export(index_exports, {
40
36
  isCanonicalRunId: () => isCanonicalRunId,
41
37
  isCanonicalSuiteId: () => isCanonicalSuiteId,
42
38
  isCanonicalTestId: () => isCanonicalTestId,
43
- isObservationId: () => isObservationId,
44
- selectApprovedSaasPlaceholder: () => selectApprovedSaasPlaceholder,
45
- selectApprovedSaasPlaceholderSlug: () => selectApprovedSaasPlaceholderSlug
39
+ isObservationId: () => isObservationId
46
40
  });
47
41
  module.exports = __toCommonJS(index_exports);
48
42
 
49
43
  // src/persistent-id.ts
50
44
  var import_id_agent = require("id-agent");
51
45
  var CANONICAL_ID_WORDS = 10;
52
- var LEGACY_OBSERVATION_ID_WORDS = 6;
53
46
  var PREFIX = {
54
47
  test: "t",
55
48
  suite: "s",
@@ -102,7 +95,7 @@ function isCanonicalId(type, value) {
102
95
  return hasPrefixAndWordCount(value, PREFIX[type], CANONICAL_ID_WORDS);
103
96
  }
104
97
  function isObservationId(value) {
105
- return isCanonicalObservationId(value) || hasPrefixAndWordCount(value, PREFIX.observation, LEGACY_OBSERVATION_ID_WORDS);
98
+ return isCanonicalObservationId(value);
106
99
  }
107
100
  function getEntityIdContract(type) {
108
101
  const prefix = PREFIX[type];
@@ -117,44 +110,10 @@ function getEntityIdContract(type) {
117
110
  function getEntityIdContracts() {
118
111
  return ENTITY_ID_TYPES.map((type) => getEntityIdContract(type));
119
112
  }
120
-
121
- // src/product-placeholders.ts
122
- var APPROVED_SAAS_PLACEHOLDERS = [
123
- { name: "Linear", slug: "linear" },
124
- { name: "Vercel", slug: "vercel" },
125
- { name: "Notion", slug: "notion" },
126
- { name: "Stripe", slug: "stripe" },
127
- { name: "GitHub", slug: "github" },
128
- { name: "Slack", slug: "slack" },
129
- { name: "Figma", slug: "figma" },
130
- { name: "Shopify", slug: "shopify" },
131
- { name: "Datadog", slug: "datadog" },
132
- { name: "Supabase", slug: "supabase" }
133
- ];
134
- var APPROVED_SAAS_PLACEHOLDER_NAMES = APPROVED_SAAS_PLACEHOLDERS.map((item) => item.name);
135
- var APPROVED_SAAS_PLACEHOLDER_SLUGS = APPROVED_SAAS_PLACEHOLDERS.map((item) => item.slug);
136
- function hashSeed(seed) {
137
- const input = String(seed);
138
- let hash = 0;
139
- for (let index = 0; index < input.length; index += 1) {
140
- hash = hash * 31 + input.charCodeAt(index) >>> 0;
141
- }
142
- return hash;
143
- }
144
- function selectApprovedSaasPlaceholder(seed) {
145
- return APPROVED_SAAS_PLACEHOLDERS[hashSeed(seed) % APPROVED_SAAS_PLACEHOLDERS.length];
146
- }
147
- function selectApprovedSaasPlaceholderSlug(seed) {
148
- return selectApprovedSaasPlaceholder(seed).slug;
149
- }
150
113
  // Annotate the CommonJS export names for ESM import in node:
151
114
  0 && (module.exports = {
152
- APPROVED_SAAS_PLACEHOLDERS,
153
- APPROVED_SAAS_PLACEHOLDER_NAMES,
154
- APPROVED_SAAS_PLACEHOLDER_SLUGS,
155
115
  CANONICAL_ID_WORDS,
156
116
  ENTITY_ID_TYPES,
157
- LEGACY_OBSERVATION_ID_WORDS,
158
117
  generateCanonicalId,
159
118
  generateHookId,
160
119
  generateObservationId,
@@ -169,8 +128,6 @@ function selectApprovedSaasPlaceholderSlug(seed) {
169
128
  isCanonicalRunId,
170
129
  isCanonicalSuiteId,
171
130
  isCanonicalTestId,
172
- isObservationId,
173
- selectApprovedSaasPlaceholder,
174
- selectApprovedSaasPlaceholderSlug
131
+ isObservationId
175
132
  });
176
133
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/persistent-id.ts","../src/product-placeholders.ts"],"sourcesContent":["export {\n CANONICAL_ID_WORDS,\n ENTITY_ID_TYPES,\n LEGACY_OBSERVATION_ID_WORDS,\n generateCanonicalId,\n generateHookId,\n generateObservationId,\n generateRunId,\n generateSuiteId,\n generateTestId,\n getEntityIdContract,\n getEntityIdContracts,\n isCanonicalId,\n isCanonicalHookId,\n isCanonicalObservationId,\n isCanonicalRunId,\n isCanonicalSuiteId,\n isCanonicalTestId,\n isObservationId,\n type EntityIdContract,\n type EntityIdType,\n} from './persistent-id.js'\n\nexport {\n type ApprovedSaasPlaceholder,\n APPROVED_SAAS_PLACEHOLDERS,\n APPROVED_SAAS_PLACEHOLDER_NAMES,\n APPROVED_SAAS_PLACEHOLDER_SLUGS,\n selectApprovedSaasPlaceholder,\n selectApprovedSaasPlaceholderSlug,\n} from './product-placeholders.js'\n","import { idAgent, parse } from 'id-agent'\n\nexport const CANONICAL_ID_WORDS = 10\nexport const LEGACY_OBSERVATION_ID_WORDS = 6\n\nconst PREFIX = {\n test: 't',\n suite: 's',\n hook: 'h',\n observation: 'obs',\n run: 'r',\n} as const\n\ntype Prefix = (typeof PREFIX)[keyof typeof PREFIX]\nexport type EntityIdType = keyof typeof PREFIX\n\nexport const ENTITY_ID_TYPES = Object.keys(PREFIX) as EntityIdType[]\n\nexport interface EntityIdContract {\n type: EntityIdType\n prefix: Prefix\n prefixWithSeparator: `${Prefix}_`\n words: number\n examplePattern: string\n}\n\nfunction hasPrefixAndWordCount(value: string, prefix: Prefix, wordCount: number): boolean {\n const parsed = parse(value)\n return parsed?.prefix === prefix && parsed.wordCount === wordCount\n}\n\nfunction generateId(prefix: Prefix): string {\n return idAgent({ prefix, words: CANONICAL_ID_WORDS })\n}\n\nexport function generateTestId(): string {\n return generateId(PREFIX.test)\n}\n\nexport function generateSuiteId(): string {\n return generateId(PREFIX.suite)\n}\n\nexport function generateObservationId(): string {\n return generateId(PREFIX.observation)\n}\n\nexport function generateHookId(): string {\n return generateId(PREFIX.hook)\n}\n\nexport function generateRunId(): string {\n return generateId(PREFIX.run)\n}\n\nexport function generateCanonicalId(type: EntityIdType): string {\n return generateId(PREFIX[type])\n}\n\nexport function isCanonicalTestId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.test, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalSuiteId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.suite, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalHookId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.hook, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalObservationId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.observation, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalRunId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.run, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalId(type: EntityIdType, value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX[type], CANONICAL_ID_WORDS)\n}\n\nexport function isObservationId(value: string): boolean {\n return isCanonicalObservationId(value)\n || hasPrefixAndWordCount(value, PREFIX.observation, LEGACY_OBSERVATION_ID_WORDS)\n}\n\nexport function getEntityIdContract(type: EntityIdType): EntityIdContract {\n const prefix = PREFIX[type]\n return {\n type,\n prefix,\n prefixWithSeparator: `${prefix}_`,\n words: CANONICAL_ID_WORDS,\n examplePattern: `${prefix}_word-word-word-word-word-word-word-word-word-word`,\n }\n}\n\nexport function getEntityIdContracts(): EntityIdContract[] {\n return ENTITY_ID_TYPES.map(type => getEntityIdContract(type))\n}\n","export interface ApprovedSaasPlaceholder {\n readonly name: string\n readonly slug: string\n}\n\nexport const APPROVED_SAAS_PLACEHOLDERS = [\n { name: 'Linear', slug: 'linear' },\n { name: 'Vercel', slug: 'vercel' },\n { name: 'Notion', slug: 'notion' },\n { name: 'Stripe', slug: 'stripe' },\n { name: 'GitHub', slug: 'github' },\n { name: 'Slack', slug: 'slack' },\n { name: 'Figma', slug: 'figma' },\n { name: 'Shopify', slug: 'shopify' },\n { name: 'Datadog', slug: 'datadog' },\n { name: 'Supabase', slug: 'supabase' },\n] as const satisfies readonly ApprovedSaasPlaceholder[]\n\nexport const APPROVED_SAAS_PLACEHOLDER_NAMES = APPROVED_SAAS_PLACEHOLDERS.map((item) => item.name)\nexport const APPROVED_SAAS_PLACEHOLDER_SLUGS = APPROVED_SAAS_PLACEHOLDERS.map((item) => item.slug)\n\nfunction hashSeed(seed: string | number): number {\n const input = String(seed)\n let hash = 0\n\n for (let index = 0; index < input.length; index += 1) {\n hash = (hash * 31 + input.charCodeAt(index)) >>> 0\n }\n\n return hash\n}\n\nexport function selectApprovedSaasPlaceholder(seed: string | number): ApprovedSaasPlaceholder {\n return APPROVED_SAAS_PLACEHOLDERS[hashSeed(seed) % APPROVED_SAAS_PLACEHOLDERS.length]\n}\n\nexport function selectApprovedSaasPlaceholderSlug(seed: string | number): string {\n return selectApprovedSaasPlaceholder(seed).slug\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/persistent-id.ts"],"sourcesContent":["export {\n CANONICAL_ID_WORDS,\n ENTITY_ID_TYPES,\n generateCanonicalId,\n generateHookId,\n generateObservationId,\n generateRunId,\n generateSuiteId,\n generateTestId,\n getEntityIdContract,\n getEntityIdContracts,\n isCanonicalId,\n isCanonicalHookId,\n isCanonicalObservationId,\n isCanonicalRunId,\n isCanonicalSuiteId,\n isCanonicalTestId,\n isObservationId,\n type EntityIdContract,\n type EntityIdType,\n} from './persistent-id.js'\n","import { idAgent, parse } from 'id-agent'\n\nexport const CANONICAL_ID_WORDS = 10\n\nconst PREFIX = {\n test: 't',\n suite: 's',\n hook: 'h',\n observation: 'obs',\n run: 'r',\n} as const\n\ntype Prefix = (typeof PREFIX)[keyof typeof PREFIX]\nexport type EntityIdType = keyof typeof PREFIX\n\nexport const ENTITY_ID_TYPES = Object.keys(PREFIX) as EntityIdType[]\n\nexport interface EntityIdContract {\n type: EntityIdType\n prefix: Prefix\n prefixWithSeparator: `${Prefix}_`\n words: number\n examplePattern: string\n}\n\nfunction hasPrefixAndWordCount(value: string, prefix: Prefix, wordCount: number): boolean {\n const parsed = parse(value)\n return parsed?.prefix === prefix && parsed.wordCount === wordCount\n}\n\nfunction generateId(prefix: Prefix): string {\n return idAgent({ prefix, words: CANONICAL_ID_WORDS })\n}\n\nexport function generateTestId(): string {\n return generateId(PREFIX.test)\n}\n\nexport function generateSuiteId(): string {\n return generateId(PREFIX.suite)\n}\n\nexport function generateObservationId(): string {\n return generateId(PREFIX.observation)\n}\n\nexport function generateHookId(): string {\n return generateId(PREFIX.hook)\n}\n\nexport function generateRunId(): string {\n return generateId(PREFIX.run)\n}\n\nexport function generateCanonicalId(type: EntityIdType): string {\n return generateId(PREFIX[type])\n}\n\nexport function isCanonicalTestId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.test, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalSuiteId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.suite, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalHookId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.hook, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalObservationId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.observation, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalRunId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.run, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalId(type: EntityIdType, value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX[type], CANONICAL_ID_WORDS)\n}\n\nexport function isObservationId(value: string): boolean {\n return isCanonicalObservationId(value)\n}\n\nexport function getEntityIdContract(type: EntityIdType): EntityIdContract {\n const prefix = PREFIX[type]\n return {\n type,\n prefix,\n prefixWithSeparator: `${prefix}_`,\n words: CANONICAL_ID_WORDS,\n examplePattern: `${prefix}_word-word-word-word-word-word-word-word-word-word`,\n }\n}\n\nexport function getEntityIdContracts(): EntityIdContract[] {\n return ENTITY_ID_TYPES.map(type => getEntityIdContract(type))\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,sBAA+B;AAExB,IAAM,qBAAqB;AAElC,IAAM,SAAS;AAAA,EACb,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,aAAa;AAAA,EACb,KAAK;AACP;AAKO,IAAM,kBAAkB,OAAO,KAAK,MAAM;AAUjD,SAAS,sBAAsB,OAAe,QAAgB,WAA4B;AACxF,QAAM,aAAS,uBAAM,KAAK;AAC1B,SAAO,QAAQ,WAAW,UAAU,OAAO,cAAc;AAC3D;AAEA,SAAS,WAAW,QAAwB;AAC1C,aAAO,yBAAQ,EAAE,QAAQ,OAAO,mBAAmB,CAAC;AACtD;AAEO,SAAS,iBAAyB;AACvC,SAAO,WAAW,OAAO,IAAI;AAC/B;AAEO,SAAS,kBAA0B;AACxC,SAAO,WAAW,OAAO,KAAK;AAChC;AAEO,SAAS,wBAAgC;AAC9C,SAAO,WAAW,OAAO,WAAW;AACtC;AAEO,SAAS,iBAAyB;AACvC,SAAO,WAAW,OAAO,IAAI;AAC/B;AAEO,SAAS,gBAAwB;AACtC,SAAO,WAAW,OAAO,GAAG;AAC9B;AAEO,SAAS,oBAAoB,MAA4B;AAC9D,SAAO,WAAW,OAAO,IAAI,CAAC;AAChC;AAEO,SAAS,kBAAkB,OAAwB;AACxD,SAAO,sBAAsB,OAAO,OAAO,MAAM,kBAAkB;AACrE;AAEO,SAAS,mBAAmB,OAAwB;AACzD,SAAO,sBAAsB,OAAO,OAAO,OAAO,kBAAkB;AACtE;AAEO,SAAS,kBAAkB,OAAwB;AACxD,SAAO,sBAAsB,OAAO,OAAO,MAAM,kBAAkB;AACrE;AAEO,SAAS,yBAAyB,OAAwB;AAC/D,SAAO,sBAAsB,OAAO,OAAO,aAAa,kBAAkB;AAC5E;AAEO,SAAS,iBAAiB,OAAwB;AACvD,SAAO,sBAAsB,OAAO,OAAO,KAAK,kBAAkB;AACpE;AAEO,SAAS,cAAc,MAAoB,OAAwB;AACxE,SAAO,sBAAsB,OAAO,OAAO,IAAI,GAAG,kBAAkB;AACtE;AAEO,SAAS,gBAAgB,OAAwB;AACtD,SAAO,yBAAyB,KAAK;AACvC;AAEO,SAAS,oBAAoB,MAAsC;AACxE,QAAM,SAAS,OAAO,IAAI;AAC1B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,qBAAqB,GAAG,MAAM;AAAA,IAC9B,OAAO;AAAA,IACP,gBAAgB,GAAG,MAAM;AAAA,EAC3B;AACF;AAEO,SAAS,uBAA2C;AACzD,SAAO,gBAAgB,IAAI,UAAQ,oBAAoB,IAAI,CAAC;AAC9D;","names":[]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,4 @@
1
1
  declare const CANONICAL_ID_WORDS = 10;
2
- declare const LEGACY_OBSERVATION_ID_WORDS = 6;
3
2
  declare const PREFIX: {
4
3
  readonly test: "t";
5
4
  readonly suite: "s";
@@ -33,44 +32,4 @@ declare function isObservationId(value: string): boolean;
33
32
  declare function getEntityIdContract(type: EntityIdType): EntityIdContract;
34
33
  declare function getEntityIdContracts(): EntityIdContract[];
35
34
 
36
- interface ApprovedSaasPlaceholder {
37
- readonly name: string;
38
- readonly slug: string;
39
- }
40
- declare const APPROVED_SAAS_PLACEHOLDERS: readonly [{
41
- readonly name: "Linear";
42
- readonly slug: "linear";
43
- }, {
44
- readonly name: "Vercel";
45
- readonly slug: "vercel";
46
- }, {
47
- readonly name: "Notion";
48
- readonly slug: "notion";
49
- }, {
50
- readonly name: "Stripe";
51
- readonly slug: "stripe";
52
- }, {
53
- readonly name: "GitHub";
54
- readonly slug: "github";
55
- }, {
56
- readonly name: "Slack";
57
- readonly slug: "slack";
58
- }, {
59
- readonly name: "Figma";
60
- readonly slug: "figma";
61
- }, {
62
- readonly name: "Shopify";
63
- readonly slug: "shopify";
64
- }, {
65
- readonly name: "Datadog";
66
- readonly slug: "datadog";
67
- }, {
68
- readonly name: "Supabase";
69
- readonly slug: "supabase";
70
- }];
71
- declare const APPROVED_SAAS_PLACEHOLDER_NAMES: ("Linear" | "Vercel" | "Notion" | "Stripe" | "GitHub" | "Slack" | "Figma" | "Shopify" | "Datadog" | "Supabase")[];
72
- declare const APPROVED_SAAS_PLACEHOLDER_SLUGS: ("linear" | "vercel" | "notion" | "stripe" | "github" | "slack" | "figma" | "shopify" | "datadog" | "supabase")[];
73
- declare function selectApprovedSaasPlaceholder(seed: string | number): ApprovedSaasPlaceholder;
74
- declare function selectApprovedSaasPlaceholderSlug(seed: string | number): string;
75
-
76
- export { APPROVED_SAAS_PLACEHOLDERS, APPROVED_SAAS_PLACEHOLDER_NAMES, APPROVED_SAAS_PLACEHOLDER_SLUGS, type ApprovedSaasPlaceholder, CANONICAL_ID_WORDS, ENTITY_ID_TYPES, type EntityIdContract, type EntityIdType, LEGACY_OBSERVATION_ID_WORDS, generateCanonicalId, generateHookId, generateObservationId, generateRunId, generateSuiteId, generateTestId, getEntityIdContract, getEntityIdContracts, isCanonicalHookId, isCanonicalId, isCanonicalObservationId, isCanonicalRunId, isCanonicalSuiteId, isCanonicalTestId, isObservationId, selectApprovedSaasPlaceholder, selectApprovedSaasPlaceholderSlug };
35
+ export { CANONICAL_ID_WORDS, ENTITY_ID_TYPES, type EntityIdContract, type EntityIdType, generateCanonicalId, generateHookId, generateObservationId, generateRunId, generateSuiteId, generateTestId, getEntityIdContract, getEntityIdContracts, isCanonicalHookId, isCanonicalId, isCanonicalObservationId, isCanonicalRunId, isCanonicalSuiteId, isCanonicalTestId, isObservationId };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  declare const CANONICAL_ID_WORDS = 10;
2
- declare const LEGACY_OBSERVATION_ID_WORDS = 6;
3
2
  declare const PREFIX: {
4
3
  readonly test: "t";
5
4
  readonly suite: "s";
@@ -33,44 +32,4 @@ declare function isObservationId(value: string): boolean;
33
32
  declare function getEntityIdContract(type: EntityIdType): EntityIdContract;
34
33
  declare function getEntityIdContracts(): EntityIdContract[];
35
34
 
36
- interface ApprovedSaasPlaceholder {
37
- readonly name: string;
38
- readonly slug: string;
39
- }
40
- declare const APPROVED_SAAS_PLACEHOLDERS: readonly [{
41
- readonly name: "Linear";
42
- readonly slug: "linear";
43
- }, {
44
- readonly name: "Vercel";
45
- readonly slug: "vercel";
46
- }, {
47
- readonly name: "Notion";
48
- readonly slug: "notion";
49
- }, {
50
- readonly name: "Stripe";
51
- readonly slug: "stripe";
52
- }, {
53
- readonly name: "GitHub";
54
- readonly slug: "github";
55
- }, {
56
- readonly name: "Slack";
57
- readonly slug: "slack";
58
- }, {
59
- readonly name: "Figma";
60
- readonly slug: "figma";
61
- }, {
62
- readonly name: "Shopify";
63
- readonly slug: "shopify";
64
- }, {
65
- readonly name: "Datadog";
66
- readonly slug: "datadog";
67
- }, {
68
- readonly name: "Supabase";
69
- readonly slug: "supabase";
70
- }];
71
- declare const APPROVED_SAAS_PLACEHOLDER_NAMES: ("Linear" | "Vercel" | "Notion" | "Stripe" | "GitHub" | "Slack" | "Figma" | "Shopify" | "Datadog" | "Supabase")[];
72
- declare const APPROVED_SAAS_PLACEHOLDER_SLUGS: ("linear" | "vercel" | "notion" | "stripe" | "github" | "slack" | "figma" | "shopify" | "datadog" | "supabase")[];
73
- declare function selectApprovedSaasPlaceholder(seed: string | number): ApprovedSaasPlaceholder;
74
- declare function selectApprovedSaasPlaceholderSlug(seed: string | number): string;
75
-
76
- export { APPROVED_SAAS_PLACEHOLDERS, APPROVED_SAAS_PLACEHOLDER_NAMES, APPROVED_SAAS_PLACEHOLDER_SLUGS, type ApprovedSaasPlaceholder, CANONICAL_ID_WORDS, ENTITY_ID_TYPES, type EntityIdContract, type EntityIdType, LEGACY_OBSERVATION_ID_WORDS, generateCanonicalId, generateHookId, generateObservationId, generateRunId, generateSuiteId, generateTestId, getEntityIdContract, getEntityIdContracts, isCanonicalHookId, isCanonicalId, isCanonicalObservationId, isCanonicalRunId, isCanonicalSuiteId, isCanonicalTestId, isObservationId, selectApprovedSaasPlaceholder, selectApprovedSaasPlaceholderSlug };
35
+ export { CANONICAL_ID_WORDS, ENTITY_ID_TYPES, type EntityIdContract, type EntityIdType, generateCanonicalId, generateHookId, generateObservationId, generateRunId, generateSuiteId, generateTestId, getEntityIdContract, getEntityIdContracts, isCanonicalHookId, isCanonicalId, isCanonicalObservationId, isCanonicalRunId, isCanonicalSuiteId, isCanonicalTestId, isObservationId };
package/dist/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  // src/persistent-id.ts
2
2
  import { idAgent, parse } from "id-agent";
3
3
  var CANONICAL_ID_WORDS = 10;
4
- var LEGACY_OBSERVATION_ID_WORDS = 6;
5
4
  var PREFIX = {
6
5
  test: "t",
7
6
  suite: "s",
@@ -54,7 +53,7 @@ function isCanonicalId(type, value) {
54
53
  return hasPrefixAndWordCount(value, PREFIX[type], CANONICAL_ID_WORDS);
55
54
  }
56
55
  function isObservationId(value) {
57
- return isCanonicalObservationId(value) || hasPrefixAndWordCount(value, PREFIX.observation, LEGACY_OBSERVATION_ID_WORDS);
56
+ return isCanonicalObservationId(value);
58
57
  }
59
58
  function getEntityIdContract(type) {
60
59
  const prefix = PREFIX[type];
@@ -69,43 +68,9 @@ function getEntityIdContract(type) {
69
68
  function getEntityIdContracts() {
70
69
  return ENTITY_ID_TYPES.map((type) => getEntityIdContract(type));
71
70
  }
72
-
73
- // src/product-placeholders.ts
74
- var APPROVED_SAAS_PLACEHOLDERS = [
75
- { name: "Linear", slug: "linear" },
76
- { name: "Vercel", slug: "vercel" },
77
- { name: "Notion", slug: "notion" },
78
- { name: "Stripe", slug: "stripe" },
79
- { name: "GitHub", slug: "github" },
80
- { name: "Slack", slug: "slack" },
81
- { name: "Figma", slug: "figma" },
82
- { name: "Shopify", slug: "shopify" },
83
- { name: "Datadog", slug: "datadog" },
84
- { name: "Supabase", slug: "supabase" }
85
- ];
86
- var APPROVED_SAAS_PLACEHOLDER_NAMES = APPROVED_SAAS_PLACEHOLDERS.map((item) => item.name);
87
- var APPROVED_SAAS_PLACEHOLDER_SLUGS = APPROVED_SAAS_PLACEHOLDERS.map((item) => item.slug);
88
- function hashSeed(seed) {
89
- const input = String(seed);
90
- let hash = 0;
91
- for (let index = 0; index < input.length; index += 1) {
92
- hash = hash * 31 + input.charCodeAt(index) >>> 0;
93
- }
94
- return hash;
95
- }
96
- function selectApprovedSaasPlaceholder(seed) {
97
- return APPROVED_SAAS_PLACEHOLDERS[hashSeed(seed) % APPROVED_SAAS_PLACEHOLDERS.length];
98
- }
99
- function selectApprovedSaasPlaceholderSlug(seed) {
100
- return selectApprovedSaasPlaceholder(seed).slug;
101
- }
102
71
  export {
103
- APPROVED_SAAS_PLACEHOLDERS,
104
- APPROVED_SAAS_PLACEHOLDER_NAMES,
105
- APPROVED_SAAS_PLACEHOLDER_SLUGS,
106
72
  CANONICAL_ID_WORDS,
107
73
  ENTITY_ID_TYPES,
108
- LEGACY_OBSERVATION_ID_WORDS,
109
74
  generateCanonicalId,
110
75
  generateHookId,
111
76
  generateObservationId,
@@ -120,8 +85,6 @@ export {
120
85
  isCanonicalRunId,
121
86
  isCanonicalSuiteId,
122
87
  isCanonicalTestId,
123
- isObservationId,
124
- selectApprovedSaasPlaceholder,
125
- selectApprovedSaasPlaceholderSlug
88
+ isObservationId
126
89
  };
127
90
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/persistent-id.ts","../src/product-placeholders.ts"],"sourcesContent":["import { idAgent, parse } from 'id-agent'\n\nexport const CANONICAL_ID_WORDS = 10\nexport const LEGACY_OBSERVATION_ID_WORDS = 6\n\nconst PREFIX = {\n test: 't',\n suite: 's',\n hook: 'h',\n observation: 'obs',\n run: 'r',\n} as const\n\ntype Prefix = (typeof PREFIX)[keyof typeof PREFIX]\nexport type EntityIdType = keyof typeof PREFIX\n\nexport const ENTITY_ID_TYPES = Object.keys(PREFIX) as EntityIdType[]\n\nexport interface EntityIdContract {\n type: EntityIdType\n prefix: Prefix\n prefixWithSeparator: `${Prefix}_`\n words: number\n examplePattern: string\n}\n\nfunction hasPrefixAndWordCount(value: string, prefix: Prefix, wordCount: number): boolean {\n const parsed = parse(value)\n return parsed?.prefix === prefix && parsed.wordCount === wordCount\n}\n\nfunction generateId(prefix: Prefix): string {\n return idAgent({ prefix, words: CANONICAL_ID_WORDS })\n}\n\nexport function generateTestId(): string {\n return generateId(PREFIX.test)\n}\n\nexport function generateSuiteId(): string {\n return generateId(PREFIX.suite)\n}\n\nexport function generateObservationId(): string {\n return generateId(PREFIX.observation)\n}\n\nexport function generateHookId(): string {\n return generateId(PREFIX.hook)\n}\n\nexport function generateRunId(): string {\n return generateId(PREFIX.run)\n}\n\nexport function generateCanonicalId(type: EntityIdType): string {\n return generateId(PREFIX[type])\n}\n\nexport function isCanonicalTestId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.test, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalSuiteId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.suite, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalHookId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.hook, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalObservationId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.observation, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalRunId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.run, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalId(type: EntityIdType, value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX[type], CANONICAL_ID_WORDS)\n}\n\nexport function isObservationId(value: string): boolean {\n return isCanonicalObservationId(value)\n || hasPrefixAndWordCount(value, PREFIX.observation, LEGACY_OBSERVATION_ID_WORDS)\n}\n\nexport function getEntityIdContract(type: EntityIdType): EntityIdContract {\n const prefix = PREFIX[type]\n return {\n type,\n prefix,\n prefixWithSeparator: `${prefix}_`,\n words: CANONICAL_ID_WORDS,\n examplePattern: `${prefix}_word-word-word-word-word-word-word-word-word-word`,\n }\n}\n\nexport function getEntityIdContracts(): EntityIdContract[] {\n return ENTITY_ID_TYPES.map(type => getEntityIdContract(type))\n}\n","export interface ApprovedSaasPlaceholder {\n readonly name: string\n readonly slug: string\n}\n\nexport const APPROVED_SAAS_PLACEHOLDERS = [\n { name: 'Linear', slug: 'linear' },\n { name: 'Vercel', slug: 'vercel' },\n { name: 'Notion', slug: 'notion' },\n { name: 'Stripe', slug: 'stripe' },\n { name: 'GitHub', slug: 'github' },\n { name: 'Slack', slug: 'slack' },\n { name: 'Figma', slug: 'figma' },\n { name: 'Shopify', slug: 'shopify' },\n { name: 'Datadog', slug: 'datadog' },\n { name: 'Supabase', slug: 'supabase' },\n] as const satisfies readonly ApprovedSaasPlaceholder[]\n\nexport const APPROVED_SAAS_PLACEHOLDER_NAMES = APPROVED_SAAS_PLACEHOLDERS.map((item) => item.name)\nexport const APPROVED_SAAS_PLACEHOLDER_SLUGS = APPROVED_SAAS_PLACEHOLDERS.map((item) => item.slug)\n\nfunction hashSeed(seed: string | number): number {\n const input = String(seed)\n let hash = 0\n\n for (let index = 0; index < input.length; index += 1) {\n hash = (hash * 31 + input.charCodeAt(index)) >>> 0\n }\n\n return hash\n}\n\nexport function selectApprovedSaasPlaceholder(seed: string | number): ApprovedSaasPlaceholder {\n return APPROVED_SAAS_PLACEHOLDERS[hashSeed(seed) % APPROVED_SAAS_PLACEHOLDERS.length]\n}\n\nexport function selectApprovedSaasPlaceholderSlug(seed: string | number): string {\n return selectApprovedSaasPlaceholder(seed).slug\n}\n"],"mappings":";AAAA,SAAS,SAAS,aAAa;AAExB,IAAM,qBAAqB;AAC3B,IAAM,8BAA8B;AAE3C,IAAM,SAAS;AAAA,EACb,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,aAAa;AAAA,EACb,KAAK;AACP;AAKO,IAAM,kBAAkB,OAAO,KAAK,MAAM;AAUjD,SAAS,sBAAsB,OAAe,QAAgB,WAA4B;AACxF,QAAM,SAAS,MAAM,KAAK;AAC1B,SAAO,QAAQ,WAAW,UAAU,OAAO,cAAc;AAC3D;AAEA,SAAS,WAAW,QAAwB;AAC1C,SAAO,QAAQ,EAAE,QAAQ,OAAO,mBAAmB,CAAC;AACtD;AAEO,SAAS,iBAAyB;AACvC,SAAO,WAAW,OAAO,IAAI;AAC/B;AAEO,SAAS,kBAA0B;AACxC,SAAO,WAAW,OAAO,KAAK;AAChC;AAEO,SAAS,wBAAgC;AAC9C,SAAO,WAAW,OAAO,WAAW;AACtC;AAEO,SAAS,iBAAyB;AACvC,SAAO,WAAW,OAAO,IAAI;AAC/B;AAEO,SAAS,gBAAwB;AACtC,SAAO,WAAW,OAAO,GAAG;AAC9B;AAEO,SAAS,oBAAoB,MAA4B;AAC9D,SAAO,WAAW,OAAO,IAAI,CAAC;AAChC;AAEO,SAAS,kBAAkB,OAAwB;AACxD,SAAO,sBAAsB,OAAO,OAAO,MAAM,kBAAkB;AACrE;AAEO,SAAS,mBAAmB,OAAwB;AACzD,SAAO,sBAAsB,OAAO,OAAO,OAAO,kBAAkB;AACtE;AAEO,SAAS,kBAAkB,OAAwB;AACxD,SAAO,sBAAsB,OAAO,OAAO,MAAM,kBAAkB;AACrE;AAEO,SAAS,yBAAyB,OAAwB;AAC/D,SAAO,sBAAsB,OAAO,OAAO,aAAa,kBAAkB;AAC5E;AAEO,SAAS,iBAAiB,OAAwB;AACvD,SAAO,sBAAsB,OAAO,OAAO,KAAK,kBAAkB;AACpE;AAEO,SAAS,cAAc,MAAoB,OAAwB;AACxE,SAAO,sBAAsB,OAAO,OAAO,IAAI,GAAG,kBAAkB;AACtE;AAEO,SAAS,gBAAgB,OAAwB;AACtD,SAAO,yBAAyB,KAAK,KAChC,sBAAsB,OAAO,OAAO,aAAa,2BAA2B;AACnF;AAEO,SAAS,oBAAoB,MAAsC;AACxE,QAAM,SAAS,OAAO,IAAI;AAC1B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,qBAAqB,GAAG,MAAM;AAAA,IAC9B,OAAO;AAAA,IACP,gBAAgB,GAAG,MAAM;AAAA,EAC3B;AACF;AAEO,SAAS,uBAA2C;AACzD,SAAO,gBAAgB,IAAI,UAAQ,oBAAoB,IAAI,CAAC;AAC9D;;;AChGO,IAAM,6BAA6B;AAAA,EACxC,EAAE,MAAM,UAAU,MAAM,SAAS;AAAA,EACjC,EAAE,MAAM,UAAU,MAAM,SAAS;AAAA,EACjC,EAAE,MAAM,UAAU,MAAM,SAAS;AAAA,EACjC,EAAE,MAAM,UAAU,MAAM,SAAS;AAAA,EACjC,EAAE,MAAM,UAAU,MAAM,SAAS;AAAA,EACjC,EAAE,MAAM,SAAS,MAAM,QAAQ;AAAA,EAC/B,EAAE,MAAM,SAAS,MAAM,QAAQ;AAAA,EAC/B,EAAE,MAAM,WAAW,MAAM,UAAU;AAAA,EACnC,EAAE,MAAM,WAAW,MAAM,UAAU;AAAA,EACnC,EAAE,MAAM,YAAY,MAAM,WAAW;AACvC;AAEO,IAAM,kCAAkC,2BAA2B,IAAI,CAAC,SAAS,KAAK,IAAI;AAC1F,IAAM,kCAAkC,2BAA2B,IAAI,CAAC,SAAS,KAAK,IAAI;AAEjG,SAAS,SAAS,MAA+B;AAC/C,QAAM,QAAQ,OAAO,IAAI;AACzB,MAAI,OAAO;AAEX,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,WAAQ,OAAO,KAAK,MAAM,WAAW,KAAK,MAAO;AAAA,EACnD;AAEA,SAAO;AACT;AAEO,SAAS,8BAA8B,MAAgD;AAC5F,SAAO,2BAA2B,SAAS,IAAI,IAAI,2BAA2B,MAAM;AACtF;AAEO,SAAS,kCAAkC,MAA+B;AAC/E,SAAO,8BAA8B,IAAI,EAAE;AAC7C;","names":[]}
1
+ {"version":3,"sources":["../src/persistent-id.ts"],"sourcesContent":["import { idAgent, parse } from 'id-agent'\n\nexport const CANONICAL_ID_WORDS = 10\n\nconst PREFIX = {\n test: 't',\n suite: 's',\n hook: 'h',\n observation: 'obs',\n run: 'r',\n} as const\n\ntype Prefix = (typeof PREFIX)[keyof typeof PREFIX]\nexport type EntityIdType = keyof typeof PREFIX\n\nexport const ENTITY_ID_TYPES = Object.keys(PREFIX) as EntityIdType[]\n\nexport interface EntityIdContract {\n type: EntityIdType\n prefix: Prefix\n prefixWithSeparator: `${Prefix}_`\n words: number\n examplePattern: string\n}\n\nfunction hasPrefixAndWordCount(value: string, prefix: Prefix, wordCount: number): boolean {\n const parsed = parse(value)\n return parsed?.prefix === prefix && parsed.wordCount === wordCount\n}\n\nfunction generateId(prefix: Prefix): string {\n return idAgent({ prefix, words: CANONICAL_ID_WORDS })\n}\n\nexport function generateTestId(): string {\n return generateId(PREFIX.test)\n}\n\nexport function generateSuiteId(): string {\n return generateId(PREFIX.suite)\n}\n\nexport function generateObservationId(): string {\n return generateId(PREFIX.observation)\n}\n\nexport function generateHookId(): string {\n return generateId(PREFIX.hook)\n}\n\nexport function generateRunId(): string {\n return generateId(PREFIX.run)\n}\n\nexport function generateCanonicalId(type: EntityIdType): string {\n return generateId(PREFIX[type])\n}\n\nexport function isCanonicalTestId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.test, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalSuiteId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.suite, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalHookId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.hook, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalObservationId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.observation, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalRunId(value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX.run, CANONICAL_ID_WORDS)\n}\n\nexport function isCanonicalId(type: EntityIdType, value: string): boolean {\n return hasPrefixAndWordCount(value, PREFIX[type], CANONICAL_ID_WORDS)\n}\n\nexport function isObservationId(value: string): boolean {\n return isCanonicalObservationId(value)\n}\n\nexport function getEntityIdContract(type: EntityIdType): EntityIdContract {\n const prefix = PREFIX[type]\n return {\n type,\n prefix,\n prefixWithSeparator: `${prefix}_`,\n words: CANONICAL_ID_WORDS,\n examplePattern: `${prefix}_word-word-word-word-word-word-word-word-word-word`,\n }\n}\n\nexport function getEntityIdContracts(): EntityIdContract[] {\n return ENTITY_ID_TYPES.map(type => getEntityIdContract(type))\n}\n"],"mappings":";AAAA,SAAS,SAAS,aAAa;AAExB,IAAM,qBAAqB;AAElC,IAAM,SAAS;AAAA,EACb,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,aAAa;AAAA,EACb,KAAK;AACP;AAKO,IAAM,kBAAkB,OAAO,KAAK,MAAM;AAUjD,SAAS,sBAAsB,OAAe,QAAgB,WAA4B;AACxF,QAAM,SAAS,MAAM,KAAK;AAC1B,SAAO,QAAQ,WAAW,UAAU,OAAO,cAAc;AAC3D;AAEA,SAAS,WAAW,QAAwB;AAC1C,SAAO,QAAQ,EAAE,QAAQ,OAAO,mBAAmB,CAAC;AACtD;AAEO,SAAS,iBAAyB;AACvC,SAAO,WAAW,OAAO,IAAI;AAC/B;AAEO,SAAS,kBAA0B;AACxC,SAAO,WAAW,OAAO,KAAK;AAChC;AAEO,SAAS,wBAAgC;AAC9C,SAAO,WAAW,OAAO,WAAW;AACtC;AAEO,SAAS,iBAAyB;AACvC,SAAO,WAAW,OAAO,IAAI;AAC/B;AAEO,SAAS,gBAAwB;AACtC,SAAO,WAAW,OAAO,GAAG;AAC9B;AAEO,SAAS,oBAAoB,MAA4B;AAC9D,SAAO,WAAW,OAAO,IAAI,CAAC;AAChC;AAEO,SAAS,kBAAkB,OAAwB;AACxD,SAAO,sBAAsB,OAAO,OAAO,MAAM,kBAAkB;AACrE;AAEO,SAAS,mBAAmB,OAAwB;AACzD,SAAO,sBAAsB,OAAO,OAAO,OAAO,kBAAkB;AACtE;AAEO,SAAS,kBAAkB,OAAwB;AACxD,SAAO,sBAAsB,OAAO,OAAO,MAAM,kBAAkB;AACrE;AAEO,SAAS,yBAAyB,OAAwB;AAC/D,SAAO,sBAAsB,OAAO,OAAO,aAAa,kBAAkB;AAC5E;AAEO,SAAS,iBAAiB,OAAwB;AACvD,SAAO,sBAAsB,OAAO,OAAO,KAAK,kBAAkB;AACpE;AAEO,SAAS,cAAc,MAAoB,OAAwB;AACxE,SAAO,sBAAsB,OAAO,OAAO,IAAI,GAAG,kBAAkB;AACtE;AAEO,SAAS,gBAAgB,OAAwB;AACtD,SAAO,yBAAyB,KAAK;AACvC;AAEO,SAAS,oBAAoB,MAAsC;AACxE,QAAM,SAAS,OAAO,IAAI;AAC1B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,qBAAqB,GAAG,MAAM;AAAA,IAC9B,OAAO;AAAA,IACP,gBAAgB,GAAG,MAAM;AAAA,EAC3B;AACF;AAEO,SAAS,uBAA2C;AACzD,SAAO,gBAAgB,IAAI,UAAQ,oBAAoB,IAAI,CAAC;AAC9D;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vostride/agent-qa-ids",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "private": false,
5
5
  "description": "Canonical ID helpers for agent-qa tests, suites, hooks, and artifacts.",
6
6
  "keywords": [
@@ -51,7 +51,7 @@
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/node": "~24.12.2",
54
- "@vostride/agent-qa-arch": "0.2.2",
54
+ "@vostride/agent-qa-arch": "0.2.4",
55
55
  "tsup": "~8.5.1",
56
56
  "typescript": "~6.0.3",
57
57
  "vitest": "~4.1.5"