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
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`
|
|
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
|
-
##
|
|
7
|
+
## Read the product FIRST — never guess (non-negotiable)
|
|
8
8
|
|
|
9
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
36
|
-
|
|
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
|
-
|
|
50
|
-
|
|
75
|
+
Stable selectors in priority order:
|
|
51
76
|
1. `[data-testid="..."]` — best.
|
|
52
77
|
2. `[aria-label="..."]` — good.
|
|
53
|
-
3.
|
|
54
|
-
4. Visible text (`text
|
|
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**
|
|
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
|
|
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.
|
|
64
|
-
3. Tell the user which file + component to fix
|
|
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
|
|
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
|
-
-
|
|
82
|
-
-
|
|
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.
|
|
85
|
-
3. `d360-capture
|
|
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>`.
|