uidex 0.9.0 → 0.11.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 (45) hide show
  1. package/dist/cli/cli.cjs +4117 -2902
  2. package/dist/cli/cli.cjs.map +1 -1
  3. package/dist/headless/index.cjs +3 -0
  4. package/dist/headless/index.cjs.map +1 -1
  5. package/dist/headless/index.d.cts +55 -16
  6. package/dist/headless/index.d.ts +55 -16
  7. package/dist/headless/index.js +3 -0
  8. package/dist/headless/index.js.map +1 -1
  9. package/dist/index.cjs +7 -1
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +55 -16
  12. package/dist/index.d.ts +55 -16
  13. package/dist/index.js +7 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/playwright/index.cjs +40 -7
  16. package/dist/playwright/index.cjs.map +1 -1
  17. package/dist/playwright/index.d.cts +15 -1
  18. package/dist/playwright/index.d.ts +15 -1
  19. package/dist/playwright/index.js +39 -7
  20. package/dist/playwright/index.js.map +1 -1
  21. package/dist/playwright/states-reporter.cjs +36 -7
  22. package/dist/playwright/states-reporter.cjs.map +1 -1
  23. package/dist/playwright/states-reporter.d.cts +15 -0
  24. package/dist/playwright/states-reporter.d.ts +15 -0
  25. package/dist/playwright/states-reporter.js +36 -7
  26. package/dist/playwright/states-reporter.js.map +1 -1
  27. package/dist/playwright/states.cjs +8 -0
  28. package/dist/playwright/states.cjs.map +1 -1
  29. package/dist/playwright/states.d.cts +44 -1
  30. package/dist/playwright/states.d.ts +44 -1
  31. package/dist/playwright/states.js +7 -0
  32. package/dist/playwright/states.js.map +1 -1
  33. package/dist/react/index.cjs +7 -1
  34. package/dist/react/index.cjs.map +1 -1
  35. package/dist/react/index.d.cts +55 -16
  36. package/dist/react/index.d.ts +55 -16
  37. package/dist/react/index.js +7 -1
  38. package/dist/react/index.js.map +1 -1
  39. package/dist/scan/index.cjs +1533 -294
  40. package/dist/scan/index.cjs.map +1 -1
  41. package/dist/scan/index.d.cts +459 -112
  42. package/dist/scan/index.d.ts +459 -112
  43. package/dist/scan/index.js +1517 -290
  44. package/dist/scan/index.js.map +1 -1
  45. package/package.json +1 -1
@@ -18,8 +18,8 @@ interface EntityRef {
18
18
  /**
19
19
  * The four kinds every captured route is expected to render — the state-matrix
20
20
  * axis. A capture that only shoots the happy path leaves most of the value on
21
- * the table, so a missing core kind must be captured, waived (the page CANNOT
22
- * render it), or acknowledged in the MISSING_KINDS baseline.
21
+ * the table, so a missing core kind must be captured or ACKNOWLEDGED (see
22
+ * `Metadata.acknowledge`).
23
23
  */
24
24
  declare const CORE_STATE_KINDS: readonly ["loading", "empty", "populated", "error"];
25
25
  type CoreStateKind = (typeof CORE_STATE_KINDS)[number];
@@ -37,34 +37,60 @@ interface StateDecl {
37
37
  name: string;
38
38
  /** Canonical kind for the state-matrix axis (defaults to `variant`). */
39
39
  kind?: StateKind;
40
- /** Acceptance criteria that only this state can evidence. */
41
- acceptance?: string[];
40
+ /**
41
+ * Acceptance criteria that only this state can evidence. Normalized into the
42
+ * same `{ id, rev, text }` regime as entity-level `acceptance` (one
43
+ * criterion-id namespace per entity), so per-state criteria are claimable by
44
+ * `uidexCovers` and visible to every acceptance gate.
45
+ */
46
+ acceptance?: AcceptanceCriterion[];
42
47
  description?: string;
43
48
  }
49
+ /**
50
+ * A normalized acceptance criterion. Authored either as a bare string (sugar:
51
+ * `id` is a deterministic kebab slug of the text, `rev` is 1) or as an object
52
+ * `{ id, rev?, text }`; parse-time normalization means everything downstream —
53
+ * audit, scaffold, the devtools — always sees this object shape. `rev` is the
54
+ * pin flows cover against (`uidexCovers("entity", "id@rev")`): bumping it when
55
+ * the criterion's meaning changes is what makes outdated-coverage detectable.
56
+ */
57
+ interface AcceptanceCriterion {
58
+ id: string;
59
+ rev: number;
60
+ text: string;
61
+ }
44
62
  interface Metadata {
45
63
  name?: string;
46
64
  description?: string;
47
- acceptance?: string[];
65
+ acceptance?: AcceptanceCriterion[];
48
66
  notes?: string;
49
67
  composes?: EntityRef[];
50
68
  flows?: readonly string[];
51
69
  features?: string[];
52
70
  widgets?: string[];
71
+ /** Page ids a feature declares it must be mounted on (feature kind only). */
72
+ surfaces?: string[];
53
73
  /** Declared render states (see StateDecl); the capture-completeness gate. */
54
74
  states?: StateDecl[];
55
75
  /**
56
- * `false` opts this page/feature/widget out of visual-states capture forever
57
- * (a redirect, a static notice, an internal target). The page-coverage gate
58
- * treats an opted-out route as accounted-for. Reason belongs in `description`.
76
+ * The ONE way to say "don't complain about this gap": scope typed reason.
77
+ *
78
+ * - scope `"*"` covers the whole entity (a redirect page that can never be
79
+ * captured, a component whose states are not gated here);
80
+ * - a core-kind scope covers that one cell of this page's route matrix.
81
+ *
82
+ * `type: "impossible"` is a permanent design statement and needs a `reason`;
83
+ * `type: "backlog"` is debt and does not. Keeping both as values of one field
84
+ * is what makes mislabeling debt as impossible a visible, reviewable edit.
85
+ * `captured-elsewhere` is computed by the workspace and never authored here.
59
86
  */
60
- capture?: boolean;
61
- /**
62
- * Per-core-kind waivers: a core kind this page's route legitimately CANNOT
63
- * render (a create form has no `empty`), mapped to a substantive reason. The
64
- * state-matrix gate treats a waived kind as accounted-for. A waiver is a
65
- * permanent design statement — unlike MISSING_KINDS backlog, which is debt.
66
- */
67
- waivers?: Partial<Record<CoreStateKind, string>>;
87
+ acknowledge?: Partial<Record<AcknowledgeScope, MetaAcknowledgment>>;
88
+ }
89
+ /** Scope of an acknowledgment: one core kind, or the whole entity. */
90
+ type AcknowledgeScope = CoreStateKind | "*";
91
+ interface MetaAcknowledgment {
92
+ type: "impossible" | "backlog";
93
+ reason?: string;
68
94
  }
69
95
  interface EntityWithMetaBase {
70
96
  id: string;
@@ -81,12 +107,25 @@ interface FlowStep {
81
107
  entityId: string;
82
108
  action?: string;
83
109
  }
110
+ /**
111
+ * A per-criterion coverage claim a flow makes via
112
+ * `uidexCovers("<entityId>", "<criterionId>@<rev>")`. The rev is REQUIRED at
113
+ * the claim site — a rev-less claim could never go stale, which would defeat
114
+ * the outdated-detection the pin exists for.
115
+ */
116
+ interface FlowCover {
117
+ entity: string;
118
+ criterion: string;
119
+ rev: number;
120
+ }
84
121
  interface Flow {
85
122
  kind: "flow";
86
123
  id: string;
87
124
  loc: Location;
88
125
  touches: string[];
89
126
  steps: FlowStep[];
127
+ /** Acceptance-criterion coverage claims made inside this flow's describe. */
128
+ covers?: FlowCover[];
90
129
  }
91
130
  interface Page extends EntityWithMetaBase {
92
131
  kind: "page";
@@ -18,8 +18,8 @@ interface EntityRef {
18
18
  /**
19
19
  * The four kinds every captured route is expected to render — the state-matrix
20
20
  * axis. A capture that only shoots the happy path leaves most of the value on
21
- * the table, so a missing core kind must be captured, waived (the page CANNOT
22
- * render it), or acknowledged in the MISSING_KINDS baseline.
21
+ * the table, so a missing core kind must be captured or ACKNOWLEDGED (see
22
+ * `Metadata.acknowledge`).
23
23
  */
24
24
  declare const CORE_STATE_KINDS: readonly ["loading", "empty", "populated", "error"];
25
25
  type CoreStateKind = (typeof CORE_STATE_KINDS)[number];
@@ -37,34 +37,60 @@ interface StateDecl {
37
37
  name: string;
38
38
  /** Canonical kind for the state-matrix axis (defaults to `variant`). */
39
39
  kind?: StateKind;
40
- /** Acceptance criteria that only this state can evidence. */
41
- acceptance?: string[];
40
+ /**
41
+ * Acceptance criteria that only this state can evidence. Normalized into the
42
+ * same `{ id, rev, text }` regime as entity-level `acceptance` (one
43
+ * criterion-id namespace per entity), so per-state criteria are claimable by
44
+ * `uidexCovers` and visible to every acceptance gate.
45
+ */
46
+ acceptance?: AcceptanceCriterion[];
42
47
  description?: string;
43
48
  }
49
+ /**
50
+ * A normalized acceptance criterion. Authored either as a bare string (sugar:
51
+ * `id` is a deterministic kebab slug of the text, `rev` is 1) or as an object
52
+ * `{ id, rev?, text }`; parse-time normalization means everything downstream —
53
+ * audit, scaffold, the devtools — always sees this object shape. `rev` is the
54
+ * pin flows cover against (`uidexCovers("entity", "id@rev")`): bumping it when
55
+ * the criterion's meaning changes is what makes outdated-coverage detectable.
56
+ */
57
+ interface AcceptanceCriterion {
58
+ id: string;
59
+ rev: number;
60
+ text: string;
61
+ }
44
62
  interface Metadata {
45
63
  name?: string;
46
64
  description?: string;
47
- acceptance?: string[];
65
+ acceptance?: AcceptanceCriterion[];
48
66
  notes?: string;
49
67
  composes?: EntityRef[];
50
68
  flows?: readonly string[];
51
69
  features?: string[];
52
70
  widgets?: string[];
71
+ /** Page ids a feature declares it must be mounted on (feature kind only). */
72
+ surfaces?: string[];
53
73
  /** Declared render states (see StateDecl); the capture-completeness gate. */
54
74
  states?: StateDecl[];
55
75
  /**
56
- * `false` opts this page/feature/widget out of visual-states capture forever
57
- * (a redirect, a static notice, an internal target). The page-coverage gate
58
- * treats an opted-out route as accounted-for. Reason belongs in `description`.
76
+ * The ONE way to say "don't complain about this gap": scope typed reason.
77
+ *
78
+ * - scope `"*"` covers the whole entity (a redirect page that can never be
79
+ * captured, a component whose states are not gated here);
80
+ * - a core-kind scope covers that one cell of this page's route matrix.
81
+ *
82
+ * `type: "impossible"` is a permanent design statement and needs a `reason`;
83
+ * `type: "backlog"` is debt and does not. Keeping both as values of one field
84
+ * is what makes mislabeling debt as impossible a visible, reviewable edit.
85
+ * `captured-elsewhere` is computed by the workspace and never authored here.
59
86
  */
60
- capture?: boolean;
61
- /**
62
- * Per-core-kind waivers: a core kind this page's route legitimately CANNOT
63
- * render (a create form has no `empty`), mapped to a substantive reason. The
64
- * state-matrix gate treats a waived kind as accounted-for. A waiver is a
65
- * permanent design statement — unlike MISSING_KINDS backlog, which is debt.
66
- */
67
- waivers?: Partial<Record<CoreStateKind, string>>;
87
+ acknowledge?: Partial<Record<AcknowledgeScope, MetaAcknowledgment>>;
88
+ }
89
+ /** Scope of an acknowledgment: one core kind, or the whole entity. */
90
+ type AcknowledgeScope = CoreStateKind | "*";
91
+ interface MetaAcknowledgment {
92
+ type: "impossible" | "backlog";
93
+ reason?: string;
68
94
  }
69
95
  interface EntityWithMetaBase {
70
96
  id: string;
@@ -81,12 +107,25 @@ interface FlowStep {
81
107
  entityId: string;
82
108
  action?: string;
83
109
  }
110
+ /**
111
+ * A per-criterion coverage claim a flow makes via
112
+ * `uidexCovers("<entityId>", "<criterionId>@<rev>")`. The rev is REQUIRED at
113
+ * the claim site — a rev-less claim could never go stale, which would defeat
114
+ * the outdated-detection the pin exists for.
115
+ */
116
+ interface FlowCover {
117
+ entity: string;
118
+ criterion: string;
119
+ rev: number;
120
+ }
84
121
  interface Flow {
85
122
  kind: "flow";
86
123
  id: string;
87
124
  loc: Location;
88
125
  touches: string[];
89
126
  steps: FlowStep[];
127
+ /** Acceptance-criterion coverage claims made inside this flow's describe. */
128
+ covers?: FlowCover[];
90
129
  }
91
130
  interface Page extends EntityWithMetaBase {
92
131
  kind: "page";
@@ -1024,6 +1024,9 @@ var tailwind_built_default = `/*! tailwindcss v4.2.2 | MIT License | https://tai
1024
1024
  .flex-1 {
1025
1025
  flex: 1;
1026
1026
  }
1027
+ .shrink {
1028
+ flex-shrink: 1;
1029
+ }
1027
1030
  .shrink-0 {
1028
1031
  flex-shrink: 0;
1029
1032
  }
@@ -7332,7 +7335,10 @@ function createEntityDetailView(config) {
7332
7335
  sections.push({ id: "description", text: meta.description });
7333
7336
  }
7334
7337
  if (offerAcceptance && meta?.acceptance?.length) {
7335
- sections.push({ id: "acceptance", items: meta.acceptance });
7338
+ sections.push({
7339
+ id: "acceptance",
7340
+ items: meta.acceptance.map((c) => c.text)
7341
+ });
7336
7342
  }
7337
7343
  if (entity) {
7338
7344
  for (const s of config.extraSections?.(ctx, entity) ?? []) {