document360-engine 0.2.9 → 0.2.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "document360-engine",
3
- "version": "0.2.9",
3
+ "version": "0.2.11",
4
4
  "description": "Headless documentation agent engine for document360-writer / -desktop. Emits a typed event stream; no UI.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/skills/CLAUDE.md CHANGED
@@ -112,6 +112,7 @@ The "Capabilities" section below lists specialized skills. Pick the right one ba
112
112
  - Any "convert/wrap this into a callout/tabs/FAQ/accordion" request, or authoring with rich components → apply `d360-markdown` (always-on syntax reference).
113
113
  - "/publish ..." → `publish-to-d360`.
114
114
  - "/screenshot ..." or any time you generate a screenshot placeholder → also call `emit-screenshot-spec`.
115
+ - "/capture-setup" / "what data do I need for screenshots" / after authoring screenshot specs in bulk → `capture-setup-checklist`.
115
116
  - Pulling extra context from other MCP sources during write-article → `gather-context-from-mcp`.
116
117
 
117
118
  If the user's intent is ambiguous, ask before invoking a skill that writes files or publishes.
@@ -0,0 +1,43 @@
1
+ # Skill: capture-setup-checklist
2
+
3
+ **Activate when** the user asks how to prepare data for screenshots ("what data do I need for captures", "capture setup", `/capture-setup`), OR right after you've emitted screenshot specs in bulk.
4
+
5
+ **Goal:** one reviewable "stage this data" checklist, so the user dresses the demo context ONCE before running `d360-capture` — the way a technical writer prepares a demo account before a screenshot session. Screenshots can't show data that isn't there; this tells the user exactly what to create.
6
+
7
+ ## How
8
+
9
+ 1. **Collect.** Find every `<!-- SCREENSHOT ... -->` block across `<docsDir>/**/*.md`. From each, read the `id`, the title, and the `prerequisites:` lines.
10
+ 2. **Anchor to the scope.** Read the capture `scope` keys from `.d360-capture.json` (e.g. `project`, or `project`+`workspace`, or `org` — whatever THIS product scopes by; do not assume "project"). If no scope is set yet, recommend the keys you saw the product use and tell the user to set them.
11
+ 3. **Synthesize — don't dump.** A raw per-spec list is noise. Instead:
12
+ - **Group by context** (e.g. "In the demo project «`scope.project`»:").
13
+ - **Dedupe** overlapping needs — if eight shots each need "≥1 suite", say it once.
14
+ - **Order foundational → specific**: create the context first, then the records, then per-shot specifics.
15
+ - **Separate the un-stageable**: shots needing a transient state (a toast, a mid-import modal) go under "Set up by hand at capture time", not the standing-data list.
16
+ 4. **Write it** to `<captureDir>/CAPTURE-SETUP.md` (versioned + reviewable). Re-running refreshes it.
17
+ 5. **Close** by telling the user the path, to set `scope` in `.d360-capture.json` to point at the prepared context, then `d360-capture auth` (once) and `d360-capture capture`.
18
+
19
+ ## Quality bar
20
+
21
+ - **Concrete:** real record names and counts ("create a suite named *Smoke*", "import one API spec"), not "have some data".
22
+ - **Generic:** use the product's actual scope keys; never hardcode FlowForge's "project".
23
+ - **Honest:** if a spec's `prerequisites:` are missing or vague, list that spec under "Needs a clearer prerequisite" rather than inventing data. Don't pretend a checklist item exists when the source doesn't say so.
24
+
25
+ ## Shape of the output (illustrative)
26
+
27
+ ```markdown
28
+ # Capture data setup
29
+
30
+ Prepare this once, then run `d360-capture capture`.
31
+
32
+ ## In the demo project "Docs Demo"
33
+ - [ ] At least 1 **suite** (e.g. "Smoke") — needed by: suites-tab-list, suite-run-dashboard, …
34
+ - [ ] At least 3 **schedules** — needed by: schedules-list-populated, schedule-context-menu
35
+ - [ ] 1 **capture** with a click-gallery + a video — needed by: captures-detail-*
36
+ - [ ] 1 imported **API spec** (with a version folder) — needed by: spec-import-*
37
+
38
+ ## Set up by hand at capture time (transient states)
39
+ - flow-generation-timeout-banner — trigger a generation timeout, then capture.
40
+
41
+ ## Needs a clearer prerequisite
42
+ - <spec-id> — its SCREENSHOT block doesn't say what data it needs; refine it.
43
+ ```
@@ -2,43 +2,69 @@
2
2
 
3
3
  **Activate when** you've just emitted a `<!-- SCREENSHOT ... -->` placeholder block in an article, OR the user runs `/screenshot <id>`.
4
4
 
5
- **Goal:** generate a Playwright `.spec.ts` file in the configured `captureDir` that the `document360-capture` (alias `d360-capture`) CLI can execute end-to-end against the user's running product.
5
+ **Goal:** generate a Playwright `.spec.ts` in the configured `captureDir` that the `document360-capture` (alias `d360-capture`) CLI runs against the user's live product.
6
6
 
7
- ## Where the spec lands
7
+ ## Read the product FIRST — never guess (non-negotiable)
8
8
 
9
- `<captureDir>/<placeholder.id>.spec.ts` read `captureDir` from `.d360-writer.json` (default: `user-docs/_capture`).
9
+ Every recurring capture failure has traced back to guessing. Before you write a single line, READ the source and ground each of these in it:
10
+
11
+ 1. **Routes** — find the router (e.g. the app's route table) and use the EXACT path. Do not assume `/spec` vs `/spec-files`, `/tests` vs `/test`. If you can't find it, say so and ask.
12
+ 2. **Selectors** — open the component and use a stable `data-testid` you actually see. Never invent one, and never fall back to `li`, `ul.divide-y li`, or other structural CSS.
13
+ 3. **Context selection** — find how the app enters the context the shot needs (selecting a project / workspace / org / etc.). You'll drive it with the capture *scope* (below), not by clicking "the first one".
14
+ 4. **Data prerequisites** — determine what state the screen needs to look real (≥1 of something, a specific record, an open modal). This becomes both the placeholder's `prerequisites:` and a runtime guard (below).
15
+
16
+ If a fact isn't in the source, do not fabricate it.
17
+
18
+ ## Capture scope — enter a KNOWN context, deterministically
19
+
20
+ The capture profile declares a generic `scope` (key→value) for the prepared demo context — e.g. `{project: "Docs Demo"}`, or `{project, workspace, language}`, or `{org}` — whatever THIS product scopes by (you learned that by reading the source; it is not always "project"). The CLI injects it; read it with the `captureScope()` / `scopeValue(key)` helpers.
21
+
22
+ - Select the context using the scope value (e.g. the project whose name === `scope.project`), via the selection mechanism you read from the source — **not** `.first()`.
23
+ - Fall back to `.first()` ONLY when the relevant scope key is unset, so single-context setups still work.
24
+
25
+ ## Data prerequisites — skip clearly, don't time out
26
+
27
+ If the data the shot needs is absent, a 15s selector timeout is a terrible error. Instead, guard it and skip with a reason that tells the user exactly what to stage:
28
+
29
+ ```typescript
30
+ if ((await rows.count()) === 0) {
31
+ test.skip(true, 'Prerequisite not met: needs ≥1 suite in project "' + (scopeValue('project') ?? '<scope>') + '". Stage it, then re-run.');
32
+ }
33
+ ```
34
+
35
+ The skip reason MUST match what you wrote in the placeholder's `prerequisites:` line — they're the same fact, surfaced two ways.
10
36
 
11
37
  ## Spec template
12
38
 
13
39
  ```typescript
14
40
  import { test } from '@playwright/test';
15
- import { waitPastLogin, dumpAnnotations, type Placeholder } from 'document360-capture/helpers';
41
+ import { waitPastLogin, dumpAnnotations, captureScope, scopeValue, type Placeholder } from 'document360-capture/helpers';
16
42
 
17
43
  const PLACEHOLDER: Placeholder = {
18
44
  id: '<placeholder.id>',
19
45
  saveTo: '<placeholder.save-to>',
20
- highlight: [
21
- // one stable selector per placeholder.highlight entry
22
- ],
23
- annotations: [
24
- // { target: '<stable selector>', label: '1', text: '<short text>' }
25
- ],
26
- redact: [
27
- // one stable selector per placeholder.redact entry
28
- ],
46
+ highlight: [ /* one stable selector per placeholder.highlight entry */ ],
47
+ annotations: [ /* { target: '<stable selector>', label: '1', text: '<short text>' } */ ],
48
+ redact: [ /* one stable selector per placeholder.redact entry */ ],
29
49
  };
30
50
 
31
51
  test('<placeholder.id>', async ({ page }) => {
32
52
  await page.goto(process.env.CAPTURE_START_URL!);
33
53
  await waitPastLogin(page, new RegExp(process.env.CAPTURE_AUTH_BOUNDARY!));
34
54
 
35
- // Translated from placeholder.steps one Playwright action per step.
36
- // Use STABLE selectors only.
37
- // ...
55
+ // 1. Enter the prepared context using the scope (selection mechanism read from source).
56
+ const scope = captureScope();
57
+ // …select the context by scope.<key>; fall back to first only when that key is unset…
58
+
59
+ // 2. Navigate using the EXACT route read from the router (never a guessed path).
60
+ // …
61
+
62
+ // 3. Prerequisite guard — skip with a clear reason instead of timing out.
63
+ // if ((await <rows>.count()) === 0) test.skip(true, 'Prerequisite not met: …');
38
64
 
65
+ // 4. Reach the target state, settle, capture.
39
66
  await page.waitForSelector('<target state selector>', { state: 'visible' });
40
67
  await page.waitForTimeout(500);
41
-
42
68
  await page.locator('<capture target selector>').screenshot({ path: PLACEHOLDER.saveTo });
43
69
  await dumpAnnotations(page, PLACEHOLDER);
44
70
  });
@@ -46,31 +72,27 @@ test('<placeholder.id>', async ({ page }) => {
46
72
 
47
73
  ## Selector quality rule (non-negotiable)
48
74
 
49
- Use stable selectors in this priority order:
50
-
75
+ Stable selectors in priority order:
51
76
  1. `[data-testid="..."]` — best.
52
77
  2. `[aria-label="..."]` — good.
53
- 3. `<role>:has-text("...")` / `role=button[name="..."]` — acceptable when unique.
54
- 4. Visible text (`text=...`, `:has-text(...)`) — acceptable for top-level nav and unique buttons.
78
+ 3. `role=button[name="..."]` / `<role>:has-text("...")` — acceptable when unique.
79
+ 4. Visible text (`text=...`) — acceptable for top-level nav and unique buttons.
55
80
 
56
- **Never** use CSS classes, `nth-child`, deep DOM paths, or auto-generated IDs (`#mui-12345`).
81
+ **Never** CSS classes, `nth-child`, structural `li`/`div.x`, deep DOM paths, or auto-generated IDs (`#mui-12345`).
57
82
 
58
- ## TODO escape hatch (when stable selectors don't exist)
59
-
60
- If a required interaction has no stable selector, do NOT write a fragile one. Instead:
83
+ ## TODO escape hatch (when a stable selector truly doesn't exist)
61
84
 
85
+ Don't write a fragile selector. Instead:
62
86
  1. Use `test.skip(...)` instead of `test(...)`.
63
- 2. Add a top-of-file comment: `// TODO: add data-testid="<suggested-name>" to <ComponentName> at <src/.../File.tsx>. Capture spec disabled until then.`
64
- 3. Tell the user which file + component to fix, plus the `data-testid` value you'd recommend.
65
-
66
- The manual intern path in the placeholder still works — only the automated capture is blocked.
87
+ 2. Top-of-file comment: `// TODO: add data-testid="<name>" to <Component> at <src/.../File.tsx>. Capture disabled until then.`
88
+ 3. Tell the user which file + component to fix and the `data-testid` to add.
67
89
 
68
90
  ## Capture region (the placeholder's `capture` field)
69
91
 
70
92
  | `capture` value | Spec uses |
71
93
  |---|---|
72
94
  | `full-page` | `await page.screenshot({ path, fullPage: true })` |
73
- | `main-panel` | a stable container selector (read it from the project's main layout source) |
95
+ | `main-panel` | a stable container selector (read it from the layout source) |
74
96
  | `modal-only` | `page.locator('[role="dialog"]').first().screenshot(...)` |
75
97
  | `panel-left` / `panel-right` | the project's named-panel selector |
76
98
  | `sidebar` | the project's sidebar selector |
@@ -78,8 +100,10 @@ The manual intern path in the placeholder still works — only the automated cap
78
100
  ## After writing the spec
79
101
 
80
102
  - Report the spec's path.
81
- - If you used the TODO escape hatch, surface the blocking selectors so the dev can fix them in one pass.
82
- - Remind the user how to capture it (screenshots are a separate tool — `document360-capture` is not bundled with the writer):
103
+ - List anything that needs the user: the `data-testid`s a dev must add (TODO hatch), and the **data prerequisites** to stage (project/workspace + the records each shot needs).
104
+ - After authoring several specs, run `capture-setup-checklist` to refresh the consolidated `CAPTURE-SETUP.md` staging guide.
105
+ - Remind how to capture (screenshots are a separate tool — not bundled with the writer):
83
106
  1. First time only: `npm i -g document360-capture`
84
- 2. Once per machine: `d360-capture auth --profile <name>`
85
- 3. `d360-capture capture <id>` to take the screenshot.
107
+ 2. Set the capture `scope` for the prepared demo context in `.d360-capture.json`.
108
+ 3. Once per machine: `d360-capture auth --profile <name>`
109
+ 4. `d360-capture capture <id>`.