@friedbotstudio/create-baseline 0.1.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 (197) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +222 -0
  3. package/bin/cli.js +247 -0
  4. package/obj/template/.claude/agents/swarm-worker.md +52 -0
  5. package/obj/template/.claude/bin/LICENSE +201 -0
  6. package/obj/template/.claude/bin/NOTICE +48 -0
  7. package/obj/template/.claude/commands/approve-spec.md +29 -0
  8. package/obj/template/.claude/commands/approve-swarm.md +27 -0
  9. package/obj/template/.claude/commands/grant-commit.md +19 -0
  10. package/obj/template/.claude/commands/init-project.md +191 -0
  11. package/obj/template/.claude/hooks/artifact_template_guard.sh +141 -0
  12. package/obj/template/.claude/hooks/consent_gate_grant.sh +89 -0
  13. package/obj/template/.claude/hooks/destructive_cmd_guard.sh +42 -0
  14. package/obj/template/.claude/hooks/env_guard.sh +36 -0
  15. package/obj/template/.claude/hooks/git_commit_guard.sh +93 -0
  16. package/obj/template/.claude/hooks/harness_continuation.sh +121 -0
  17. package/obj/template/.claude/hooks/lib/__pycache__/resume_writer.cpython-314.pyc +0 -0
  18. package/obj/template/.claude/hooks/lib/common.sh +328 -0
  19. package/obj/template/.claude/hooks/lib/resume_writer.py +341 -0
  20. package/obj/template/.claude/hooks/lint_runner.sh +55 -0
  21. package/obj/template/.claude/hooks/memory_pre_compact.sh +36 -0
  22. package/obj/template/.claude/hooks/memory_session_start.sh +244 -0
  23. package/obj/template/.claude/hooks/memory_stop.sh +173 -0
  24. package/obj/template/.claude/hooks/plantuml_syntax_guard.sh +161 -0
  25. package/obj/template/.claude/hooks/process_lifecycle_guard.sh +89 -0
  26. package/obj/template/.claude/hooks/setup_guard.sh +50 -0
  27. package/obj/template/.claude/hooks/spec_approval_guard.sh +81 -0
  28. package/obj/template/.claude/hooks/spec_design_calls_guard.sh +183 -0
  29. package/obj/template/.claude/hooks/spec_diagram_presence_guard.sh +141 -0
  30. package/obj/template/.claude/hooks/swarm_approval_guard.sh +39 -0
  31. package/obj/template/.claude/hooks/swarm_boundary_guard.sh +136 -0
  32. package/obj/template/.claude/hooks/tdd_order_guard.sh +176 -0
  33. package/obj/template/.claude/hooks/test_runner.sh +75 -0
  34. package/obj/template/.claude/hooks/tests/fixtures/ac008_byte_equal_reference.txt +12 -0
  35. package/obj/template/.claude/hooks/tests/memory_session_start_test.sh +285 -0
  36. package/obj/template/.claude/hooks/track_guard.sh +127 -0
  37. package/obj/template/.claude/hooks/verify_pass_guard.sh +88 -0
  38. package/obj/template/.claude/memory/README.md +108 -0
  39. package/obj/template/.claude/memory/_pending.md +15 -0
  40. package/obj/template/.claude/memory/_resume.md +12 -0
  41. package/obj/template/.claude/memory/conventions.md +26 -0
  42. package/obj/template/.claude/memory/decisions.md +29 -0
  43. package/obj/template/.claude/memory/landmarks.md +26 -0
  44. package/obj/template/.claude/memory/landmines.md +27 -0
  45. package/obj/template/.claude/memory/libraries.md +27 -0
  46. package/obj/template/.claude/memory/pending-questions.md +28 -0
  47. package/obj/template/.claude/project.json +221 -0
  48. package/obj/template/.claude/settings.json +110 -0
  49. package/obj/template/.claude/skills/archive/SKILL.md +48 -0
  50. package/obj/template/.claude/skills/archive/archive.sh +145 -0
  51. package/obj/template/.claude/skills/audit-baseline/SKILL.md +80 -0
  52. package/obj/template/.claude/skills/audit-baseline/audit.sh +919 -0
  53. package/obj/template/.claude/skills/brd/SKILL.md +44 -0
  54. package/obj/template/.claude/skills/brd/template.md +83 -0
  55. package/obj/template/.claude/skills/chore/SKILL.md +99 -0
  56. package/obj/template/.claude/skills/claude-automation-recommender/LICENSE +202 -0
  57. package/obj/template/.claude/skills/claude-automation-recommender/NOTICE +69 -0
  58. package/obj/template/.claude/skills/claude-automation-recommender/SKILL.md +358 -0
  59. package/obj/template/.claude/skills/claude-automation-recommender/references/hooks-patterns.md +226 -0
  60. package/obj/template/.claude/skills/claude-automation-recommender/references/mcp-servers.md +263 -0
  61. package/obj/template/.claude/skills/claude-automation-recommender/references/plugins-reference.md +98 -0
  62. package/obj/template/.claude/skills/claude-automation-recommender/references/skills-reference.md +408 -0
  63. package/obj/template/.claude/skills/claude-automation-recommender/references/subagent-templates.md +181 -0
  64. package/obj/template/.claude/skills/code-structure/SKILL.md +204 -0
  65. package/obj/template/.claude/skills/commit/SKILL.md +21 -0
  66. package/obj/template/.claude/skills/copywriting/SKILL.md +252 -0
  67. package/obj/template/.claude/skills/copywriting/evals/evals.json +111 -0
  68. package/obj/template/.claude/skills/copywriting/references/ai-writing-detection.md +200 -0
  69. package/obj/template/.claude/skills/copywriting/references/copy-frameworks.md +344 -0
  70. package/obj/template/.claude/skills/copywriting/references/natural-transitions.md +272 -0
  71. package/obj/template/.claude/skills/design-ui/SKILL.md +175 -0
  72. package/obj/template/.claude/skills/design-ui/references/design-vs-development.md +89 -0
  73. package/obj/template/.claude/skills/design-ui/references/intent-table.md +64 -0
  74. package/obj/template/.claude/skills/design-ui/references/orchestration.md +121 -0
  75. package/obj/template/.claude/skills/design-ui/references/state-machine.md +125 -0
  76. package/obj/template/.claude/skills/document/SKILL.md +66 -0
  77. package/obj/template/.claude/skills/documentation/SKILL.md +50 -0
  78. package/obj/template/.claude/skills/harness/SKILL.md +169 -0
  79. package/obj/template/.claude/skills/humanizer/SKILL.md +489 -0
  80. package/obj/template/.claude/skills/humanizer/references/ai-writing-detection.md +208 -0
  81. package/obj/template/.claude/skills/impeccable/PROJECT_NOTES.md +22 -0
  82. package/obj/template/.claude/skills/impeccable/SKILL.md +153 -0
  83. package/obj/template/.claude/skills/impeccable/agents/openai.yaml +4 -0
  84. package/obj/template/.claude/skills/impeccable/reference/adapt.md +190 -0
  85. package/obj/template/.claude/skills/impeccable/reference/animate.md +173 -0
  86. package/obj/template/.claude/skills/impeccable/reference/audit.md +134 -0
  87. package/obj/template/.claude/skills/impeccable/reference/bolder.md +113 -0
  88. package/obj/template/.claude/skills/impeccable/reference/brand.md +104 -0
  89. package/obj/template/.claude/skills/impeccable/reference/clarify.md +174 -0
  90. package/obj/template/.claude/skills/impeccable/reference/cognitive-load.md +106 -0
  91. package/obj/template/.claude/skills/impeccable/reference/color-and-contrast.md +105 -0
  92. package/obj/template/.claude/skills/impeccable/reference/colorize.md +154 -0
  93. package/obj/template/.claude/skills/impeccable/reference/craft.md +138 -0
  94. package/obj/template/.claude/skills/impeccable/reference/critique.md +213 -0
  95. package/obj/template/.claude/skills/impeccable/reference/delight.md +302 -0
  96. package/obj/template/.claude/skills/impeccable/reference/distill.md +111 -0
  97. package/obj/template/.claude/skills/impeccable/reference/document.md +427 -0
  98. package/obj/template/.claude/skills/impeccable/reference/extract.md +70 -0
  99. package/obj/template/.claude/skills/impeccable/reference/harden.md +347 -0
  100. package/obj/template/.claude/skills/impeccable/reference/heuristics-scoring.md +234 -0
  101. package/obj/template/.claude/skills/impeccable/reference/interaction-design.md +195 -0
  102. package/obj/template/.claude/skills/impeccable/reference/layout.md +141 -0
  103. package/obj/template/.claude/skills/impeccable/reference/live.md +513 -0
  104. package/obj/template/.claude/skills/impeccable/reference/motion-design.md +99 -0
  105. package/obj/template/.claude/skills/impeccable/reference/onboard.md +234 -0
  106. package/obj/template/.claude/skills/impeccable/reference/optimize.md +258 -0
  107. package/obj/template/.claude/skills/impeccable/reference/overdrive.md +130 -0
  108. package/obj/template/.claude/skills/impeccable/reference/personas.md +178 -0
  109. package/obj/template/.claude/skills/impeccable/reference/polish.md +232 -0
  110. package/obj/template/.claude/skills/impeccable/reference/product.md +62 -0
  111. package/obj/template/.claude/skills/impeccable/reference/quieter.md +99 -0
  112. package/obj/template/.claude/skills/impeccable/reference/responsive-design.md +114 -0
  113. package/obj/template/.claude/skills/impeccable/reference/shape.md +136 -0
  114. package/obj/template/.claude/skills/impeccable/reference/spatial-design.md +100 -0
  115. package/obj/template/.claude/skills/impeccable/reference/teach.md +137 -0
  116. package/obj/template/.claude/skills/impeccable/reference/typeset.md +124 -0
  117. package/obj/template/.claude/skills/impeccable/reference/typography.md +159 -0
  118. package/obj/template/.claude/skills/impeccable/reference/ux-writing.md +107 -0
  119. package/obj/template/.claude/skills/impeccable/scripts/cleanup-deprecated.mjs +284 -0
  120. package/obj/template/.claude/skills/impeccable/scripts/command-metadata.json +94 -0
  121. package/obj/template/.claude/skills/impeccable/scripts/design-parser.mjs +820 -0
  122. package/obj/template/.claude/skills/impeccable/scripts/detect-csp.mjs +198 -0
  123. package/obj/template/.claude/skills/impeccable/scripts/is-generated.mjs +69 -0
  124. package/obj/template/.claude/skills/impeccable/scripts/live-accept.mjs +465 -0
  125. package/obj/template/.claude/skills/impeccable/scripts/live-browser.js +4684 -0
  126. package/obj/template/.claude/skills/impeccable/scripts/live-inject.mjs +436 -0
  127. package/obj/template/.claude/skills/impeccable/scripts/live-poll.mjs +187 -0
  128. package/obj/template/.claude/skills/impeccable/scripts/live-server.mjs +679 -0
  129. package/obj/template/.claude/skills/impeccable/scripts/live-wrap.mjs +395 -0
  130. package/obj/template/.claude/skills/impeccable/scripts/live.mjs +247 -0
  131. package/obj/template/.claude/skills/impeccable/scripts/load-context.mjs +93 -0
  132. package/obj/template/.claude/skills/impeccable/scripts/modern-screenshot.umd.js +14 -0
  133. package/obj/template/.claude/skills/impeccable/scripts/pin.mjs +214 -0
  134. package/obj/template/.claude/skills/implement/SKILL.md +83 -0
  135. package/obj/template/.claude/skills/intake/SKILL.md +46 -0
  136. package/obj/template/.claude/skills/intake/template.md +61 -0
  137. package/obj/template/.claude/skills/integrate/SKILL.md +62 -0
  138. package/obj/template/.claude/skills/memory-flush/SKILL.md +172 -0
  139. package/obj/template/.claude/skills/memory-flush/sweep.py +286 -0
  140. package/obj/template/.claude/skills/memory-flush/tests/run.sh +327 -0
  141. package/obj/template/.claude/skills/prose/SKILL.md +119 -0
  142. package/obj/template/.claude/skills/rca/SKILL.md +42 -0
  143. package/obj/template/.claude/skills/rca/template.md +83 -0
  144. package/obj/template/.claude/skills/research/SKILL.md +75 -0
  145. package/obj/template/.claude/skills/scenario/SKILL.md +64 -0
  146. package/obj/template/.claude/skills/scout/SKILL.md +72 -0
  147. package/obj/template/.claude/skills/security/SKILL.md +75 -0
  148. package/obj/template/.claude/skills/simplify/SKILL.md +67 -0
  149. package/obj/template/.claude/skills/spec/SKILL.md +69 -0
  150. package/obj/template/.claude/skills/spec/template.md +274 -0
  151. package/obj/template/.claude/skills/spec-diagram-review/SKILL.md +81 -0
  152. package/obj/template/.claude/skills/spec-lint/SKILL.md +55 -0
  153. package/obj/template/.claude/skills/spec-lint/lint.sh +218 -0
  154. package/obj/template/.claude/skills/spec-render/SKILL.md +45 -0
  155. package/obj/template/.claude/skills/spec-render/render.sh +109 -0
  156. package/obj/template/.claude/skills/spec-traceability-review/SKILL.md +72 -0
  157. package/obj/template/.claude/skills/swarm-dispatch/SKILL.md +212 -0
  158. package/obj/template/.claude/skills/swarm-dispatch/swarm_merge.sh +154 -0
  159. package/obj/template/.claude/skills/swarm-plan/SKILL.md +90 -0
  160. package/obj/template/.claude/skills/swarm-plan/validate.sh +181 -0
  161. package/obj/template/.claude/skills/tdd/SKILL.md +100 -0
  162. package/obj/template/.claude/skills/technical-tutorials/SKILL.md +569 -0
  163. package/obj/template/.claude/skills/technical-tutorials/references/audience-context-README.md +53 -0
  164. package/obj/template/.claude/skills/technical-tutorials/references/audience-context.md +246 -0
  165. package/obj/template/.claude/skills/technical-tutorials/references/audience-example.md +175 -0
  166. package/obj/template/.claude/skills/technical-tutorials/references/audience-template.md +152 -0
  167. package/obj/template/.claude/skills/triage/SKILL.md +55 -0
  168. package/obj/template/.claude/skills/verify/SKILL.md +74 -0
  169. package/obj/template/.mcp.json +24 -0
  170. package/obj/template/CLAUDE.md +327 -0
  171. package/obj/template/docs/init/seed.md +585 -0
  172. package/obj/template/manifest.json +214 -0
  173. package/package.json +48 -0
  174. package/src/.mcp.template.json +24 -0
  175. package/src/.npmrc.template +2 -0
  176. package/src/CLAUDE.template.md +327 -0
  177. package/src/agents/swarm-worker.template.md +51 -0
  178. package/src/cli/conflict.js +31 -0
  179. package/src/cli/doctor.js +152 -0
  180. package/src/cli/install.js +93 -0
  181. package/src/cli/io.js +27 -0
  182. package/src/cli/manifest.js +38 -0
  183. package/src/cli/mcp.js +54 -0
  184. package/src/cli/merge.js +107 -0
  185. package/src/cli/plantuml.js +121 -0
  186. package/src/cli/util.js +10 -0
  187. package/src/memory/_pending.template.md +15 -0
  188. package/src/memory/_resume.template.md +12 -0
  189. package/src/memory/conventions.template.md +26 -0
  190. package/src/memory/decisions.template.md +29 -0
  191. package/src/memory/landmarks.template.md +26 -0
  192. package/src/memory/landmines.template.md +27 -0
  193. package/src/memory/libraries.template.md +27 -0
  194. package/src/memory/pending-questions.template.md +28 -0
  195. package/src/project.template.json +221 -0
  196. package/src/seed.template.md +585 -0
  197. package/src/settings.template.json +110 -0
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Shared context loader for every impeccable command that needs to know
3
+ * "who is this for" and "what does this look like".
4
+ *
5
+ * Input: project root (process.cwd()).
6
+ *
7
+ * Output (JSON to stdout):
8
+ * {
9
+ * hasProduct: boolean, // PRODUCT.md found (or auto-migrated)
10
+ * product: string | null, // PRODUCT.md contents
11
+ * productPath: string | null, // relative path
12
+ * hasDesign: boolean, // DESIGN.md found
13
+ * design: string | null, // DESIGN.md contents
14
+ * designPath: string | null,
15
+ * migrated: boolean, // true if we auto-renamed .impeccable.md -> PRODUCT.md
16
+ * }
17
+ *
18
+ * Filename matching is case-insensitive for PRODUCT.md and DESIGN.md. The
19
+ * Google DESIGN.md convention is uppercase at repo root; Kiro-style and
20
+ * lowercase variants are also matched so users don't get punished for case.
21
+ */
22
+
23
+ import fs from 'node:fs';
24
+ import path from 'node:path';
25
+
26
+ const PRODUCT_NAMES = ['PRODUCT.md', 'Product.md', 'product.md'];
27
+ const DESIGN_NAMES = ['DESIGN.md', 'Design.md', 'design.md'];
28
+ const LEGACY_NAMES = ['.impeccable.md'];
29
+
30
+ export function loadContext(cwd = process.cwd()) {
31
+ let migrated = false;
32
+
33
+ // 1. Look for PRODUCT.md (case-insensitive)
34
+ let productPath = firstExisting(cwd, PRODUCT_NAMES);
35
+
36
+ // 2. Legacy: if no PRODUCT.md but .impeccable.md exists, rename in place
37
+ if (!productPath) {
38
+ const legacyPath = firstExisting(cwd, LEGACY_NAMES);
39
+ if (legacyPath) {
40
+ const newPath = path.join(cwd, 'PRODUCT.md');
41
+ try {
42
+ fs.renameSync(legacyPath, newPath);
43
+ productPath = newPath;
44
+ migrated = true;
45
+ } catch {
46
+ // Rename failed (permissions, etc.) — fall back to reading legacy in place
47
+ productPath = legacyPath;
48
+ }
49
+ }
50
+ }
51
+
52
+ // 3. DESIGN.md (case-insensitive)
53
+ const designPath = firstExisting(cwd, DESIGN_NAMES);
54
+
55
+ const product = productPath ? safeRead(productPath) : null;
56
+ const design = designPath ? safeRead(designPath) : null;
57
+
58
+ return {
59
+ hasProduct: !!product,
60
+ product,
61
+ productPath: productPath ? path.relative(cwd, productPath) : null,
62
+ hasDesign: !!design,
63
+ design,
64
+ designPath: designPath ? path.relative(cwd, designPath) : null,
65
+ migrated,
66
+ };
67
+ }
68
+
69
+ function firstExisting(cwd, names) {
70
+ for (const name of names) {
71
+ const abs = path.join(cwd, name);
72
+ if (fs.existsSync(abs)) return abs;
73
+ }
74
+ return null;
75
+ }
76
+
77
+ function safeRead(p) {
78
+ try { return fs.readFileSync(p, 'utf-8'); } catch { return null; }
79
+ }
80
+
81
+ // ---------------------------------------------------------------------------
82
+ // CLI mode — print the context as JSON
83
+ // ---------------------------------------------------------------------------
84
+
85
+ function cli() {
86
+ const result = loadContext(process.cwd());
87
+ console.log(JSON.stringify(result, null, 2));
88
+ }
89
+
90
+ const _running = process.argv[1];
91
+ if (_running?.endsWith('load-context.mjs') || _running?.endsWith('load-context.mjs/')) {
92
+ cli();
93
+ }
@@ -0,0 +1,14 @@
1
+ (function(y,v){typeof exports=="object"&&typeof module!="undefined"?v(exports):typeof define=="function"&&define.amd?define(["exports"],v):(y=typeof globalThis!="undefined"?globalThis:y||self,v(y.modernScreenshot={}))})(this,function(y){"use strict";var rr=Object.defineProperty,nr=Object.defineProperties;var or=Object.getOwnPropertyDescriptors;var Z=Object.getOwnPropertySymbols;var xe=Object.prototype.hasOwnProperty,Me=Object.prototype.propertyIsEnumerable;var Oe=Math.pow,Le=(y,v,N)=>v in y?rr(y,v,{enumerable:!0,configurable:!0,writable:!0,value:N}):y[v]=N,D=(y,v)=>{for(var N in v||(v={}))xe.call(v,N)&&Le(y,N,v[N]);if(Z)for(var N of Z(v))Me.call(v,N)&&Le(y,N,v[N]);return y},M=(y,v)=>nr(y,or(v));var je=(y,v)=>{var N={};for(var R in y)xe.call(y,R)&&v.indexOf(R)<0&&(N[R]=y[R]);if(y!=null&&Z)for(var R of Z(y))v.indexOf(R)<0&&Me.call(y,R)&&(N[R]=y[R]);return N};var C=(y,v,N)=>new Promise((R,O)=>{var X=P=>{try{q(N.next(P))}catch(W){O(W)}},j=P=>{try{q(N.throw(P))}catch(W){O(W)}},q=P=>P.done?R(P.value):Promise.resolve(P.value).then(X,j);q((N=N.apply(y,v)).next())});var Be;function v(e,t){return e[13]=1,e[14]=t>>8,e[15]=t&255,e[16]=t>>8,e[17]=t&255,e}const N=112,R=72,O=89,X=115;let j;function q(){const e=new Int32Array(256);for(let t=0;t<256;t++){let r=t;for(let n=0;n<8;n++)r=r&1?3988292384^r>>>1:r>>>1;e[t]=r}return e}function P(e){let t=-1;j||(j=q());for(let r=0;r<e.length;r++)t=j[(t^e[r])&255]^t>>>8;return t^-1}function W(e){const t=e.length-1;for(let r=t;r>=4;r--)if(e[r-4]===9&&e[r-3]===N&&e[r-2]===R&&e[r-1]===O&&e[r]===X)return r-3;return 0}function ae(e,t,r=!1){const n=new Uint8Array(13);t*=39.3701,n[0]=N,n[1]=R,n[2]=O,n[3]=X,n[4]=t>>>24,n[5]=t>>>16,n[6]=t>>>8,n[7]=t&255,n[8]=n[4],n[9]=n[5],n[10]=n[6],n[11]=n[7],n[12]=1;const i=P(n),a=new Uint8Array(4);if(a[0]=i>>>24,a[1]=i>>>16,a[2]=i>>>8,a[3]=i&255,r){const s=W(e);return e.set(n,s),e.set(a,s+13),e}else{const s=new Uint8Array(4);s[0]=0,s[1]=0,s[2]=0,s[3]=9;const o=new Uint8Array(54);return o.set(e,0),o.set(s,33),o.set(n,37),o.set(a,50),o}}const qe="AAlwSFlz",We="AAAJcEhZ",He="AAAACXBI";function Ve(e){let t=e.indexOf(qe);return t===-1&&(t=e.indexOf(We)),t===-1&&(t=e.indexOf(He)),t}const se="[modern-screenshot]",U=typeof window!="undefined",ze=U&&"Worker"in window,ie=U&&"atob"in window,Xe=U&&"btoa"in window,ee=U?(Be=window.navigator)==null?void 0:Be.userAgent:"",le=ee.includes("Chrome"),G=ee.includes("AppleWebKit")&&!le,te=ee.includes("Firefox"),Ge=e=>e&&"__CONTEXT__"in e,Ye=e=>e.constructor.name==="CSSFontFaceRule",Je=e=>e.constructor.name==="CSSImportRule",Ke=e=>e.constructor.name==="CSSLayerBlockRule",I=e=>e.nodeType===1,H=e=>typeof e.className=="object",ce=e=>e.tagName==="image",Qe=e=>e.tagName==="use",V=e=>I(e)&&typeof e.style!="undefined"&&!H(e),Ze=e=>e.nodeType===8,et=e=>e.nodeType===3,$=e=>e.tagName==="IMG",Y=e=>e.tagName==="VIDEO",tt=e=>e.tagName==="CANVAS",rt=e=>e.tagName==="TEXTAREA",nt=e=>e.tagName==="INPUT",ot=e=>e.tagName==="STYLE",at=e=>e.tagName==="SCRIPT",st=e=>e.tagName==="SELECT",it=e=>e.tagName==="SLOT",lt=e=>e.tagName==="IFRAME",ct=(...e)=>console.warn(se,...e);function ut(e){var r;const t=(r=e==null?void 0:e.createElement)==null?void 0:r.call(e,"canvas");return t&&(t.height=t.width=1),!!t&&"toDataURL"in t&&!!t.toDataURL("image/webp").includes("image/webp")}const re=e=>e.startsWith("data:");function ue(e,t){if(e.match(/^[a-z]+:\/\//i))return e;if(U&&e.match(/^\/\//))return window.location.protocol+e;if(e.match(/^[a-z]+:/i)||!U)return e;const r=J().implementation.createHTMLDocument(),n=r.createElement("base"),i=r.createElement("a");return r.head.appendChild(n),r.body.appendChild(i),t&&(n.href=t),i.href=e,i.href}function J(e){var t;return(t=e&&I(e)?e==null?void 0:e.ownerDocument:e)!=null?t:window.document}const K="http://www.w3.org/2000/svg";function fe(e,t,r){const n=J(r).createElementNS(K,"svg");return n.setAttributeNS(null,"width",e.toString()),n.setAttributeNS(null,"height",t.toString()),n.setAttributeNS(null,"viewBox",`0 0 ${e} ${t}`),n}function de(e,t){let r=new XMLSerializer().serializeToString(e);return t&&(r=r.replace(/[\u0000-\u0008\v\f\u000E-\u001F\uD800-\uDFFF\uFFFE\uFFFF]/gu,"")),`data:image/svg+xml;charset=utf-8,${encodeURIComponent(r)}`}function ft(e,t="image/png",r=1){return C(this,null,function*(){try{return yield new Promise((n,i)=>{e.toBlob(a=>{a?n(a):i(new Error("Blob is null"))},t,r)})}catch(n){if(ie)return dt(e.toDataURL(t,r));throw n}})}function dt(e){var o,c;const[t,r]=e.split(","),n=(c=(o=t.match(/data:(.+);/))==null?void 0:o[1])!=null?c:void 0,i=window.atob(r),a=i.length,s=new Uint8Array(a);for(let u=0;u<a;u+=1)s[u]=i.charCodeAt(u);return new Blob([s],{type:n})}function ge(e,t){return new Promise((r,n)=>{const i=new FileReader;i.onload=()=>r(i.result),i.onerror=()=>n(i.error),i.onabort=()=>n(new Error(`Failed read blob to ${t}`)),t==="dataUrl"?i.readAsDataURL(e):t==="arrayBuffer"&&i.readAsArrayBuffer(e)})}const gt=e=>ge(e,"dataUrl"),mt=e=>ge(e,"arrayBuffer");function _(e,t){const r=J(t).createElement("img");return r.decoding="sync",r.loading="eager",r.src=e,r}function L(e,t){return new Promise(r=>{const{timeout:n,ownerDocument:i,onError:a,onWarn:s}=t!=null?t:{},o=typeof e=="string"?_(e,J(i)):e;let c=null,u=null;function l(){r(o),c&&clearTimeout(c),u==null||u()}if(n&&(c=setTimeout(l,n)),Y(o)){const d=o.currentSrc||o.src;if(!d)return o.poster?L(o.poster,t).then(r):l();if(o.readyState>=2)return l();const m=l,f=h=>{s==null||s("Failed video load",d,h),a==null||a(h),l()};u=()=>{o.removeEventListener("loadeddata",m),o.removeEventListener("error",f)},o.addEventListener("loadeddata",m,{once:!0}),o.addEventListener("error",f,{once:!0})}else{const d=ce(o)?o.href.baseVal:o.currentSrc||o.src;if(!d)return l();const m=()=>C(this,null,function*(){if($(o)&&"decode"in o)try{yield o.decode()}catch(h){s==null||s("Failed to decode image, trying to render anyway",o.dataset.originalSrc||d,h)}l()}),f=h=>{s==null||s("Failed image load",o.dataset.originalSrc||d,h),l()};if($(o)&&o.complete)return m();u=()=>{o.removeEventListener("load",m),o.removeEventListener("error",f)},o.addEventListener("load",m,{once:!0}),o.addEventListener("error",f,{once:!0})}})}function me(e,t){return C(this,null,function*(){V(e)&&($(e)||Y(e)?yield L(e,t):yield Promise.all(["img","video"].flatMap(r=>Array.from(e.querySelectorAll(r)).map(n=>L(n,t)))))})}const he=function(){let t=0;const r=()=>`0000${(Math.random()*Oe(36,4)<<0).toString(36)}`.slice(-4);return()=>(t+=1,`u${r()}${t}`)}();function we(e){return e==null?void 0:e.split(",").map(t=>t.trim().replace(/"|'/g,"").toLowerCase()).filter(Boolean)}let pe=0;function ht(e){const t=`${se}[#${pe}]`;return pe++,{time:r=>e&&console.time(`${t} ${r}`),timeEnd:r=>e&&console.timeEnd(`${t} ${r}`),warn:(...r)=>e&&ct(...r)}}function wt(e){return{cache:e?"no-cache":"force-cache"}}function k(e,t){return C(this,null,function*(){return Ge(e)?e:ye(e,M(D({},t),{autoDestruct:!0}))})}function ye(e,t){return C(this,null,function*(){var f,h,g,p,E;const{scale:r=1,workerUrl:n,workerNumber:i=1}=t||{},a=!!(t!=null&&t.debug),s=(f=t==null?void 0:t.features)!=null?f:!0,o=(h=e.ownerDocument)!=null?h:U?window.document:void 0,c=(p=(g=e.ownerDocument)==null?void 0:g.defaultView)!=null?p:U?window:void 0,u=new Map,l=M(D({width:0,height:0,quality:1,type:"image/png",scale:r,backgroundColor:null,style:null,filter:null,maximumCanvasSize:0,timeout:3e4,progress:null,debug:a,fetch:D({requestInit:wt((E=t==null?void 0:t.fetch)==null?void 0:E.bypassingCache),placeholderImage:"data:image/png;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",bypassingCache:!1},t==null?void 0:t.fetch),fetchFn:null,font:{},drawImageInterval:100,workerUrl:null,workerNumber:i,onCloneEachNode:null,onCloneNode:null,onEmbedNode:null,onCreateForeignObjectSvg:null,includeStyleProperties:null,autoDestruct:!1},t),{__CONTEXT__:!0,log:ht(a),node:e,ownerDocument:o,ownerWindow:c,dpi:r===1?null:96*r,svgStyleElement:be(o),svgDefsElement:o==null?void 0:o.createElementNS(K,"defs"),svgStyles:new Map,defaultComputedStyles:new Map,workers:[...Array.from({length:ze&&n&&i?i:0})].map(()=>{try{const b=new Worker(n);return b.onmessage=w=>C(this,null,function*(){var A,F,B,$e;const{url:S,result:T}=w.data;T?(F=(A=u.get(S))==null?void 0:A.resolve)==null||F.call(A,T):($e=(B=u.get(S))==null?void 0:B.reject)==null||$e.call(B,new Error(`Error receiving message from worker: ${S}`))}),b.onmessageerror=w=>{var T,A;const{url:S}=w.data;(A=(T=u.get(S))==null?void 0:T.reject)==null||A.call(T,new Error(`Error receiving message from worker: ${S}`))},b}catch(b){return l.log.warn("Failed to new Worker",b),null}}).filter(Boolean),fontFamilies:new Map,fontCssTexts:new Map,acceptOfImage:`${[ut(o)&&"image/webp","image/svg+xml","image/*","*/*"].filter(Boolean).join(",")};q=0.8`,requests:u,drawImageCount:0,tasks:[],features:s,isEnable:b=>{var w,S;return b==="restoreScrollPosition"?typeof s=="boolean"?!1:(w=s[b])!=null?w:!1:typeof s=="boolean"?s:(S=s[b])!=null?S:!0},shadowRoots:[]});l.log.time("wait until load"),yield me(e,{timeout:l.timeout,onWarn:l.log.warn}),l.log.timeEnd("wait until load");const{width:d,height:m}=pt(e,l);return l.width=d,l.height=m,l})}function be(e){if(!e)return;const t=e.createElement("style"),r=t.ownerDocument.createTextNode(`
2
+ .______background-clip--text {
3
+ background-clip: text;
4
+ -webkit-background-clip: text;
5
+ }
6
+ `);return t.appendChild(r),t}function pt(e,t){let{width:r,height:n}=t;if(I(e)&&(!r||!n)){const i=e.getBoundingClientRect();r=r||i.width||Number(e.getAttribute("width"))||0,n=n||i.height||Number(e.getAttribute("height"))||0}return{width:r,height:n}}function yt(e,t){return C(this,null,function*(){const{log:r,timeout:n,drawImageCount:i,drawImageInterval:a}=t;r.time("image to canvas");const s=yield L(e,{timeout:n,onWarn:t.log.warn}),{canvas:o,context2d:c}=bt(e.ownerDocument,t),u=()=>{try{c==null||c.drawImage(s,0,0,o.width,o.height)}catch(l){t.log.warn("Failed to drawImage",l)}};if(u(),t.isEnable("fixSvgXmlDecode"))for(let l=0;l<i;l++)yield new Promise(d=>{setTimeout(()=>{c==null||c.clearRect(0,0,o.width,o.height),u(),d()},l+a)});return t.drawImageCount=0,r.timeEnd("image to canvas"),o})}function bt(e,t){const{width:r,height:n,scale:i,backgroundColor:a,maximumCanvasSize:s}=t,o=e.createElement("canvas");o.width=Math.floor(r*i),o.height=Math.floor(n*i),o.style.width=`${r}px`,o.style.height=`${n}px`,s&&(o.width>s||o.height>s)&&(o.width>s&&o.height>s?o.width>o.height?(o.height*=s/o.width,o.width=s):(o.width*=s/o.height,o.height=s):o.width>s?(o.height*=s/o.width,o.width=s):(o.width*=s/o.height,o.height=s));const c=o.getContext("2d");return c&&a&&(c.fillStyle=a,c.fillRect(0,0,o.width,o.height)),{canvas:o,context2d:c}}function Se(e,t){if(e.ownerDocument)try{const a=e.toDataURL();if(a!=="data:,")return _(a,e.ownerDocument)}catch(a){t.log.warn("Failed to clone canvas",a)}const r=e.cloneNode(!1),n=e.getContext("2d"),i=r.getContext("2d");try{return n&&i&&i.putImageData(n.getImageData(0,0,e.width,e.height),0,0),r}catch(a){t.log.warn("Failed to clone canvas",a)}return r}function St(e,t){var r;try{if((r=e==null?void 0:e.contentDocument)!=null&&r.documentElement)return ne(e.contentDocument.documentElement,t)}catch(n){t.log.warn("Failed to clone iframe",n)}return e.cloneNode(!1)}function Et(e){const t=e.cloneNode(!1);return e.currentSrc&&e.currentSrc!==e.src&&(t.src=e.currentSrc,t.srcset=""),t.loading==="lazy"&&(t.loading="eager"),t}function Ct(e,t){return C(this,null,function*(){if(e.ownerDocument&&!e.currentSrc&&e.poster)return _(e.poster,e.ownerDocument);const r=e.cloneNode(!1);r.crossOrigin="anonymous",e.currentSrc&&e.currentSrc!==e.src&&(r.src=e.currentSrc);const n=r.ownerDocument;if(n){let i=!0;if(yield L(r,{onError:()=>i=!1,onWarn:t.log.warn}),!i)return e.poster?_(e.poster,e.ownerDocument):r;r.currentTime=e.currentTime,yield new Promise(s=>{r.addEventListener("seeked",s,{once:!0})});const a=n.createElement("canvas");a.width=e.offsetWidth,a.height=e.offsetHeight;try{const s=a.getContext("2d");s&&s.drawImage(r,0,0,a.width,a.height)}catch(s){return t.log.warn("Failed to clone video",s),e.poster?_(e.poster,e.ownerDocument):r}return Se(a,t)}return r})}function Tt(e,t){return tt(e)?Se(e,t):lt(e)?St(e,t):$(e)?Et(e):Y(e)?Ct(e,t):e.cloneNode(!1)}function vt(e){let t=e.sandbox;if(!t){const{ownerDocument:r}=e;try{r&&(t=r.createElement("iframe"),t.id=`__SANDBOX__${he()}`,t.width="0",t.height="0",t.style.visibility="hidden",t.style.position="fixed",r.body.appendChild(t),t.srcdoc='<!DOCTYPE html><meta charset="UTF-8"><title></title><body>',e.sandbox=t)}catch(n){e.log.warn("Failed to getSandBox",n)}}return t}const At=["width","height","-webkit-text-fill-color"],Nt=["stroke","fill"];function Ee(e,t,r){const{defaultComputedStyles:n}=r,i=e.nodeName.toLowerCase(),a=H(e)&&i!=="svg",s=a?Nt.map(g=>[g,e.getAttribute(g)]).filter(([,g])=>g!==null):[],o=[a&&"svg",i,s.map((g,p)=>`${g}=${p}`).join(","),t].filter(Boolean).join(":");if(n.has(o))return n.get(o);const c=vt(r),u=c==null?void 0:c.contentWindow;if(!u)return new Map;const l=u==null?void 0:u.document;let d,m;a?(d=l.createElementNS(K,"svg"),m=d.ownerDocument.createElementNS(d.namespaceURI,i),s.forEach(([g,p])=>{m.setAttributeNS(null,g,p)}),d.appendChild(m)):d=m=l.createElement(i),m.textContent=" ",l.body.appendChild(d);const f=u.getComputedStyle(m,t),h=new Map;for(let g=f.length,p=0;p<g;p++){const E=f.item(p);At.includes(E)||h.set(E,f.getPropertyValue(E))}return l.body.removeChild(d),n.set(o,h),h}function Ce(e,t,r){var o;const n=new Map,i=[],a=new Map;if(r)for(const c of r)s(c);else for(let c=e.length,u=0;u<c;u++){const l=e.item(u);s(l)}for(let c=i.length,u=0;u<c;u++)(o=a.get(i[u]))==null||o.forEach((l,d)=>n.set(d,l));function s(c){const u=e.getPropertyValue(c),l=e.getPropertyPriority(c),d=c.lastIndexOf("-"),m=d>-1?c.substring(0,d):void 0;if(m){let f=a.get(m);f||(f=new Map,a.set(m,f)),f.set(c,[u,l])}t.get(c)===u&&!l||(m?i.push(m):n.set(c,[u,l]))}return n}function Rt(e,t,r,n){var d,m,f,h;const{ownerWindow:i,includeStyleProperties:a,currentParentNodeStyle:s}=n,o=t.style,c=i.getComputedStyle(e),u=Ee(e,null,n);s==null||s.forEach((g,p)=>{u.delete(p)});const l=Ce(c,u,a);l.delete("transition-property"),l.delete("all"),l.delete("d"),l.delete("content"),r&&(l.delete("position"),l.delete("margin-top"),l.delete("margin-right"),l.delete("margin-bottom"),l.delete("margin-left"),l.delete("margin-block-start"),l.delete("margin-block-end"),l.delete("margin-inline-start"),l.delete("margin-inline-end"),l.set("box-sizing",["border-box",""])),((d=l.get("background-clip"))==null?void 0:d[0])==="text"&&t.classList.add("______background-clip--text"),le&&(l.has("font-kerning")||l.set("font-kerning",["normal",""]),(((m=l.get("overflow-x"))==null?void 0:m[0])==="hidden"||((f=l.get("overflow-y"))==null?void 0:f[0])==="hidden")&&((h=l.get("text-overflow"))==null?void 0:h[0])==="ellipsis"&&e.scrollWidth===e.clientWidth&&l.set("text-overflow",["clip",""]));for(let g=o.length,p=0;p<g;p++)o.removeProperty(o.item(p));return l.forEach(([g,p],E)=>{o.setProperty(E,g,p)}),l}function It(e,t){(rt(e)||nt(e)||st(e))&&t.setAttribute("value",e.value)}const kt=["::before","::after"],Dt=["::-webkit-scrollbar","::-webkit-scrollbar-button","::-webkit-scrollbar-thumb","::-webkit-scrollbar-track","::-webkit-scrollbar-track-piece","::-webkit-scrollbar-corner","::-webkit-resizer"];function Pt(e,t,r,n,i){const{ownerWindow:a,svgStyleElement:s,svgStyles:o,currentNodeStyle:c}=n;if(!s||!a)return;function u(l){var w;const d=a.getComputedStyle(e,l);let m=d.getPropertyValue("content");if(!m||m==="none")return;i==null||i(m),m=m.replace(/(')|(")|(counter\(.+\))/g,"");const f=[he()],h=Ee(e,l,n);c==null||c.forEach((S,T)=>{h.delete(T)});const g=Ce(d,h,n.includeStyleProperties);g.delete("content"),g.delete("-webkit-locale"),((w=g.get("background-clip"))==null?void 0:w[0])==="text"&&t.classList.add("______background-clip--text");const p=[`content: '${m}';`];if(g.forEach(([S,T],A)=>{p.push(`${A}: ${S}${T?" !important":""};`)}),p.length===1)return;try{t.className=[t.className,...f].join(" ")}catch(S){n.log.warn("Failed to copyPseudoClass",S);return}const E=p.join(`
7
+ `);let b=o.get(E);b||(b=[],o.set(E,b)),b.push(`.${f[0]}${l}`)}kt.forEach(u),r&&Dt.forEach(u)}const Te=new Set(["symbol"]);function ve(e,t,r,n,i){return C(this,null,function*(){if(I(r)&&(ot(r)||at(r))||n.filter&&!n.filter(r))return;Te.has(t.nodeName)||Te.has(r.nodeName)?n.currentParentNodeStyle=void 0:n.currentParentNodeStyle=n.currentNodeStyle;const a=yield ne(r,n,!1,i);n.isEnable("restoreScrollPosition")&&Ut(e,a),t.appendChild(a)})}function Ae(e,t,r,n){return C(this,null,function*(){var a;let i=e.firstChild;I(e)&&e.shadowRoot&&(i=(a=e.shadowRoot)==null?void 0:a.firstChild,r.shadowRoots.push(e.shadowRoot));for(let s=i;s;s=s.nextSibling)if(!Ze(s))if(I(s)&&it(s)&&typeof s.assignedNodes=="function"){const o=s.assignedNodes();for(let c=0;c<o.length;c++)yield ve(e,t,o[c],r,n)}else yield ve(e,t,s,r,n)})}function Ut(e,t){if(!V(e)||!V(t))return;const{scrollTop:r,scrollLeft:n}=e;if(!r&&!n)return;const{transform:i}=t.style,a=new DOMMatrix(i),{a:s,b:o,c,d:u}=a;a.a=1,a.b=0,a.c=0,a.d=1,a.translateSelf(-n,-r),a.a=s,a.b=o,a.c=c,a.d=u,t.style.transform=a.toString()}function _t(e,t){const{backgroundColor:r,width:n,height:i,style:a}=t,s=e.style;if(r&&s.setProperty("background-color",r,"important"),n&&s.setProperty("width",`${n}px`,"important"),i&&s.setProperty("height",`${i}px`,"important"),a)for(const o in a)s[o]=a[o]}const Ft=/^[\w-:]+$/;function ne(e,t,r=!1,n){return C(this,null,function*(){var u,l,d,m;const{ownerDocument:i,ownerWindow:a,fontFamilies:s,onCloneEachNode:o}=t;if(i&&et(e))return n&&/\S/.test(e.data)&&n(e.data),i.createTextNode(e.data);if(i&&a&&I(e)&&(V(e)||H(e))){const f=yield Tt(e,t);if(t.isEnable("removeAbnormalAttributes")){const w=f.getAttributeNames();for(let S=w.length,T=0;T<S;T++){const A=w[T];Ft.test(A)||f.removeAttribute(A)}}const h=t.currentNodeStyle=Rt(e,f,r,t);r&&_t(f,t);let g=!1;if(t.isEnable("copyScrollbar")){const w=[(u=h.get("overflow-x"))==null?void 0:u[0],(l=h.get("overflow-y"))==null?void 0:l[0]];g=w.includes("scroll")||(w.includes("auto")||w.includes("overlay"))&&(e.scrollHeight>e.clientHeight||e.scrollWidth>e.clientWidth)}const p=(d=h.get("text-transform"))==null?void 0:d[0],E=we((m=h.get("font-family"))==null?void 0:m[0]),b=E?w=>{p==="uppercase"?w=w.toUpperCase():p==="lowercase"?w=w.toLowerCase():p==="capitalize"&&(w=w[0].toUpperCase()+w.substring(1)),E.forEach(S=>{let T=s.get(S);T||s.set(S,T=new Set),w.split("").forEach(A=>T.add(A))})}:void 0;return Pt(e,f,g,t,b),It(e,f),Y(e)||(yield Ae(e,f,t,b)),yield o==null?void 0:o(f),f}const c=e.cloneNode(!1);return yield Ae(e,c,t),yield o==null?void 0:o(c),c})}function Ne(e){if(e.ownerDocument=void 0,e.ownerWindow=void 0,e.svgStyleElement=void 0,e.svgDefsElement=void 0,e.svgStyles.clear(),e.defaultComputedStyles.clear(),e.sandbox){try{e.sandbox.remove()}catch(t){e.log.warn("Failed to destroyContext",t)}e.sandbox=void 0}e.workers=[],e.fontFamilies.clear(),e.fontCssTexts.clear(),e.requests.clear(),e.tasks=[],e.shadowRoots=[]}function Bt(e){const o=e,{url:t,timeout:r,responseType:n}=o,i=je(o,["url","timeout","responseType"]),a=new AbortController,s=r?setTimeout(()=>a.abort(),r):void 0;return fetch(t,D({signal:a.signal},i)).then(c=>{if(!c.ok)throw new Error("Failed fetch, not 2xx response",{cause:c});switch(n){case"arrayBuffer":return c.arrayBuffer();case"dataUrl":return c.blob().then(gt);case"text":default:return c.text()}}).finally(()=>clearTimeout(s))}function z(e,t){const{url:r,requestType:n="text",responseType:i="text",imageDom:a}=t;let s=r;const{timeout:o,acceptOfImage:c,requests:u,fetchFn:l,fetch:{requestInit:d,bypassingCache:m,placeholderImage:f},font:h,workers:g,fontFamilies:p}=e;n==="image"&&(G||te)&&e.drawImageCount++;let E=u.get(r);if(!E){m&&m instanceof RegExp&&m.test(s)&&(s+=(/\?/.test(s)?"&":"?")+new Date().getTime());const b=n.startsWith("font")&&h&&h.minify,w=new Set;b&&n.split(";")[1].split(",").forEach(F=>{p.has(F)&&p.get(F).forEach(B=>w.add(B))});const S=b&&w.size,T=D({url:s,timeout:o,responseType:S?"arrayBuffer":i,headers:n==="image"?{accept:c}:void 0},d);E={type:n,resolve:void 0,reject:void 0,response:null},E.response=C(this,null,function*(){if(l&&n==="image"){const A=yield l(r);if(A)return A}return!G&&r.startsWith("http")&&g.length?new Promise((A,F)=>{g[u.size&g.length-1].postMessage(D({rawUrl:r},T)),E.resolve=A,E.reject=F}):Bt(T)}).catch(A=>{if(u.delete(r),n==="image"&&f)return e.log.warn("Failed to fetch image base64, trying to use placeholder image",s),typeof f=="string"?f:f(a);throw A}),u.set(r,E)}return E.response}function Re(e,t,r,n){return C(this,null,function*(){if(!Ie(e))return e;for(const[i,a]of $t(e,t))try{const s=yield z(r,{url:a,requestType:n?"image":"text",responseType:"dataUrl"});e=e.replace(Lt(i),`$1${s}$3`)}catch(s){r.log.warn("Failed to fetch css data url",i,s)}return e})}function Ie(e){return/url\((['"]?)([^'"]+?)\1\)/.test(e)}const ke=/url\((['"]?)([^'"]+?)\1\)/g;function $t(e,t){const r=[];return e.replace(ke,(n,i,a)=>(r.push([a,ue(a,t)]),n)),r.filter(([n])=>!re(n))}function Lt(e){const t=e.replace(/([.*+?^${}()|\[\]\/\\])/g,"\\$1");return new RegExp(`(url\\(['"]?)(${t})(['"]?\\))`,"g")}const xt=["background-image","border-image-source","-webkit-border-image","-webkit-mask-image","list-style-image"];function Mt(e,t){return xt.map(r=>{const n=e.getPropertyValue(r);return!n||n==="none"?null:((G||te)&&t.drawImageCount++,Re(n,null,t,!0).then(i=>{!i||n===i||e.setProperty(r,i,e.getPropertyPriority(r))}))}).filter(Boolean)}function Ot(e,t){if($(e)){const r=e.currentSrc||e.src;if(!re(r))return[z(t,{url:r,imageDom:e,requestType:"image",responseType:"dataUrl"}).then(n=>{n&&(e.srcset="",e.dataset.originalSrc=r,e.src=n||"")})];(G||te)&&t.drawImageCount++}else if(H(e)&&!re(e.href.baseVal)){const r=e.href.baseVal;return[z(t,{url:r,imageDom:e,requestType:"image",responseType:"dataUrl"}).then(n=>{n&&(e.dataset.originalSrc=r,e.href.baseVal=n||"")})]}return[]}function jt(e,t){var o;const{ownerDocument:r,svgDefsElement:n}=t,i=(o=e.getAttribute("href"))!=null?o:e.getAttribute("xlink:href");if(!i)return[];const[a,s]=i.split("#");if(s){const c=`#${s}`,u=t.shadowRoots.reduce((l,d)=>l!=null?l:d.querySelector(`svg ${c}`),r==null?void 0:r.querySelector(`svg ${c}`));if(a&&e.setAttribute("href",c),n!=null&&n.querySelector(c))return[];if(u)return n==null||n.appendChild(u.cloneNode(!0)),[];if(a)return[z(t,{url:a,responseType:"text"}).then(l=>{n==null||n.insertAdjacentHTML("beforeend",l)})]}return[]}function De(e,t){const{tasks:r}=t;I(e)&&(($(e)||ce(e))&&r.push(...Ot(e,t)),Qe(e)&&r.push(...jt(e,t))),V(e)&&r.push(...Mt(e.style,t)),e.childNodes.forEach(n=>{De(n,t)})}function qt(e,t){return C(this,null,function*(){const{ownerDocument:r,svgStyleElement:n,fontFamilies:i,fontCssTexts:a,tasks:s,font:o}=t;if(!(!r||!n||!i.size))if(o&&o.cssText){const c=Ue(o.cssText,t);n.appendChild(r.createTextNode(`${c}
8
+ `))}else{const c=Array.from(r.styleSheets).filter(f=>{try{return"cssRules"in f&&!!f.cssRules.length}catch(h){return t.log.warn(`Error while reading CSS rules from ${f.href}`,h),!1}}),u=r.implementation.createHTMLDocument(""),l=u.createElement("style");u.head.appendChild(l);const d=l.sheet;yield Promise.all(c.flatMap(f=>Array.from(f.cssRules).map(h=>C(this,null,function*(){if(Je(h)){const g=h.href;let p="";try{p=yield z(t,{url:g,requestType:"text",responseType:"text"})}catch(b){t.log.warn(`Error fetch remote css import from ${g}`,b)}const E=p.replace(ke,(b,w,S)=>b.replace(S,ue(S,g)));for(const b of Ht(E))try{d.insertRule(b,d.cssRules.length)}catch(w){t.log.warn("Error inserting rule from remote css import",{rule:b,error:w})}}})))),d.cssRules.length&&c.push(d);const m=[];c.forEach(f=>{oe(f.cssRules,m)}),m.filter(f=>{var h;return Ye(f)&&Ie(f.style.getPropertyValue("src"))&&((h=we(f.style.getPropertyValue("font-family")))==null?void 0:h.some(g=>i.has(g)))}).forEach(f=>{const h=f,g=a.get(h.cssText);g?n.appendChild(r.createTextNode(`${g}
9
+ `)):s.push(Re(h.cssText,h.parentStyleSheet?h.parentStyleSheet.href:null,t).then(p=>{p=Ue(p,t),a.set(h.cssText,p),n.appendChild(r.createTextNode(`${p}
10
+ `))}))})}})}const Wt=/(\/\*[\s\S]*?\*\/)/g,Pe=/((@.*?keyframes [\s\S]*?){([\s\S]*?}\s*?)})/gi;function Ht(e){if(e==null)return[];const t=[];let r=e.replace(Wt,"");for(;;){const a=Pe.exec(r);if(!a)break;t.push(a[0])}r=r.replace(Pe,"");const n=/@import[\s\S]*?url\([^)]*\)[\s\S]*?;/gi,i=new RegExp("((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})","gi");for(;;){let a=n.exec(r);if(a)i.lastIndex=n.lastIndex;else if(a=i.exec(r),a)n.lastIndex=i.lastIndex;else break;t.push(a[0])}return t}const Vt=/url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g,zt=/src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;function Ue(e,t){const{font:r}=t,n=r?r==null?void 0:r.preferredFormat:void 0;return n?e.replace(zt,i=>{for(;;){const[a,,s]=Vt.exec(i)||[];if(!s)return"";if(s===n)return`src: ${a};`}}):e}function oe(e,t=[]){for(const r of Array.from(e))Ke(r)?t.push(...oe(r.cssRules)):"cssRules"in r?oe(r.cssRules,t):t.push(r);return t}const Xt=/\bx?link:?href\s*=\s*["'](?!data:)[^"']+["']/i;function Gt(e){return Xt.test(e.innerHTML)}function _e(e,t){return C(this,null,function*(){const r=yield k(e,t);if(I(r.node)&&H(r.node)&&!Gt(r.node))return r.node;const{ownerDocument:n,log:i,tasks:a,svgStyleElement:s,svgDefsElement:o,svgStyles:c,font:u,progress:l,autoDestruct:d,onCloneNode:m,onEmbedNode:f,onCreateForeignObjectSvg:h}=r;i.time("clone node");const g=yield ne(r.node,r,!0);if(s&&n){let S="";c.forEach((T,A)=>{S+=`${T.join(`,
11
+ `)} {
12
+ ${A}
13
+ }
14
+ `}),s.appendChild(n.createTextNode(S))}i.timeEnd("clone node"),yield m==null?void 0:m(g),u!==!1&&I(g)&&(i.time("embed web font"),yield qt(g,r),i.timeEnd("embed web font")),i.time("embed node"),De(g,r);const p=a.length;let E=0;const b=()=>C(this,null,function*(){for(;;){const S=a.pop();if(!S)break;try{yield S}catch(T){r.log.warn("Failed to run task",T)}l==null||l(++E,p)}});l==null||l(E,p),yield Promise.all([...Array.from({length:4})].map(b)),i.timeEnd("embed node"),yield f==null?void 0:f(g);const w=Yt(g,r);return o&&w.insertBefore(o,w.children[0]),s&&w.insertBefore(s,w.children[0]),d&&Ne(r),yield h==null?void 0:h(w),w})}function Yt(e,t){const{width:r,height:n}=t,i=fe(r,n,e.ownerDocument),a=i.ownerDocument.createElementNS(i.namespaceURI,"foreignObject");return a.setAttributeNS(null,"x","0%"),a.setAttributeNS(null,"y","0%"),a.setAttributeNS(null,"width","100%"),a.setAttributeNS(null,"height","100%"),a.append(e),i.appendChild(a),i}function Q(e,t){return C(this,null,function*(){var s;const r=yield k(e,t),n=yield _e(r),i=de(n,r.isEnable("removeControlCharacter"));r.autoDestruct||(r.svgStyleElement=be(r.ownerDocument),r.svgDefsElement=(s=r.ownerDocument)==null?void 0:s.createElementNS(K,"defs"),r.svgStyles.clear());const a=_(i,n.ownerDocument);return yield yt(a,r)})}function Jt(e,t){return C(this,null,function*(){const r=yield k(e,t),{log:n,type:i,quality:a,dpi:s}=r,o=yield Q(r);n.time("canvas to blob");const c=yield ft(o,i,a);if(["image/png","image/jpeg"].includes(i)&&s){const u=yield mt(c.slice(0,33));let l=new Uint8Array(u);return i==="image/png"?l=ae(l,s):i==="image/jpeg"&&(l=v(l,s)),n.timeEnd("canvas to blob"),new Blob([l,c.slice(33)],{type:i})}return n.timeEnd("canvas to blob"),c})}function x(e,t){return C(this,null,function*(){const r=yield k(e,t),{log:n,quality:i,type:a,dpi:s}=r,o=yield Q(r);n.time("canvas to data url");let c=o.toDataURL(a,i);if(["image/png","image/jpeg"].includes(a)&&s&&ie&&Xe){const[u,l]=c.split(",");let d=0,m=!1;if(a==="image/png"){const w=Ve(l);w>=0?(d=Math.ceil((w+28)/3)*4,m=!0):d=33/3*4}else a==="image/jpeg"&&(d=18/3*4);const f=l.substring(0,d),h=l.substring(d),g=window.atob(f),p=new Uint8Array(g.length);for(let w=0;w<p.length;w++)p[w]=g.charCodeAt(w);const E=a==="image/png"?ae(p,s,m):v(p,s),b=window.btoa(String.fromCharCode(...E));c=[u,",",b,h].join("")}return n.timeEnd("canvas to data url"),c})}function Fe(e,t){return C(this,null,function*(){const r=yield k(e,t),{width:n,height:i,ownerDocument:a}=r,s=yield x(r),o=fe(n,i,a),c=o.ownerDocument.createElementNS(o.namespaceURI,"image");return c.setAttributeNS(null,"href",s),c.setAttributeNS(null,"height","100%"),c.setAttributeNS(null,"width","100%"),o.appendChild(c),de(o,r.isEnable("removeControlCharacter"))})}function Kt(e,t){return C(this,null,function*(){const r=yield k(e,t),{ownerDocument:n,width:i,height:a,scale:s,type:o}=r,c=o==="image/svg+xml"?yield Fe(r):yield x(r),u=_(c,n);return u.width=Math.floor(i*s),u.height=Math.floor(a*s),u.style.width=`${i}px`,u.style.height=`${a}px`,u})}function Qt(e,t){return C(this,null,function*(){return x(yield k(e,M(D({},t),{type:"image/jpeg"})))})}function Zt(e,t){return C(this,null,function*(){const r=yield k(e,t),n=yield Q(r);return n.getContext("2d").getImageData(0,0,n.width,n.height).data})}function er(e,t){return C(this,null,function*(){return x(yield k(e,M(D({},t),{type:"image/png"})))})}function tr(e,t){return C(this,null,function*(){return x(yield k(e,M(D({},t),{type:"image/webp"})))})}y.createContext=ye,y.destroyContext=Ne,y.domToBlob=Jt,y.domToCanvas=Q,y.domToDataUrl=x,y.domToForeignObjectSvg=_e,y.domToImage=Kt,y.domToJpeg=Qt,y.domToPixel=Zt,y.domToPng=er,y.domToSvg=Fe,y.domToWebp=tr,y.loadMedia=L,y.waitUntilLoad=me,Object.defineProperty(y,Symbol.toStringTag,{value:"Module"})});
@@ -0,0 +1,214 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Pin/unpin sub-commands as standalone skill shortcuts.
4
+ *
5
+ * Usage:
6
+ * node <scripts_path>/pin.mjs pin <command>
7
+ * node <scripts_path>/pin.mjs unpin <command>
8
+ *
9
+ * `pin audit` creates a lightweight /audit skill that redirects to /impeccable audit.
10
+ * `unpin audit` removes that shortcut.
11
+ *
12
+ * The script discovers harness directories (.claude/skills, .cursor/skills, etc.)
13
+ * in the project root and creates/removes the pin in all of them.
14
+ */
15
+
16
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync, readdirSync } from 'node:fs';
17
+ import { join, resolve, dirname } from 'node:path';
18
+ import { fileURLToPath } from 'node:url';
19
+
20
+ const __dirname = dirname(fileURLToPath(import.meta.url));
21
+
22
+ // All known harness directories
23
+ const HARNESS_DIRS = [
24
+ '.claude', '.cursor', '.gemini', '.codex', '.agents',
25
+ '.trae', '.trae-cn', '.pi', '.opencode', '.kiro', '.rovodev',
26
+ ];
27
+
28
+ // Valid sub-command names
29
+ const VALID_COMMANDS = [
30
+ 'craft', 'teach', 'extract', 'document', 'shape',
31
+ 'critique', 'audit',
32
+ 'polish', 'bolder', 'quieter', 'distill', 'harden', 'onboard', 'live',
33
+ 'animate', 'colorize', 'typeset', 'layout', 'delight', 'overdrive',
34
+ 'clarify', 'adapt', 'optimize',
35
+ ];
36
+
37
+ // Marker to identify pinned skills (so unpin doesn't delete user skills)
38
+ const PIN_MARKER = '<!-- impeccable-pinned-skill -->';
39
+
40
+ /**
41
+ * Walk up from startDir to find a project root.
42
+ */
43
+ function findProjectRoot(startDir = process.cwd()) {
44
+ let dir = resolve(startDir);
45
+ while (dir !== '/') {
46
+ if (
47
+ existsSync(join(dir, 'package.json')) ||
48
+ existsSync(join(dir, '.git')) ||
49
+ existsSync(join(dir, 'skills-lock.json'))
50
+ ) {
51
+ return dir;
52
+ }
53
+ const parent = resolve(dir, '..');
54
+ if (parent === dir) break;
55
+ dir = parent;
56
+ }
57
+ return resolve(startDir);
58
+ }
59
+
60
+ /**
61
+ * Find harness skill directories that have an impeccable skill installed.
62
+ */
63
+ function findHarnessDirs(projectRoot) {
64
+ const dirs = [];
65
+ for (const harness of HARNESS_DIRS) {
66
+ const skillsDir = join(projectRoot, harness, 'skills');
67
+ // Only pin in harness dirs that already have impeccable installed
68
+ const impeccableDir = join(skillsDir, 'impeccable');
69
+ if (existsSync(impeccableDir) || existsSync(join(skillsDir, 'i-impeccable'))) {
70
+ dirs.push(skillsDir);
71
+ }
72
+ }
73
+ return dirs;
74
+ }
75
+
76
+ /**
77
+ * Load command metadata (descriptions for pinned skills).
78
+ */
79
+ function loadCommandMetadata() {
80
+ const metadataPath = join(__dirname, 'command-metadata.json');
81
+ if (existsSync(metadataPath)) {
82
+ return JSON.parse(readFileSync(metadataPath, 'utf-8'));
83
+ }
84
+ return {};
85
+ }
86
+
87
+ /**
88
+ * Generate a pinned skill's SKILL.md content.
89
+ */
90
+ function generatePinnedSkill(command, metadata) {
91
+ const desc = metadata[command]?.description || `Shortcut for /impeccable ${command}.`;
92
+ const hint = metadata[command]?.argumentHint || '[target]';
93
+
94
+ return `---
95
+ name: ${command}
96
+ description: "${desc}"
97
+ argument-hint: "${hint}"
98
+ user-invocable: true
99
+ ---
100
+
101
+ ${PIN_MARKER}
102
+
103
+ This is a pinned shortcut for \`{{command_prefix}}impeccable ${command}\`.
104
+
105
+ Invoke {{command_prefix}}impeccable ${command}, passing along any arguments provided here, and follow its instructions.
106
+ `;
107
+ }
108
+
109
+ /**
110
+ * Pin a command: create shortcut skill in all harness dirs.
111
+ */
112
+ function pin(command, projectRoot) {
113
+ const metadata = loadCommandMetadata();
114
+ const harnessDirs = findHarnessDirs(projectRoot);
115
+
116
+ if (harnessDirs.length === 0) {
117
+ console.log('No harness directories with impeccable installed found.');
118
+ return false;
119
+ }
120
+
121
+ const content = generatePinnedSkill(command, metadata);
122
+ let created = 0;
123
+
124
+ for (const skillsDir of harnessDirs) {
125
+ // Check if skill already exists (and isn't a pin)
126
+ const skillDir = join(skillsDir, command);
127
+ if (existsSync(skillDir)) {
128
+ const existingMd = join(skillDir, 'SKILL.md');
129
+ if (existsSync(existingMd)) {
130
+ const existing = readFileSync(existingMd, 'utf-8');
131
+ if (!existing.includes(PIN_MARKER)) {
132
+ console.log(` SKIP: ${skillDir} (non-pinned skill already exists)`);
133
+ continue;
134
+ }
135
+ }
136
+ }
137
+
138
+ mkdirSync(skillDir, { recursive: true });
139
+ writeFileSync(join(skillDir, 'SKILL.md'), content, 'utf-8');
140
+ console.log(` + ${skillDir}`);
141
+ created++;
142
+ }
143
+
144
+ if (created > 0) {
145
+ console.log(`\nPinned '${command}' as a standalone shortcut in ${created} location(s).`);
146
+ console.log(`You can now use /${command} directly.`);
147
+ }
148
+
149
+ return created > 0;
150
+ }
151
+
152
+ /**
153
+ * Unpin a command: remove shortcut skill from all harness dirs.
154
+ */
155
+ function unpin(command, projectRoot) {
156
+ const harnessDirs = findHarnessDirs(projectRoot);
157
+ let removed = 0;
158
+
159
+ for (const skillsDir of harnessDirs) {
160
+ const skillDir = join(skillsDir, command);
161
+ if (!existsSync(skillDir)) continue;
162
+
163
+ const skillMd = join(skillDir, 'SKILL.md');
164
+ if (!existsSync(skillMd)) continue;
165
+
166
+ // Safety: only remove if it's a pinned skill
167
+ const content = readFileSync(skillMd, 'utf-8');
168
+ if (!content.includes(PIN_MARKER)) {
169
+ console.log(` SKIP: ${skillDir} (not a pinned skill)`);
170
+ continue;
171
+ }
172
+
173
+ rmSync(skillDir, { recursive: true, force: true });
174
+ console.log(` - ${skillDir}`);
175
+ removed++;
176
+ }
177
+
178
+ if (removed > 0) {
179
+ console.log(`\nUnpinned '${command}' from ${removed} location(s).`);
180
+ console.log(`Use /impeccable ${command} to access it.`);
181
+ } else {
182
+ console.log(`No pinned '${command}' shortcut found.`);
183
+ }
184
+
185
+ return removed > 0;
186
+ }
187
+
188
+ // --- CLI ---
189
+ const [,, action, command] = process.argv;
190
+
191
+ if (!action || !command) {
192
+ console.log('Usage: node pin.mjs <pin|unpin> <command>');
193
+ console.log(`\nAvailable commands: ${VALID_COMMANDS.join(', ')}`);
194
+ process.exit(1);
195
+ }
196
+
197
+ if (action !== 'pin' && action !== 'unpin') {
198
+ console.error(`Unknown action: ${action}. Use 'pin' or 'unpin'.`);
199
+ process.exit(1);
200
+ }
201
+
202
+ if (!VALID_COMMANDS.includes(command)) {
203
+ console.error(`Unknown command: ${command}`);
204
+ console.error(`Available commands: ${VALID_COMMANDS.join(', ')}`);
205
+ process.exit(1);
206
+ }
207
+
208
+ const root = findProjectRoot();
209
+
210
+ if (action === 'pin') {
211
+ pin(command, root);
212
+ } else {
213
+ unpin(command, root);
214
+ }
@@ -0,0 +1,83 @@
1
+ ---
2
+ name: implement
3
+ owner: baseline
4
+ description: Write the production code that makes a pre-decided set of failing tests pass, within an explicit write_set, following an explicit behavior contract. Used by `/tdd` Step 3 and by `/swarm-dispatch` workers. The caller has already decided architecture, naming, file layout, and abstraction boundaries — this skill executes that recipe with code-structure discipline and a 5-iteration RALPH loop. No scope expansion, no design decisions, no test edits.
5
+ ---
6
+
7
+ You are executing a **decision the main context has already made**: "make these failing tests pass by writing code in these files." You are not the architect. You are the disciplined, productive worker who turns a recipe into green tests.
8
+
9
+ # Mandatory first step
10
+
11
+ Invoke `Skill(code-structure)` before writing or modifying any file. Apply its layer model and abstraction rules to every file. Do not paraphrase its rules — apply them.
12
+
13
+ # Inputs the caller must provide
14
+
15
+ If any are missing, **stop and ask** — do not infer architecture or scope.
16
+
17
+ - **Failing test paths**: the exact test files (and ideally test names) that must turn green.
18
+ - **Write set**: the exact list of source file paths you are permitted to write or modify. Anything outside this list is forbidden.
19
+ - **Behavior contract**: a precise description of what the code under test must do. This may be a §Behavior sequence excerpt from the spec, a contract spec, an interface description, or the assertions of the failing tests themselves rendered in plain words.
20
+ - **Project conventions**: from `.claude/project.json` — `test.cmd`, `lint.cmd`, language-specific tooling.
21
+ - **Optional but useful**: scout report excerpts, naming/style anchors, the chosen library + version (caller resolves this from the research memo).
22
+
23
+ # Library APIs
24
+
25
+ For any third-party library API you use, hit the `context7` MCP first:
26
+ 1. `mcp__plugin_context7_context7__resolve-library-id`
27
+ 2. `mcp__plugin_context7_context7__query-docs`
28
+
29
+ Never recall an API from training data. Record `<library>@<version> — <api names>` in your final report.
30
+
31
+ # Method (RALPH loop, capped at 5 iterations)
32
+
33
+ 1. **Read the failing tests in full.** Note exact assertions, fixtures, mocks, expected exceptions. If a test mocks an internal module, the database, or a gRPC channel, stop and surface — those are seed.md violations and you do not silently honor them.
34
+ 2. **Read the behavior contract.** Cross-reference it against test assertions. Mismatches are caller decisions; surface as Open question, do not improvise.
35
+ 3. **Read existing code in the write set and immediate neighbors.** Match style, reuse helpers, follow naming. Reuse-before-create is `code-structure`'s rule, not a suggestion.
36
+ 4. **Run the failing tests once.** Confirm they fail, and that they fail for the right reason (`AssertionError` is the right reason; `ImportError` because the module doesn't exist yet is also right; `SyntaxError` in a fixture is the wrong reason — surface it).
37
+ 5. **Implement the minimum code that makes the failing tests pass.** Apply `code-structure` rules to every file. For any third-party API, hit `context7` first. Write only inside the write set.
38
+ 6. **Run the tests again.**
39
+ - **Green** → proceed to step 7.
40
+ - **Red** → read the failure, adjust the implementation (not the tests), loop back to step 5.
41
+ - **Cap at 5 iterations.** Iteration 5 ends and is still red? Stop, return `BLOCKED`.
42
+ 7. **Final pass.** Run `lint.cmd` if configured; address findings inside the write set only. Re-run tests once more.
43
+
44
+ # Output (inline report)
45
+
46
+ ```
47
+ # Implement — <slug or task id>
48
+
49
+ ## Verdict
50
+ GREEN | RED | BLOCKED
51
+
52
+ ## Files touched
53
+ - <path> — <one-line summary>
54
+
55
+ ## Tests run
56
+ - Command: <test cmd>
57
+ - Last result: <green | failures: N>
58
+
59
+ ## Library APIs cited (context7-confirmed)
60
+ - <library>@<version> — <api names>
61
+
62
+ ## RALPH iterations used
63
+ <N> of 5
64
+
65
+ ## Notes / blockers
66
+ - <anything the caller needs to know>
67
+
68
+ ## Open questions for the caller
69
+ - <ambiguity that prevented progress>
70
+ ```
71
+
72
+ # Constraints (non-negotiables from seed.md)
73
+
74
+ - **No stubs.** Every declared function fully implemented.
75
+ - **No `TODO` / `FIXME` / `HACK` / `XXX`.** Do it now or do not write the code.
76
+ - **No commented-out code.** Delete what's removed.
77
+ - **No mocks of internal modules, the database, or gRPC.** Acceptable mock targets only: third-party HTTP that can't run locally, system clock, OS randomness — each marked `# MOCK: <reason>`.
78
+ - **YAGNI.** No "future use" parameters, flags, or abstractions. Abstract on the third concrete use case.
79
+ - **Match the write set exactly.** A file outside it is a violation. If you genuinely need one, stop and surface — do not silently expand scope. (In `swarm-dispatch` worktree mode, the merge audit will reject the change anyway.)
80
+ - **Never modify tests.** If a test seems wrong, surface it under Open questions. The `scenario` skill's territory, not yours.
81
+ - **Never approve specs or write to `docs/specs/`.**
82
+ - **Never run `git commit` or `git push`.** Commits happen in `/commit`.
83
+ - **If you cap out at 5 RALPH iterations**, return `BLOCKED` honestly. Don't fake green.
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: intake
3
+ owner: baseline
4
+ description: Draft a Workflow Phase 1 intake document capturing a new request — the problem, the desired outcome, constraints, and testable acceptance criteria. Use when a user brings a new feature, change, or investigation that doesn't yet have a spec. The output lives at `docs/intake/<slug>.md` and feeds `/scout`, `/research`, and `/spec` downstream.
5
+ ---
6
+
7
+ # Intake — Workflow Phase 1
8
+
9
+ You are drafting an **intake document** — the earliest structured artifact in the workflow. Its job is to compress a conversation into a single file downstream phases can trust.
10
+
11
+ ## Prerequisite
12
+
13
+ `.claude/state/workflow.json` exists (written by `/triage`) with `entry_phase` either `intake` or a later phase that lists `intake` in `exceptions`. If neither is true, stop and instruct the user to run `/triage` first.
14
+
15
+ ## Inputs
16
+
17
+ - The user's request (in plain English, usually the first thing they said after triage).
18
+ - The `template.md` file next to this SKILL.md — the canonical structure to produce.
19
+
20
+ ## Steps
21
+
22
+ 1. Verify the prerequisite above.
23
+ 2. Read `template.md` in this skill directory. Use it as the skeleton of the output — every heading must survive into the final document.
24
+ 3. **Never write a section with placeholder text, "TBD", or fabricate content the user didn't state.** Either:
25
+ - Ask the user a targeted question per section before writing it, OR
26
+ - Leave the section empty except for a single bullet under **## Open questions** listing what you still need.
27
+ 4. Derive the slug from the first non-trivial noun phrase in the request. Use kebab-case, lowercase, ≤ 40 chars. Example: "add retry to webhook worker" → `webhook-worker-retry`.
28
+ 5. Write the populated intake to `docs/intake/<slug>.md`.
29
+ 6. Append `"intake"` to `.claude/state/workflow.json` → `completed` and update `updated_at` (current epoch).
30
+ 7. Tell the user: "Intake captured at `docs/intake/<slug>.md`. Open questions: N. Next: `/scout`." If the request is cross-functional or spans multiple systems, also suggest `/brd` before `/scout`.
31
+
32
+ ## Drafting rules
33
+
34
+ - **Acceptance criteria must be testable.** A criterion that starts with "users should find it easy to…" is not testable — rewrite it as "given X, when user does Y, system does Z." If you cannot restate it testably, put it in **Open questions**.
35
+ - **Non-goals are not optional.** Every intake names at least one explicit non-goal. If the user says "everything is in scope," push back: the lack of non-goals is how scope creep starts.
36
+ - **Stakeholders must be concrete.** "Product", "Engineering", "Design" are roles. Name the specific person or team on the hook for each.
37
+ - **No stubs, no TODOs** (seed.md § Always Production Code). Unknown content goes in **Open questions**, not as placeholder prose.
38
+ - **Do not self-approve**; intake does not need approval in this workflow, but don't add "Status: Approved" lines — that's a spec-only concept and the spec_approval_guard will block it.
39
+
40
+ ## What downstream phases expect
41
+
42
+ - `/scout` reads **Problem** and **Goal** to scope the codebase search.
43
+ - `/research` reads **Constraints** and **Acceptance criteria** to filter candidate solutions.
44
+ - `/spec` reads **Non-goals** to avoid re-expanding scope, and **Acceptance criteria** as the seed for the spec's own AC section.
45
+
46
+ Write for those downstream readers, not for the user re-reading it in isolation.
@@ -0,0 +1,61 @@
1
+ # <one-line title — the request as a sentence>
2
+
3
+ <!--
4
+ Intake document. Produced by the `intake` skill.
5
+ Required sections (enforced by artifact_template_guard): Problem, Goal, Acceptance criteria.
6
+ -->
7
+
8
+ ## Problem
9
+
10
+ <What is broken, missing, or unacceptable today? Who experiences it? When?
11
+ Include the smallest concrete scenario a reader can picture. Avoid abstractions
12
+ like "improve performance" — say "P95 of /api/orders is 2.3s, target is <500ms".>
13
+
14
+ ## Goal
15
+
16
+ <One sentence. The outcome, in the user's or business's terms, not the
17
+ implementation's. "Webhook retries succeed without manual intervention" —
18
+ not "add exponential backoff to worker loop".>
19
+
20
+ ## Non-goals
21
+
22
+ <At least one. What are we explicitly NOT doing? This is the primary scope-
23
+ creep defence.>
24
+
25
+ - <non-goal 1>
26
+ - <non-goal 2>
27
+
28
+ ## Success metrics
29
+
30
+ <How will we know this worked? Prefer numbers over adjectives.>
31
+
32
+ - <metric> — baseline: <current>, target: <new>, measured via: <source>
33
+
34
+ ## Stakeholders
35
+
36
+ <Named people or teams on the hook, not roles.>
37
+
38
+ - **Requester**: <name>
39
+ - **Reviewer**: <name>
40
+ - **Operator** (who runs it in prod): <name>
41
+
42
+ ## Constraints
43
+
44
+ <Things that narrow the solution space. Technical (must run on existing infra),
45
+ regulatory (PII handling), timeline (ship by X), or human (team on vacation).>
46
+
47
+ - <constraint>
48
+
49
+ ## Acceptance criteria
50
+
51
+ <Numbered, testable. Each criterion should translate to at least one test.>
52
+
53
+ 1. <given X, when Y, then Z>
54
+ 2. <given X, when Y, then Z>
55
+
56
+ ## Open questions
57
+
58
+ <Questions the intake could not resolve. These block the next phase until
59
+ answered.>
60
+
61
+ - <question>
@@ -0,0 +1,62 @@
1
+ ---
2
+ name: integrate
3
+ owner: baseline
4
+ description: Workflow Phase 9 — Integration and Verification. Runs the full test suite, stamps the binding verdict at .claude/state/last_test_result, optionally runs a cross-engine smoke check, and writes harness_state so the harness auto-continues or yields. No subagent delegation.
5
+ ---
6
+
7
+ # Prereq
8
+
9
+ `simplify` in `completed` AND (`security` in `completed` OR `security` in `exceptions`).
10
+
11
+ # Steps
12
+
13
+ 1. **Verify prereq.** Read `.claude/state/workflow.json` and confirm.
14
+
15
+ 2. **Run the binding test command and stamp the verdict (inlined verify).** This used to be a `verify` skill invocation; the four mechanical operations are inlined here per `.claude/skills/verify/SKILL.md` (the contract doc). In order:
16
+ - Read `.claude/project.json` → `test.cmd`. If absent or empty, the verdict is `FAIL` with reason "project.json not configured" and step 2 stops with that verdict.
17
+ - Run the command via Bash from the project root. Capture stdout, stderr, and exit code. Do not retry. Do not pass `{file}` placeholders — integrate always runs the full suite.
18
+ - Apply verdict rules: `PASS` iff exit code 0 AND at least one test executed AND no failed/errored test; otherwise `FAIL`. A timeout is FAIL. A killed process is FAIL.
19
+ - Atomically write `.claude/state/last_test_result` with exactly four lines plus a single trailing newline:
20
+ ```
21
+ <PASS|FAIL>
22
+ <ISO-8601 UTC timestamp>
23
+ <exact command>
24
+ <exit code>
25
+ ```
26
+ The `verify_pass_guard` hook reads line 1 as the binding verdict.
27
+ - Emit the human-readable inline report (Verdict, Command, Exit code, Output tail) alongside the statefile write.
28
+
29
+ 3. **Read line 1 of `.claude/state/last_test_result`.**
30
+ - **PASS** → continue to step 4.
31
+ - **FAIL** → stop. Do **not** proceed to documentation or commit. Surface the verdict's reason and the output tail to the user. Write `harness_state` per step 5 with `state: "yielded"` and `reason: "integrate failed: <one-line summary>; needs user decision"`. Together with the user, decide whether to loop back to `/tdd` (mechanical bug) or escalate to a spec change.
32
+
33
+ 4. **Cross-engine smoke (optional, fires only if applicable).** Run this step only if **all** of the following hold:
34
+ - `playwright` is declared in `.mcp.json` (check before invoking — never hallucinate the tool).
35
+ - The project has a frontend surface (a `package.json` with a dev/start script, or `docs/site/`, or a similar live-rendered target).
36
+ - The diff under review touched at least one file that affects the rendered UI (anything under `src/`, `app/`, `pages/`, `components/`, `docs/site/`, or styles/templates referenced from those).
37
+
38
+ When all three hold:
39
+ - Start the dev server in a background Bash with a known port.
40
+ - For each engine in `chromium`, `webkit`, `firefox` (skip engines outside the project's declared browser-support floor):
41
+ - `mcp__playwright__browser_navigate` to the project's primary surfaces (home, plus any route the diff touched).
42
+ - `mcp__playwright__browser_snapshot` for the accessibility tree; check for unexpected `[disabled]` / `[hidden]` regressions vs the prior snapshot if one exists at `docs/site/_visual/<slug>/<engine>.snapshot.json`.
43
+ - `mcp__playwright__browser_screenshot` per primary surface; save to `docs/site/_visual/<slug>/<engine>-<route>.png`.
44
+ - Surface any console errors, 4xx/5xx network responses, or accessibility-tree diffs as **integrate findings** — these don't block the verify verdict but the user must triage before `/commit`.
45
+ - Stop the dev server.
46
+
47
+ Skip silently if any of the three conditions don't hold. Don't surface a "no playwright" warning on every run — backend-only repos shouldn't see noise.
48
+
49
+ 5. **Marker op FIRST, then write harness_state.** Append `"integrate"` to `workflow.json → completed`. Then:
50
+ - On `state: "continue"` (more phases remain): `echo "<slug>" > .claude/state/.harness_active` to refresh the active marker, then write `.claude/state/harness_state` with `{state: "continue", slug, reason}`. The next pending non-excepted phase fires on the same turn via the Stop hook.
51
+ - On `state: "yielded"` (line 1 of `last_test_result` was FAIL — handled in step 3): `rm -f .claude/state/.harness_active`, then write `harness_state` with `{state: "yielded", slug, reason}`.
52
+ The state file carries exactly three keys; no `written_at`, no `tick_count`.
53
+ Tell the user: "Tests green<.|, with cross-engine smoke clean / N findings to triage>. Next: `/document`."
54
+
55
+ # Constraints
56
+
57
+ - **Always run the full suite at this phase** — not affected-tests-only. The inlined verify operations run the full project test.cmd.
58
+ - **Always preserve the four-line `last_test_result` byte format.** The `verify_pass_guard` hook depends on it.
59
+ - **Do not modify code here.** If integrate fails, the fix happens in `/tdd` (bug) or via a spec change (design).
60
+ - **Cross-engine smoke is opt-in via `.mcp.json` presence.** Do not install playwright as a side effect of running this skill; the user (or `/init-project`) controls whether playwright is declared.
61
+ - **Cross-engine findings are advisory.** They surface to the user; they do not flip the verify verdict from PASS to FAIL.
62
+ - **Always write `harness_state` before the terminal message.** The Stop hook reads it to drive auto-continuation; integrate's terminal message ends the turn.