@alistigo/features 0.2.4 → 0.2.6

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/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alistigo/features",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "license": "MIT",
5
5
  "author": {
6
6
  "name": "Mikael Labrut",
package/dist/tags.d.ts CHANGED
@@ -11,17 +11,24 @@
11
11
  * Tag categories follow the `gherkin-features` skill: Milestone, Group,
12
12
  * Capability, Test type, Suite, Actor.
13
13
  */
14
- /** Which milestone a feature belongs to. Required — every Feature has exactly one. */
15
- export declare const MILESTONE_TAGS: readonly ["@m1", "@m2", "@m3", "@m4", "@v1"];
14
+ /**
15
+ * Which milestone a feature belongs to. Required — every Feature has exactly one.
16
+ *
17
+ * `@platform` marks cross-cutting platform capabilities (e.g. the artifact plugin
18
+ * system) that are orthogonal to the numbered milestone sequence, rather than
19
+ * belonging to a specific numbered milestone.
20
+ */
21
+ export declare const MILESTONE_TAGS: readonly ["@m1", "@m2", "@m3", "@m4", "@v1", "@platform"];
16
22
  export type MilestoneTag = (typeof MILESTONE_TAGS)[number];
17
23
  /**
18
24
  * Which feature group a feature belongs to. Required — every Feature has
19
25
  * exactly one. Mirrors the folder layout under `features/`.
20
26
  *
21
27
  * - `@core` — base list app (text elements, add, delete, persist)
22
- * - Plugin groups will be added as plugins land: `@todo`, `@checklist`, etc.
28
+ * - `@artifact-plugins` artifact-lifecycle/infra plugins (Sentry, PostHog)
29
+ * - Domain plugin groups will be added as they land: `@todo`, `@checklist`, etc.
23
30
  */
24
- export declare const GROUP_TAGS: readonly ["@core"];
31
+ export declare const GROUP_TAGS: readonly ["@core", "@artifact-plugins"];
25
32
  export type GroupTag = (typeof GROUP_TAGS)[number];
26
33
  /** What capability the feature exercises. Required — at least one. */
27
34
  export declare const CAPABILITY_TAGS: readonly ["@capability:list", "@capability:element", "@capability:persistence", "@capability:loading", "@capability:export", "@capability:host-protocol", "@capability:plugins"];
@@ -1 +1 @@
1
- {"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../src/tags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,sFAAsF;AACtF,eAAO,MAAM,cAAc,8CAA+C,CAAC;AAC3E,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,oBAAqB,CAAC;AAC7C,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,sEAAsE;AACtE,eAAO,MAAM,eAAe,kLAQlB,CAAC;AACX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,+CAA+C;AAC/C,eAAO,MAAM,cAAc,uDAAwD,CAAC;AACpF,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,0DAA0D;AAC1D,eAAO,MAAM,UAAU,6CAA8C,CAAC;AACtE,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,2CAA2C;AAC3C,eAAO,MAAM,UAAU,sDAAuD,CAAC;AAC/E,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,MAAM,MAAM,WAAW,GACnB,YAAY,GACZ,QAAQ,GACR,aAAa,GACb,WAAW,GACX,QAAQ,GACR,QAAQ,CAAC;AAEb,eAAO,MAAM,QAAQ,EAAE,SAAS,WAAW,EAO1C,CAAC;AAIF,0DAA0D;AAC1D,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,WAAW,CAE1D"}
1
+ {"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../src/tags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,2DAA4D,CAAC;AACxF,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,yCAA0C,CAAC;AAClE,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,sEAAsE;AACtE,eAAO,MAAM,eAAe,kLAQlB,CAAC;AACX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,+CAA+C;AAC/C,eAAO,MAAM,cAAc,uDAAwD,CAAC;AACpF,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,0DAA0D;AAC1D,eAAO,MAAM,UAAU,6CAA8C,CAAC;AACtE,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,2CAA2C;AAC3C,eAAO,MAAM,UAAU,sDAAuD,CAAC;AAC/E,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,MAAM,MAAM,WAAW,GACnB,YAAY,GACZ,QAAQ,GACR,aAAa,GACb,WAAW,GACX,QAAQ,GACR,QAAQ,CAAC;AAEb,eAAO,MAAM,QAAQ,EAAE,SAAS,WAAW,EAO1C,CAAC;AAIF,0DAA0D;AAC1D,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,WAAW,CAE1D"}
package/dist/tags.js CHANGED
@@ -11,16 +11,23 @@
11
11
  * Tag categories follow the `gherkin-features` skill: Milestone, Group,
12
12
  * Capability, Test type, Suite, Actor.
13
13
  */
14
- /** Which milestone a feature belongs to. Required — every Feature has exactly one. */
15
- export const MILESTONE_TAGS = ["@m1", "@m2", "@m3", "@m4", "@v1"];
14
+ /**
15
+ * Which milestone a feature belongs to. Required — every Feature has exactly one.
16
+ *
17
+ * `@platform` marks cross-cutting platform capabilities (e.g. the artifact plugin
18
+ * system) that are orthogonal to the numbered milestone sequence, rather than
19
+ * belonging to a specific numbered milestone.
20
+ */
21
+ export const MILESTONE_TAGS = ["@m1", "@m2", "@m3", "@m4", "@v1", "@platform"];
16
22
  /**
17
23
  * Which feature group a feature belongs to. Required — every Feature has
18
24
  * exactly one. Mirrors the folder layout under `features/`.
19
25
  *
20
26
  * - `@core` — base list app (text elements, add, delete, persist)
21
- * - Plugin groups will be added as plugins land: `@todo`, `@checklist`, etc.
27
+ * - `@artifact-plugins` artifact-lifecycle/infra plugins (Sentry, PostHog)
28
+ * - Domain plugin groups will be added as they land: `@todo`, `@checklist`, etc.
22
29
  */
23
- export const GROUP_TAGS = ["@core"];
30
+ export const GROUP_TAGS = ["@core", "@artifact-plugins"];
24
31
  /** What capability the feature exercises. Required — at least one. */
25
32
  export const CAPABILITY_TAGS = [
26
33
  "@capability:list",
package/dist/tags.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tags.js","sourceRoot":"","sources":["../src/tags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,sFAAsF;AACtF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAU,CAAC;AAG3E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAO,CAAU,CAAC;AAG7C,sEAAsE;AACtE,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,kBAAkB;IAClB,qBAAqB;IACrB,yBAAyB;IACzB,qBAAqB;IACrB,oBAAoB;IACpB,2BAA2B;IAC3B,qBAAqB;CACb,CAAC;AAGX,+CAA+C;AAC/C,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,aAAa,EAAE,YAAY,EAAE,aAAa,CAAU,CAAC;AAGpF,0DAA0D;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,QAAQ,EAAE,aAAa,EAAE,OAAO,CAAU,CAAC;AAGtE,2CAA2C;AAC3C,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,aAAa,EAAE,WAAW,EAAE,aAAa,CAAU,CAAC;AAW/E,MAAM,CAAC,MAAM,QAAQ,GAA2B;IAC9C,GAAG,cAAc;IACjB,GAAG,UAAU;IACb,GAAG,eAAe;IAClB,GAAG,cAAc;IACjB,GAAG,UAAU;IACb,GAAG,UAAU;CACd,CAAC;AAEF,MAAM,OAAO,GAAG,IAAI,GAAG,CAAS,QAAQ,CAAC,CAAC;AAE1C,0DAA0D;AAC1D,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC"}
1
+ {"version":3,"file":"tags.js","sourceRoot":"","sources":["../src/tags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,CAAU,CAAC;AAGxF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,mBAAmB,CAAU,CAAC;AAGlE,sEAAsE;AACtE,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,kBAAkB;IAClB,qBAAqB;IACrB,yBAAyB;IACzB,qBAAqB;IACrB,oBAAoB;IACpB,2BAA2B;IAC3B,qBAAqB;CACb,CAAC;AAGX,+CAA+C;AAC/C,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,aAAa,EAAE,YAAY,EAAE,aAAa,CAAU,CAAC;AAGpF,0DAA0D;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,QAAQ,EAAE,aAAa,EAAE,OAAO,CAAU,CAAC;AAGtE,2CAA2C;AAC3C,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,aAAa,EAAE,WAAW,EAAE,aAAa,CAAU,CAAC;AAW/E,MAAM,CAAC,MAAM,QAAQ,GAA2B;IAC9C,GAAG,cAAc;IACjB,GAAG,UAAU;IACb,GAAG,eAAe;IAClB,GAAG,cAAc;IACjB,GAAG,UAAU;IACb,GAAG,UAAU;CACd,CAAC;AAEF,MAAM,OAAO,GAAG,IAAI,GAAG,CAAS,QAAQ,CAAC,CAAC;AAE1C,0DAA0D;AAC1D,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,58 @@
1
+ # artifact-plugins — Artifact-lifecycle/infra plugins
2
+
3
+ Feature group for the composable artifact plugin system (see
4
+ [ADR 0016](../../../../docs/adrs/0016-artifact-plugin-system.md)). Covers
5
+ plugins that hook into an artifact's lifecycle and event bus — Sentry error
6
+ monitoring, PostHog analytics — as distinct from future domain-contribution
7
+ plugins (checkbox, priority, etc.) which will get their own group folder(s)
8
+ when they land.
9
+
10
+ | File | Capability |
11
+ |------|------------|
12
+ | [sentry-error-capture.feature](sentry-error-capture.feature) | Sentry plugin initialization and error reporting |
13
+ | [posthog-analytics-tracking.feature](posthog-analytics-tracking.feature) | PostHog plugin initialization and widget-displayed tracking |
14
+
15
+ ## Scope
16
+
17
+ These scenarios describe plugin lifecycle mechanics — hook invocation and event
18
+ reaction — at the Host/Plugin contract level, not real network behavior. No
19
+ scenario should make a real Sentry or PostHog network call; "the plugin captures an
20
+ event" means the plugin's own capture function was invoked with the expected
21
+ payload.
22
+
23
+ This is a `@platform` milestone group — orthogonal to the numbered `@m1`–`@m4`
24
+ sequence, since the plugin system is cross-cutting infrastructure rather than a
25
+ milestone-scoped list capability.
26
+
27
+ ## Status: `@todo`
28
+
29
+ Both features are tagged `@todo` — the runner (`cli/alistigo-features-runner-playwright`)
30
+ skips them rather than failing on undefined steps. Unlike the `core/` group, this
31
+ runner is a real Playwright harness driving the built iframe against a live preview
32
+ server, not an in-memory Application-layer runner. Implementing these scenarios for
33
+ real requires:
34
+
35
+ - Intercepting (via `page.route()`) the jsDelivr URL a plugin resolves to, so the
36
+ dynamic `import()` in `@alistigo/artifact-plugin-api`'s loader serves a local fake
37
+ plugin bundle instead of a real network request — keeping the scenario
38
+ network-free while still exercising the real load → `setup()` → event-subscription
39
+ path end-to-end.
40
+ - An observable proxy for internal plugin/event state from the page — the exposed
41
+ `Alistigo.about()` debug API (`plugins: string[]`) covers "is a plugin loaded";
42
+ asserting an emitted event was actually captured needs either a page-side test hook
43
+ or a fake plugin bundle that writes an observable marker (e.g. a DOM attribute) when
44
+ its capture function runs.
45
+
46
+ Remove `@todo` once that harness support exists and the steps are implemented.
47
+
48
+ ## Definition of Done
49
+
50
+ This group is done when every scenario in this folder is green via the runner,
51
+ and a plugin's own package (`@alistigo/artifact-sentry-plugin`,
52
+ `@alistigo/artifact-posthog-plugin`) implements exactly the hooks these
53
+ scenarios describe.
54
+
55
+ See:
56
+ - [`docs/adrs/0016-artifact-plugin-system.md`](../../../../docs/adrs/0016-artifact-plugin-system.md) for the design
57
+ - [`docs/glossary.md`](../../docs/glossary.md) for the Plugin entity and Host actor
58
+ - [`docs/style-guide.md`](../../docs/style-guide.md) for how to write a scenario
@@ -0,0 +1,31 @@
1
+ @platform
2
+ @artifact-plugins
3
+ @capability:plugins
4
+ @actor:host
5
+ @todo
6
+ Feature: PostHog plugin tracks widget display
7
+ As the Host
8
+ I want the PostHog plugin to record a widget_displayed event on first mount
9
+ So that product usage is measurable without coupling core to a specific vendor
10
+
11
+ @happy-path
12
+ @smoke
13
+ Scenario: PostHog plugin captures widget_displayed on first mount
14
+ Given an artifact host with the PostHog plugin enabled and an API key configured
15
+ When the host completes its first mount
16
+ Then the host should emit a "widget:displayed" event with the locale, storage type, and version
17
+ And the PostHog plugin should capture a "widget_displayed" event with those properties
18
+
19
+ @edge-case
20
+ Scenario: PostHog plugin does not double-report on remount
21
+ Given an artifact host with the PostHog plugin enabled and an API key configured
22
+ And the host has already completed its first mount
23
+ When the host is mounted again on the same container
24
+ Then the host should not emit a second "widget:displayed" event
25
+
26
+ @edge-case
27
+ Scenario: PostHog plugin is a silent no-op without an API key
28
+ Given an artifact host with the PostHog plugin enabled but no API key configured
29
+ When the host completes its first mount
30
+ Then the PostHog plugin should report itself as not initialized
31
+ And the PostHog plugin should not capture any event
@@ -0,0 +1,30 @@
1
+ @platform
2
+ @artifact-plugins
3
+ @capability:plugins
4
+ @actor:host
5
+ Feature: Sentry plugin captures render errors
6
+ As the Host
7
+ I want the Sentry plugin to observe and report uncaught render errors
8
+ So that developers learn about failures without manual instrumentation
9
+
10
+ @happy-path
11
+ Scenario: Sentry plugin initializes when a DSN is configured
12
+ Given the "@alistigo/artifact-sentry-plugin" plugin
13
+ And a non-initialized artifact "list" with plugin configured
14
+ When the artifact initialize
15
+ Then the plugin should be initialized
16
+
17
+ @happy-path
18
+ Scenario: An uncaught render error is reported through the plugin
19
+ Given the "@alistigo/artifact-sentry-plugin" plugin
20
+ And an initialized artifact "list" with plugin configured
21
+ When an uncaught render error occurs
22
+ Then the plugin should capture the error
23
+
24
+ @edge-case
25
+ Scenario: Sentry plugin is a silent no-op without a DSN
26
+ Given the "@alistigo/artifact-sentry-plugin" plugin
27
+ And an non-initialized artifact "list" with plugin not configured
28
+ When the artifact initialize
29
+ Then the plugin should report itself as not initialized
30
+ And no error should be thrown
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alistigo/features",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "license": "MIT",
5
5
  "author": {
6
6
  "name": "Mikael Labrut",