forked from setube/stackprism
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstackprism-skill.test.mjs
More file actions
276 lines (265 loc) · 17.9 KB
/
Copy pathstackprism-skill.test.mjs
File metadata and controls
276 lines (265 loc) · 17.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
import { test } from 'node:test'
const skillSource = await readFile(new URL('../agent-skill/stackprism-site-experience/SKILL.md', import.meta.url), 'utf8')
const agentsSource = await readFile(new URL('../AGENTS.md', import.meta.url), 'utf8')
const readmeSource = await readFile(new URL('../agent-skill/stackprism-site-experience/README.md', import.meta.url), 'utf8')
const openaiYamlSource = await readFile(new URL('../agent-skill/stackprism-site-experience/agents/openai.yaml', import.meta.url), 'utf8')
const consumptionGuideSource = await readFile(
new URL('../agent-skill/stackprism-site-experience/references/agent-consumption-guide.md', import.meta.url),
'utf8'
)
const profileSchemaSource = await readFile(
new URL('../agent-skill/stackprism-site-experience/references/site-experience-profile-schema.md', import.meta.url),
'utf8'
)
const frontmatter = source => {
const match = source.match(/^---\n(?<body>[\s\S]*?)\n---/)
assert.ok(match?.groups?.body, 'skill must have YAML frontmatter')
return Object.fromEntries(
match.groups.body.split('\n').map(line => {
const separatorIndex = line.indexOf(':')
assert.ok(separatorIndex > 0, `invalid frontmatter line: ${line}`)
return [line.slice(0, separatorIndex).trim(), line.slice(separatorIndex + 1).trim()]
})
)
}
const yamlValue = (source, key) => {
const match = source.match(new RegExp(`^\\s*${key}:\\s*'(?<value>[^']+)'`, 'm'))
assert.ok(match?.groups?.value, `missing ${key} in openai.yaml`)
return match.groups.value
}
const fencedBlocks = source => [...source.matchAll(/```(?<lang>\w+)?\n(?<body>[\s\S]*?)```/g)].map(match => match.groups)
const assertBefore = (source, first, second) => {
const firstIndex = source.indexOf(first)
const secondIndex = source.indexOf(second)
assert.notEqual(firstIndex, -1, `missing ${first}`)
assert.notEqual(secondIndex, -1, `missing ${second}`)
assert.ok(firstIndex < secondIndex, `${first} must appear before ${second}`)
}
test('stackprism site experience skill advertises the current bridge workflow', () => {
const metadata = frontmatter(skillSource)
const bashBlocks = fencedBlocks(skillSource)
.filter(block => block.lang === 'bash')
.map(block => block.body)
assert.equal(metadata.name, 'stackprism-site-experience')
assert.match(metadata.description, /StackPrism Agent Bridge profile/)
assert.match(metadata.description, /specific http\(s\) URL/)
assert.match(metadata.description, /Agent Bridge E2E verification/)
assert.match(metadata.description, /Do not use for generic UI edits/)
assert.match(metadata.description, /backend-only work/)
assert.match(metadata.description, /StackPrism internal code review/)
assert.match(skillSource, /StackPrism internal source review, refactor, or maintenance/)
assert.ok(
bashBlocks.some(block => block.includes('scripts/capture-site.mjs')),
'skill must show preferred capture helper'
)
assert.ok(
bashBlocks.some(block => block.includes('scripts/stackprism-bridge.mjs')),
'skill must show JS bridge'
)
assert.ok(
bashBlocks.some(block => block.includes('scripts/stackprism_bridge.py')),
'skill must show Python fallback'
)
assert.match(skillSource, /scripts\/capture-site\.mjs/)
assert.match(skillSource, /scripts\/stackprism-bridge\.mjs/)
assert.match(skillSource, /scripts\/stackprism_bridge\.py/)
assert.match(skillSource, /STACKPRISM_BROWSER_OPEN_COMMAND/)
assert.match(skillSource, /STACKPRISM_BROWSER_OPEN_ARGS_JSON/)
assert.match(skillSource, /--allow-private-network/)
assert.match(skillSource, /confirm the dev server is running and the URL is reachable/)
assert.match(skillSource, /Localhost support is only for public, demo, or explicitly desensitized development pages/)
assert.match(skillSource, /local, intranet, or internal pages that contain login state/)
assert.match(skillSource, /--include tech,visual,layout,components,interaction,ux,assets/)
assert.match(skillSource, /--max-resource-urls/)
assert.match(skillSource, /one JSON summary on stdout/)
assert.match(skillSource, /one JSON error object to stderr/)
assert.match(skillSource, /`error\.code`, `error\.message`, and sanitized `error\.details`/)
assert.match(skillSource, /PRIVATE_NETWORK_TARGET_BLOCKED/)
assert.match(skillSource, /CAPTURE_BUSY/)
assert.match(skillSource, /AGENT_BRIDGE_DISABLED/)
assert.match(skillSource, /EXTENSION_NOT_CONNECTED/)
assert.match(skillSource, /Firefox profiles/)
assert.match(skillSource, /"--profile","\/absolute\/path\/to\/profile"/)
assert.match(skillSource, /correct Chrome, Edge, or Firefox profile/)
assert.match(skillSource, /Cross-platform explicit profile examples/)
assert.match(skillSource, /Set environment variables with the syntax of the current shell/)
assert.match(skillSource, /examples below describe the values/)
assert.match(skillSource, /Windows Chrome/)
assert.match(skillSource, /C:\\Program Files\\Google\\Chrome\\Application\\chrome\.exe/)
assert.match(skillSource, /Windows Edge/)
assert.match(skillSource, /Linux Chrome\/Chromium/)
assert.match(skillSource, /STACKPRISM_BROWSER_OPEN_COMMAND=firefox/)
assert.match(skillSource, /\["-P","<firefox-profile-with-stackprism>"\]/)
assert.match(skillSource, /## Private Page Boundary/)
assert.match(skillSource, /even when the user says they own the account/)
assert.match(skillSource, /I cannot automatically capture that private or logged-in page with StackPrism/)
assert.match(skillSource, /public demo URL, a desensitized test-environment URL/)
assert.match(skillSource, /current browser page/)
assert.match(skillSource, /do not use `active_tab`/)
assert.match(skillSource, /If you already have a redacted screenshot or recording with private content removed/)
assert.match(skillSource, /do not create a new screenshot of the private page for this request/)
assert.match(skillSource, /do not ask the user to create screenshots for private pages/)
assert.match(skillSource, /Accept a user-provided redacted screenshot or recording only if the user already has one/)
assert.match(skillSource, /http:\/\/127\.0\.0\.1:5173\//)
assert.match(skillSource, /\/Applications\/Google Chrome\.app\/Contents\/MacOS\/Google Chrome/)
assert.match(skillSource, /<profile-directory-with-stackprism>/)
assert.match(skillSource, /do not use `Default` unless the user confirms StackPrism is installed and enabled there/)
assert.match(skillSource, /--include tech,visual,layout,components,ux/)
assert.match(skillSource, /--max-resource-urls 150/)
assert.match(skillSource, /--include tech,layout,components,ux/)
assert.match(skillSource, /--max-resource-urls 50/)
assert.match(skillSource, /--no-screenshot/)
assert.match(skillSource, /Retry attempts must preserve the original capture context exactly/)
assert.match(skillSource, /same `STACKPRISM_BROWSER_OPEN_COMMAND`/)
assert.match(skillSource, /same target policy flags such as `--allow-private-network`/)
assert.match(skillSource, /add that flag directly after `--url "\$TARGET_URL"`/)
assert.match(skillSource, /For an original local\/private attempt, add/)
assert.doesNotMatch(skillSource, /STACKPRISM_CAPTURE_TARGET_FLAGS/)
assert.match(skillSource, /Before the final non-visual attempt/)
assert.match(skillSource, /Do not run the final `--no-screenshot` retry until the user confirms/)
assert.match(skillSource, /the result can only support structural, technology, component, and limited UX findings/)
assert.match(skillSource, /The current experience profile is passive/)
assert.match(skillSource, /does not click, type, submit forms, or exercise workflows/)
assert.match(skillSource, /"captureScreenshot": true/)
assert.match(skillSource, /## E2E Evidence Manifest/)
assert.match(skillSource, /browserName/)
assert.match(skillSource, /profileIdentifier/)
assert.match(skillSource, /extensionVersion/)
assert.match(skillSource, /privateNetworkOverrideUsed/)
assert.match(skillSource, /Safe to report/)
assert.match(skillSource, /Never paste or commit/)
assert.match(skillSource, /`apiToken`/)
assert.match(skillSource, /token-bearing bridge URLs/)
assert.match(skillSource, /`captureId` may appear in local result artifacts/)
assert.match(skillSource, /shasum -a 256/)
assert.match(skillSource, /stat -f '%N %z bytes'/)
assert.match(skillSource, /Use this public report template instead of pasting raw stdout/)
assert.match(skillSource, /"captureId": "\[redacted\]"/)
assert.match(skillSource, /"browserName": "<Chrome\|Edge\|Firefox>"/)
assert.match(skillSource, /"profileIdentifier": "<profile-label-used-for-this-run>"/)
assert.match(skillSource, /extension details page/)
assert.match(skillSource, /Do not include extension internal UUIDs/)
assert.match(skillSource, /## Firefox E2E Validation/)
assert.match(skillSource, /exact safe public `http:` or `https:` smoke URL/)
assert.match(skillSource, /do not choose an arbitrary public page/)
assert.match(skillSource, /\/Applications\/Firefox\.app\/Contents\/MacOS\/firefox/)
assert.match(skillSource, /<firefox-profile-with-stackprism>/)
assert.match(skillSource, /browserName` to `Firefox/)
assert.match(skillSource, /exact `-P` profile name or `--profile` path label/)
assert.match(skillSource, /When the user asks for a recreation brief/)
assert.match(skillSource, /Record the captured viewport names and dimensions/)
assert.match(skillSource, /Do not infer mobile or responsive breakpoint behavior/)
})
test('stackprism site experience skill points agents to repo-local references', () => {
assert.match(skillSource, /references\/site-experience-profile-schema\.md/)
assert.match(skillSource, /references\/agent-consumption-guide\.md/)
assert.match(profileSchemaSource, /Schema id: `stackprism\.site_experience_profile\.v1`/)
assert.match(profileSchemaSource, /agentGuidance/)
assert.match(profileSchemaSource, /recreationPlan/)
assert.match(profileSchemaSource, /Screenshot image base64 is intentionally omitted/)
assert.match(consumptionGuideSource, /Start from `agentGuidance\.recreationPlan`/)
assert.match(consumptionGuideSource, /Read `limitations`/)
assertBefore(consumptionGuideSource, 'Read `limitations` first', 'Start from `agentGuidance.recreationPlan`')
assertBefore(skillSource, 'Read `limitations` first', 'Start from `agentGuidance.recreationPlan`')
assert.match(consumptionGuideSource, /verificationChecklist/)
assert.match(consumptionGuideSource, /Raw `\/profile` access still requires the API token/)
assert.match(consumptionGuideSource, /Never copy `apiToken`, `bridgeToken`, nonce/)
assert.match(consumptionGuideSource, /raw profile JSON containing private content/)
assert.match(consumptionGuideSource, /screenshot data URLs/)
assert.match(consumptionGuideSource, /If `visualProfile` or screenshot evidence is missing, do not claim visual parity/)
assert.match(consumptionGuideSource, /A tech-only profile supports technology, dependency, and runtime observations only/)
assert.match(consumptionGuideSource, /not sufficient for UI implementation, visual comparison, or visual verification/)
assert.match(consumptionGuideSource, /A reduced non-visual retry supports structural, technology, and limited UX findings only/)
assert.match(consumptionGuideSource, /A reduced retry is valid only if it preserved the original capture context/)
assert.match(consumptionGuideSource, /target policy flags such as `--allow-private-network`/)
assert.match(consumptionGuideSource, /Destination project conventions override the source page's stack/)
assert.match(consumptionGuideSource, /component library, routing, state, CSS architecture, test framework/)
assert.match(consumptionGuideSource, /Interaction smoke tests should cover viewport, key path, hover and focus states/)
assert.match(consumptionGuideSource, /responsive breakpoint, screenshot or DOM geometry evidence, and explicit limitations/)
assert.match(consumptionGuideSource, /StackPrism experience capture is passive/)
assert.match(consumptionGuideSource, /does not click, type, submit forms, or exercise workflows/)
assert.match(consumptionGuideSource, /For recreation briefs, structure the brief from `agentGuidance\.recreationPlan`/)
assert.match(consumptionGuideSource, /Recreation brief structure/)
assert.match(consumptionGuideSource, /Evidence and limitations/)
assert.match(consumptionGuideSource, /captured viewport names and dimensions/)
assert.match(consumptionGuideSource, /Technical direction/)
assert.match(consumptionGuideSource, /Visual direction/)
assert.match(consumptionGuideSource, /Layout and components/)
assert.match(consumptionGuideSource, /Interaction and UX/)
assert.match(consumptionGuideSource, /Assets and verification/)
assert.match(consumptionGuideSource, /Safe report fields/)
assert.match(consumptionGuideSource, /unredacted `captureId`/)
assert.match(consumptionGuideSource, /Screenshots are not pixel-redacted/)
assert.match(consumptionGuideSource, /login-protected, account-specific, billing/)
assert.match(consumptionGuideSource, /billing, admin, inbox, dashboard, internal/)
assert.match(consumptionGuideSource, /I cannot automatically capture that private or logged-in page with StackPrism/)
assert.match(consumptionGuideSource, /public demo URL, a desensitized test-environment URL/)
assert.match(consumptionGuideSource, /If you already have a redacted screenshot or recording with private content removed/)
assert.match(consumptionGuideSource, /do not create a new screenshot of the private page for this request/)
assert.match(consumptionGuideSource, /Localhost or intranet targets are acceptable only when they are public, demo, or explicitly desensitized development pages/)
assert.match(consumptionGuideSource, /current browser page/)
assert.match(consumptionGuideSource, /Accept redacted screenshots or recordings only when the user already has them/)
assert.match(consumptionGuideSource, /do not ask the user to create new screenshots of private pages/)
assert.match(profileSchemaSource, /`visualReference` for optional screenshot handling/)
assert.match(profileSchemaSource, /`verificationChecklist` for destination-app acceptance checks/)
})
test('stackprism site experience skill UI metadata remains aligned with global discovery', () => {
const shortDescription = yamlValue(openaiYamlSource, 'short_description')
const defaultPrompt = yamlValue(openaiYamlSource, 'default_prompt')
assert.equal(yamlValue(openaiYamlSource, 'display_name'), 'StackPrism Site Experience')
assert.equal(shortDescription, 'Capture StackPrism Agent Bridge URL profiles')
assert.ok(shortDescription.length >= 25 && shortDescription.length <= 64)
assert.match(defaultPrompt, /\$stackprism-site-experience/)
assert.match(defaultPrompt, /StackPrism Agent Bridge profile/)
assert.match(defaultPrompt, /website recreation/)
assert.match(defaultPrompt, /UX comparison/)
assert.match(defaultPrompt, /live browser evidence/)
assert.match(defaultPrompt, /Agent Bridge E2E validation/)
assert.match(defaultPrompt, /extension/)
assert.match(defaultPrompt, /not private login\/account/)
assert.ok(defaultPrompt.length <= 260)
assert.equal(defaultPrompt.split(/[.!?]\s+/).filter(Boolean).length, 1)
assert.match(openaiYamlSource, /display_name: 'StackPrism Site Experience'/)
assert.match(openaiYamlSource, /allow_implicit_invocation: true/)
})
test('repo-local skill documents bridge asset parity and local installation boundary', () => {
assert.match(readmeSource, /not automatically installed into Codex or any global skill registry/)
assert.match(readmeSource, /JavaScript bridge and Python fallback intentionally share the same bridge page CSS and client script text/)
assert.match(readmeSource, /--include tech,visual,layout,components,interaction,ux,assets/)
assert.match(readmeSource, /--max-resource-urls <n>/)
assert.match(readmeSource, /The direct bridge scripts print a single ready JSON line/)
assert.match(readmeSource, /one JSON summary to stdout/)
assert.match(readmeSource, /one JSON error object to stderr/)
assert.match(readmeSource, /Local development targets such as `localhost`/)
assert.match(readmeSource, /--allow-private-network/)
assert.match(readmeSource, /Localhost support is only for public, demo, or explicitly desensitized development pages/)
assert.match(readmeSource, /http:\/\/127\.0\.0\.1:5173\//)
assert.match(readmeSource, /<profile-directory-with-stackprism>/)
assert.match(readmeSource, /use `Default` only if StackPrism is really enabled there/)
assert.match(readmeSource, /Do not capture private or logged-in pages/)
assert.match(readmeSource, /already-redacted screenshot\/recording/)
assert.match(readmeSource, /Do not ask users to create new screenshots of private pages/)
assert.match(readmeSource, /current browser page/)
assert.match(readmeSource, /retry with less data, not partial results/)
assert.match(readmeSource, /Keep the same URL, browser\/profile env, and private-network flag on every retry/)
assert.match(readmeSource, /--max-resource-urls 150/)
assert.match(readmeSource, /--max-resource-urls 50 --no-screenshot/)
assert.match(readmeSource, /only if the user accepts losing screenshot evidence/)
assert.match(readmeSource, /For Firefox E2E, use an exact safe public URL/)
assert.match(readmeSource, /if the URL is missing, ask for one/)
assert.match(readmeSource, /do not choose an arbitrary public page or `example\.com`/)
assert.match(readmeSource, /explicit Firefox profile/)
assert.match(readmeSource, /<firefox-profile-with-stackprism>/)
assert.match(readmeSource, /browserName: "Firefox"/)
assert.match(readmeSource, /evidence manifest outside the repository/)
assert.match(readmeSource, /Never paste or commit `apiToken`/)
assert.match(readmeSource, /shasum -a 256/)
assert.match(readmeSource, /redact `captureId`/)
assert.match(readmeSource, /tests\/stackprism_bridge_py\.test\.mjs/)
assert.match(agentsSource, /repo-local skill/)
assert.match(agentsSource, /JavaScript bridge 优先/)
assert.match(agentsSource, /Python fallback/)
assert.match(agentsSource, /ready JSON/)
})