@hiver/skills 1.0.1 → 1.0.2

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 (35) hide show
  1. package/collections/extension/agents/build-feature.md +41 -0
  2. package/collections/extension/agents/build-milestone.md +62 -0
  3. package/collections/extension/skills/build-backbone-component/SKILL.md +100 -0
  4. package/collections/extension/skills/build-backbone-component/references/backbone-scaffolds.md +162 -0
  5. package/collections/extension/skills/build-backbone-component/references/react-mount-path.md +93 -0
  6. package/collections/extension/skills/build-component/SKILL.md +33 -0
  7. package/collections/extension/skills/build-component/palette/README.md +3 -0
  8. package/collections/extension/skills/build-component/palette/colors.md +87 -0
  9. package/collections/extension/skills/build-component/references/best-practices.md +8 -0
  10. package/collections/extension/skills/build-component/references/component-organization.md +21 -0
  11. package/collections/extension/skills/build-component/references/figma-integration.md +5 -0
  12. package/collections/extension/skills/build-component/references/icons.md +8 -0
  13. package/collections/extension/skills/build-component/references/layout-and-structure.md +8 -0
  14. package/collections/extension/skills/build-component/references/state-management.md +25 -0
  15. package/collections/extension/skills/build-component/references/ui-kit-and-styling.md +13 -0
  16. package/collections/extension/skills/build-component/typography/README.md +3 -0
  17. package/collections/extension/skills/build-component/typography/variants.md +79 -0
  18. package/collections/extension/skills/ci-cd/SKILL.md +67 -0
  19. package/collections/extension/skills/ci-cd/references/bundle-and-troubleshooting.md +50 -0
  20. package/collections/extension/skills/ci-cd/references/file-registry.md +28 -0
  21. package/collections/extension/skills/connect-api/SKILL.md +23 -0
  22. package/collections/extension/skills/connect-api/references/api-call-structure.md +84 -0
  23. package/collections/extension/skills/connect-api/references/best-practices.md +10 -0
  24. package/collections/extension/skills/connect-api/references/data-fetchers.md +52 -0
  25. package/collections/extension/skills/connect-api/references/error-handling.md +34 -0
  26. package/collections/extension/skills/connect-api/references/hook-organization.md +11 -0
  27. package/collections/extension/skills/connect-api/references/query-keys.md +21 -0
  28. package/collections/extension/skills/connect-api/references/react-query-usage.md +83 -0
  29. package/collections/extension/skills/connect-api/references/url-placeholders.md +17 -0
  30. package/collections/extension/skills/modify-extension/SKILL.md +110 -0
  31. package/collections/extension/skills/modify-extension/references/architecture.md +55 -0
  32. package/collections/extension/skills/modify-extension/references/implementation-patterns.md +180 -0
  33. package/collections/extension/skills/scaffold-react-feature/SKILL.md +141 -0
  34. package/collections/extension/skills/write-test-cases/SKILL.md +93 -0
  35. package/package.json +1 -1
@@ -0,0 +1,110 @@
1
+ ---
2
+ name: modify-extension
3
+ description: Full command over Chrome extension top-level code in hiver-extension-v3/. Use when adding new features, modifying the script injection pipeline, fixing load sequence bugs, adding service worker commands, new iframes, new context menus, or any other change scoped to the extension layer.
4
+ ---
5
+
6
+ # Build Extension V3
7
+
8
+ **Scope:** All code inside `hiver-extension-v3/` — manifest, service worker, content scripts, iframes, context menus, env config, and `src/` files.
9
+
10
+ **Out of scope:** The React app bundles (`gx_combined.js`, `gx_react_combined.js`, `index.js`) that get injected into Gmail. Those are built from a separate part of the codebase. This skill only owns the extension layer that loads and injects those bundles.
11
+
12
+ **Never touch `chrome_extension_dev/`** — it is auto-generated from `hiver-extension-v3/` during local dev builds. All changes go into `hiver-extension-v3/` only.
13
+
14
+ ---
15
+
16
+ ## Step 1 — Understand the Task
17
+
18
+ Read the task and classify it:
19
+
20
+ | Task type | Primary files involved |
21
+ |---|---|
22
+ | New service worker message command | `service_worker.js` |
23
+ | New context menu item | `ContextMenu.js`, `service_worker.js` |
24
+ | New iframe | `content_scripts/iframes.js`, `manifest.json`, new `src/iframe_*.html` |
25
+ | New content script | `manifest.json`, new file in `content_scripts/` |
26
+ | Modify script injection pipeline | `service_worker.js`, `grexit.js` |
27
+ | Fix load sequence bug | `grexit.js`, `content_scripts/gmail.js`, `content_scripts/utils.js` |
28
+ | New manifest permission or resource | `manifest.json` |
29
+ | Env-specific behavior | `env.js`, `service_worker.js` |
30
+
31
+ ---
32
+
33
+ ## Step 2 — Write Plain English Test Cases (TDD)
34
+
35
+ Before writing any code, write explicit test cases:
36
+
37
+ ```
38
+ TEST: [short name]
39
+ GIVEN: [precondition / starting state]
40
+ WHEN: [event or action that occurs]
41
+ THEN: [expected outcome]
42
+ ```
43
+
44
+ Then trace through the existing code and confirm each test currently fails. Implement. Then trace through updated code and confirm each test now passes.
45
+
46
+ ---
47
+
48
+ ## Step 3 — Read the Relevant Files
49
+
50
+ Always read the files you will touch before editing.
51
+
52
+ ## Reference files
53
+
54
+ **Load lazily — only read a reference file when you are about to perform that specific task. Do NOT read all files upfront.**
55
+
56
+ | Topic | File | When to load |
57
+ |-------|------|--------------|
58
+ | Architecture (file roles, injection pipeline, env behavior) | [references/architecture.md](references/architecture.md) | When you need to understand file relationships or the boot sequence |
59
+ | Implementation patterns (service worker, context menu, iframe, content script, manifest, env-gating, logging) | [references/implementation-patterns.md](references/implementation-patterns.md) | When writing code for a specific task type |
60
+
61
+ ---
62
+
63
+ ## Step 4 — Check if Chrome APIs or Patterns Are Unfamiliar
64
+
65
+ If the task requires a Chrome extension API that does not already exist in the codebase, **do not guess**. Use WebSearch:
66
+
67
+ ```
68
+ search: "chrome extension manifest v3 <topic> site:developer.chrome.com"
69
+ ```
70
+
71
+ Always prefer the Chrome Developers documentation over general web search results. Reconcile with how the existing codebase handles similar things.
72
+
73
+ ---
74
+
75
+ ## Step 5 — Implement
76
+
77
+ Load the relevant reference file for the task type and follow the pattern.
78
+
79
+ ---
80
+
81
+ ## Step 6 — Verify Test Cases
82
+
83
+ After implementing, trace through each test case from Step 2:
84
+ - Identify the exact code path that satisfies the `THEN` condition
85
+ - If any test still fails, fix before closing the task
86
+
87
+ ---
88
+
89
+ ## Hard Rules — Never Violate
90
+
91
+ 1. **Script load order in manifest is fixed** — `hiver-logger.js` → (performanceLogger, utils, gmail, iframes) → `grexit.js`. Wrong order = silent runtime failure.
92
+ 2. **No import/export in content scripts** — Only `service_worker.js` and files it imports are ES modules.
93
+ 3. **Always return true for async message handlers** — If `sendResponse` is called inside `.then()` or after `await`, the `case` block must `return true`.
94
+ 4. **New DOM manipulation needs trusted types** — Route through `src/trusted-type-policy.js`.
95
+ 5. **Use reloadUntil for critical boot failures** — Add entry to `reloadKeys` with unique key and `maxCount: 5`.
96
+ 6. **Log all significant pipeline stages** — New boot steps must call `postMessageToLogger` on both success and failure.
97
+
98
+ ---
99
+
100
+ ## Checklist
101
+
102
+ - [ ] Relevant files read before editing
103
+ - [ ] Plain English test cases written before implementation
104
+ - [ ] Implementation follows the correct pattern for the task type
105
+ - [ ] Script load order in `manifest.json` is correct (if manifest was changed)
106
+ - [ ] `return true` present for any new async message handler
107
+ - [ ] New files under `src/` are covered by `web_accessible_resources`
108
+ - [ ] New chrome API usage has corresponding permission in manifest
109
+ - [ ] Env-gating done correctly (not using `import` in content scripts)
110
+ - [ ] Each test case traced through updated code and confirmed passing
@@ -0,0 +1,55 @@
1
+ # Extension Architecture Reference
2
+
3
+ ## File Roles and Module Types
4
+
5
+ | File | Role | Module type |
6
+ |---|---|---|
7
+ | `manifest.json` | Permissions, content script order, web_accessible_resources | — |
8
+ | `service_worker.js` | Message hub, script/CSS injection, update lifecycle | **ES module** |
9
+ | `grexit.js` | Gmail boot orchestrator — runs the full load sequence | **NOT a module** (uses globals) |
10
+ | `hiver-logger.js` | Constants + `HiverLogger` class — must load before `grexit.js` | **NOT a module** |
11
+ | `customClasses.js` | `CustomFetchError` | ES module (imported by `service_worker.js`) |
12
+ | `ContextMenu.js` | Context menu creation + click handling | ES module (imported by `service_worker.js`) |
13
+ | `env.js` | Production env: `HIVER_V2_HOST`, `HIVER_SELECTORS_API_URL`, `APP_ENV = 'production'` | ES module |
14
+ | `env.dev.js` | Dev env overrides (same exports, different values) | ES module |
15
+ | `content_scripts/utils.js` | `autoRetry`, `waitUntil`, `reloadUntil`, `getDebugEnabled` | Global |
16
+ | `content_scripts/gmail.js` | `waitForGmailToLoadNew`, `waitForGmailInitialization` | Global |
17
+ | `content_scripts/iframes.js` | `injectExtensionIframes` — injects 7 iframes | Global |
18
+ | `content_scripts/flowTracer.js` | Flow tracing (runs in MAIN world at document_start) | Global |
19
+ | `content_scripts/performanceLogger.js` | Performance logging helpers | Global |
20
+ | `src/selectors.js` | Resolves Gmail DOM selectors from `localStorage('selectors')` | Injected via `chrome.scripting` |
21
+ | `src/trusted-type-policy.js` | CSP Trusted Types policy setup | Injected via `chrome.scripting` |
22
+ | `src/iframe_*.html` | Individual iframe pages (editor, chat, analytics, gainsight, video, loggly) | Standalone |
23
+ | `src/iframe_*_handler.js` | Handlers loaded inside each iframe | Global (in iframe context) |
24
+
25
+ ## Script Injection Pipeline
26
+
27
+ ```
28
+ grexit.js boots in Gmail tab
29
+
30
+ ├─ [1] injectTrustedTypePolicy()
31
+ │ → sends "injectTrustedTypePolicy" → service_worker executes src/trusted-type-policy.js
32
+
33
+ ├─ [2] autoRetry(setupExtensionMetaDataGlobals)
34
+ │ → sends "setupExtensionMetaDataGlobals" → service_worker injects version/id globals
35
+
36
+ ├─ [3] initializeHiverExtension() [IIFE]
37
+ │ → sends "fetchSelectorsAndApplicationVersions"
38
+ │ → service_worker fetches in parallel:
39
+ │ gmailSelectors API → stored in localStorage('selectors')
40
+ │ runtimeBundleVersion API → extensionUiVersion, channelsUiVersion, featureFlags
41
+
42
+ ├─ [4] → sends "injectHiverSelectorScript" → service_worker executes src/selectors.js
43
+
44
+ ├─ [5] → sends "injectAppScripts" → service_worker executes:
45
+ │ gx_combined.js + gx_react_combined.js + index.js
46
+
47
+ └─ [6] injectExtensionIframes() → 7 hidden iframes injected into Gmail DOM
48
+ ```
49
+
50
+ ## Environment Behavior
51
+
52
+ | `APP_ENV` | Script paths | CSS injection | Update checks |
53
+ |---|---|---|---|
54
+ | `'production'` | Fetched from `runtimeBundleVersion` API | No | Yes |
55
+ | anything else | `build/latest/*.js` (local) | Yes (`insertAppCSSOnBuddyEnvironment`) | No |
@@ -0,0 +1,180 @@
1
+ # Extension Implementation Patterns
2
+
3
+ ## Adding a new service worker message command
4
+
5
+ Add a case inside the `onMessage` switch in `service_worker.js`:
6
+
7
+ ```js
8
+ // async command — must return true
9
+ case 'myNewCommand_1':
10
+ myAsyncOperation(request.someArg).then(sendResponse);
11
+ return true; // required — keeps the message port open until sendResponse fires
12
+
13
+ // sync command
14
+ case 'myNewCommand_2':
15
+ sendResponse(someValue);
16
+ break;
17
+ ```
18
+
19
+ Send from a content script:
20
+ ```js
21
+ chrome.runtime.sendMessage({ command: 'myNewCommand_1', someArg: value }, ({ success, data, error }) => {
22
+ if (!success) { /* handle error */ }
23
+ // use data
24
+ });
25
+ ```
26
+
27
+ ---
28
+
29
+ ## Adding a new context menu item
30
+
31
+ In `ContextMenu.js`, add inside `createContextMenu()`:
32
+ ```js
33
+ chrome.contextMenus.create({
34
+ id: 'myNewItem',
35
+ title: 'My New Action',
36
+ contexts: ['page'],
37
+ documentUrlPatterns: ['*://mail.google.com/*']
38
+ });
39
+ ```
40
+
41
+ Add a handler function:
42
+ ```js
43
+ const handleMyNewItem = async (tabId) => {
44
+ try {
45
+ chrome.tabs.sendMessage(tabId, {
46
+ type: 'CONTEXT_MENU_WORKER_EVENT',
47
+ payload: { type: 'MY_NEW_ACTION' }
48
+ });
49
+ } catch (err) {
50
+ console.log('== FAILED TO HANDLE MY_NEW_ACTION ==', err);
51
+ }
52
+ };
53
+ ```
54
+
55
+ Wire it in `handleContextMenuClick`:
56
+ ```js
57
+ if (info.menuItemId === 'myNewItem') {
58
+ await handleMyNewItem(tab.id);
59
+ }
60
+ ```
61
+
62
+ ---
63
+
64
+ ## Adding a new iframe
65
+
66
+ In `content_scripts/iframes.js`, add inside `injectExtensionIframes()` following the existing pattern:
67
+ ```js
68
+ const iframe_myfeature_id = 'Hiver_iframe_myfeature';
69
+ let iframe_myfeature = doc.getElementById(iframe_myfeature_id);
70
+ if (!iframe_myfeature) {
71
+ injectIframe({
72
+ id: iframe_myfeature_id,
73
+ src: chrome.runtime.getURL('src/iframe_myfeature.html'),
74
+ style: 'display:none;border:none;',
75
+ body
76
+ });
77
+ }
78
+ ```
79
+
80
+ Then create `src/iframe_myfeature.html`. The existing `"src/*"` wildcard in `web_accessible_resources` already covers it — verify it does before adding a new entry.
81
+
82
+ ---
83
+
84
+ ## Adding a new content script (shared globals)
85
+
86
+ Create the file in `content_scripts/`. Add it to `manifest.json` at the **correct position** in the `js` array:
87
+
88
+ ```json
89
+ "js": [
90
+ "hiver-logger.js",
91
+ "src/trusted-type-policy.js",
92
+ "content_scripts/performanceLogger.js",
93
+ "content_scripts/utils.js",
94
+ "content_scripts/gmail.js",
95
+ "content_scripts/iframes.js",
96
+ "content_scripts/myNewScript.js",
97
+ "grexit.js"
98
+ ]
99
+ ```
100
+
101
+ Rules:
102
+ - If your script defines globals that other scripts consume → place it **before** those scripts
103
+ - If your script uses globals from `hiver-logger.js` → place it **after** `hiver-logger.js`
104
+ - `grexit.js` is always **last**
105
+ - Do **not** use `import`/`export` — content scripts are not ES modules
106
+
107
+ ---
108
+
109
+ ## Adding a file injected via chrome.scripting
110
+
111
+ Create the file in `src/`. Inject it from `service_worker.js`:
112
+ ```js
113
+ function executeScripts(tabId, files, executionWorld = 'MAIN') {
114
+ return chrome.scripting.executeScript({ target: { tabId }, files, world: executionWorld });
115
+ }
116
+
117
+ // usage
118
+ executeScripts(tabId, ['src/myfile.js']); // runs in MAIN world by default
119
+ ```
120
+
121
+ Check `web_accessible_resources` in `manifest.json`. The existing wildcard `"src/*"` covers any new file under `src/`.
122
+
123
+ ---
124
+
125
+ ## Adding a new manifest permission
126
+
127
+ ```json
128
+ "permissions": ["scripting", "contextMenus", "myNewPermission"]
129
+ ```
130
+
131
+ For host permissions:
132
+ ```json
133
+ "host_permissions": ["*://mail.google.com/*", "*://mynewhost.com/*"]
134
+ ```
135
+
136
+ ---
137
+
138
+ ## Env-gating new behavior
139
+
140
+ In `service_worker.js` (ES module — `APP_ENV` is importable):
141
+ ```js
142
+ import { APP_ENV } from './env.js';
143
+
144
+ if (APP_ENV !== 'production') {
145
+ // dev-only behavior
146
+ }
147
+ ```
148
+
149
+ In content scripts (`APP_ENV` is not importable). Pass it through a service worker message response or inject it as a global via `executeFunction`:
150
+ ```js
151
+ function setMyEnvGlobal(appEnv) {
152
+ window.MY_APP_ENV = appEnv;
153
+ }
154
+ // in service_worker.js handler:
155
+ executeFunction({ tabId, functionToExecute: setMyEnvGlobal, args: [APP_ENV] });
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Adding a new log stage in the boot sequence
161
+
162
+ ```js
163
+ const currentStage = 'myNewStage';
164
+ const { duration, stageDuration } = getStageDetails(currentStage);
165
+ postMessageToLogger({
166
+ message: 'Description of what happened',
167
+ stage: currentStage,
168
+ duration,
169
+ stageDuration,
170
+ level: LOG_LEVELS.DEBUG, // or LOG_LEVELS.ERROR
171
+ });
172
+ ```
173
+
174
+ For failures, add a `LOG_MESSAGES` constant in `hiver-logger.js`:
175
+ ```js
176
+ const LOG_MESSAGES = {
177
+ // existing...
178
+ MY_NEW_FAILURE: 'My new thing failed to initialize',
179
+ };
180
+ ```
@@ -0,0 +1,141 @@
1
+ ---
2
+ name: scaffold-react-feature
3
+ description: Generate standard feature folder structure, wiring, and feature flag boilerplate for new features. Internal skill — used by build-milestone agent, not invoked directly by users.
4
+ ---
5
+
6
+ # Scaffold Feature
7
+
8
+ **Trigger:** Only when building a **new feature or new component**. Do NOT use for bug fixes or issue fixes.
9
+
10
+ **Used by:** `build-milestone` agent internally. Not invoked directly by users.
11
+
12
+ ---
13
+
14
+ ## Step 1 — Determine Mount Type
15
+
16
+ Ask (or infer from agent context / milestone doc):
17
+
18
+ > **Is this feature mounted via Backbone or pure React?**
19
+
20
+ - **Backbone mount** → the feature is rendered inside a Backbone view using `ReactBackboneModules`
21
+ - **React-only** → the feature is lazy-imported and rendered directly in `react-extn/src/index.js`
22
+
23
+ ---
24
+
25
+ ## Step 2 — Create Folder Structure
26
+
27
+ Create the following under `react-extn/src/<FeatureName>/`:
28
+
29
+ ```
30
+ <FeatureName>/
31
+ index.js ← main React component export
32
+ hooks/ ← custom hooks (data, state, business logic)
33
+ constants/
34
+ queries.js ← React Query query/mutation keys
35
+ index.js ← other constants (strings, enums, config)
36
+ components/ ← sub-components
37
+ utils.js ← pure utility functions
38
+ mounter.js ← ONLY if Backbone-mounted (see Step 3a)
39
+ ```
40
+
41
+ ---
42
+
43
+ ## Step 3a — Backbone Mount Wiring
44
+
45
+ ### Create `mounter.js`
46
+
47
+ ```js
48
+ import ReactDOM from 'react-dom/client';
49
+ import { HiverProvider } from '@hiver/hiver-ui-kit';
50
+ import { Provider } from 'react-redux';
51
+ import HiverQueryClientProvider from '../reactQueryClient.js';
52
+ import MyFeature from './index.js';
53
+
54
+ export const mountMyFeature = (store) => (container, props) => {
55
+ const root = ReactDOM.createRoot(container);
56
+ root.render(
57
+ <HiverProvider custom>
58
+ <HiverQueryClientProvider>
59
+ <Provider store={store}>
60
+ <MyFeature {...props} />
61
+ </Provider>
62
+ </HiverQueryClientProvider>
63
+ </HiverProvider>
64
+ );
65
+ return root.unmount.bind(root);
66
+ };
67
+ ```
68
+
69
+ Replace `MyFeature` / `mountMyFeature` with the actual feature name.
70
+
71
+ ### Register in `ReactBackboneModules/index.js`
72
+
73
+ 1. Add the import at the top:
74
+ ```js
75
+ import { mountMyFeature } from '../MyFeature/mounter';
76
+ ```
77
+ 2. Inside `appendReactBackboneModules()`, add:
78
+ ```js
79
+ myFeature: createModule(mountMyFeature(store)),
80
+ ```
81
+
82
+ Use camelCase for the module key (e.g., `myFeature`).
83
+
84
+ ---
85
+
86
+ ## Step 3b — React-only Wiring
87
+
88
+ ### Add lazy import in the file where the component is consumed
89
+
90
+ Do **not** default to `react-extn/src/index.js`. Add the lazy import in whichever file actually renders this component (e.g., a parent page, a layout component, or a route file).
91
+
92
+ ```js
93
+ const LazyMyFeature = React.lazy(() => import('./MyFeature' /* webpackChunkName: "my_feature" */))
94
+ ```
95
+
96
+ - Use `PascalCase` for the variable name prefixed with `Lazy`
97
+ - Use `snake_case` for `webpackChunkName`
98
+ - Render `<LazyMyFeature />` at the correct place in that file, wrapped in `<React.Suspense>` if not already present
99
+
100
+ ---
101
+
102
+ ## Step 4 — Feature Flag Boilerplate (if needed)
103
+
104
+ If the milestone requires a feature flag:
105
+
106
+ ### Naming convention
107
+ Use the `rls-` prefix: e.g., `rls-my-feature-name`
108
+
109
+ ### Add key to `react-extn/src/utils/constants.js`
110
+
111
+ Find the `featureKeys` object and add:
112
+ ```js
113
+ myFeatureName: 'rls-my-feature-name',
114
+ ```
115
+
116
+ ### Add checker function to `react-extn/src/utils/features.js`
117
+
118
+ ```js
119
+ export const isMyFeatureEnabled = (availableFeatures) =>
120
+ isFeatureActive(availableFeatures, featureKeys.myFeatureName);
121
+ ```
122
+
123
+ ### Gate the feature render
124
+
125
+ Use `availableFeatures` from Redux and the checker function to conditionally render:
126
+ ```js
127
+ const availableFeatures = useSelector(state => state.availableFeatures);
128
+ if (!isMyFeatureEnabled(availableFeatures)) return null;
129
+ ```
130
+
131
+ ---
132
+
133
+ ## Checklist (confirm before handing off to build-component)
134
+
135
+ - [ ] Folder structure created under `react-extn/src/<FeatureName>/`
136
+ - [ ] Mount type determined: Backbone / React-only
137
+ - [ ] `mounter.js` created and registered in `ReactBackboneModules/index.js` (Backbone only)
138
+ - [ ] Lazy import added in the correct consumer file (React-only, not necessarily the root `index.js`)
139
+ - [ ] Feature flag key added to `constants.js` (if needed)
140
+ - [ ] Feature flag checker added to `features.js` (if needed)
141
+ - [ ] Feature is gated behind the flag in the component (if needed)
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: write-test-cases
3
+ description: Writes structured behavioural test cases for a milestone into a progress-sheet markdown file. Invoked by build-milestone before any implementation begins (Normal Mode) or once per feedback round (Fix Mode). Never writes source code.
4
+ ---
5
+
6
+ # Write Test Cases
7
+
8
+ Generates a complete set of structured behavioural test cases for a milestone and saves them as a progress sheet that `build-milestone` uses to drive its TDD loop.
9
+
10
+ ## When to Use
11
+
12
+ - Invoked by `build-milestone` at the start of **Normal Mode** — before any implementation begins
13
+ - Invoked by `build-milestone` at the start of **Fix Mode** — once per feedback round, scoped to the feedback
14
+
15
+ ## Inputs
16
+
17
+ - Path to the milestone document (always required)
18
+ - Mode: `normal` or `feedback`
19
+ - If `feedback` mode: path to the feedback file
20
+
21
+ ## Instructions
22
+
23
+ ### Normal Mode
24
+
25
+ 1. Read the milestone document thoroughly. Extract:
26
+ - Goal
27
+ - Acceptance criteria (2–3 product-level "done" conditions)
28
+ - Architectural approach and high-level areas affected
29
+
30
+ 2. Explore the codebase **scoped strictly to the "High-level areas affected" section of the milestone doc**. Read only the files and directories explicitly named there. Do NOT fan out to unrelated modules. Limit reads to what is minimally needed to understand current state — what exists, what doesn't, what will change.
31
+
32
+ 3. If the milestone doc contains Figma design links, load them using the Figma MCP tool. Analyze the designs to identify UI-specific behaviours and edge cases. Load only the specific nodes linked — do not traverse the full Figma file.
33
+
34
+ 4. Derive test cases from the acceptance criteria and your codebase exploration. For each observable behaviour the milestone introduces or changes, write one test case. Aim for full coverage across:
35
+ - Happy path (primary user flows)
36
+ - Edge cases (boundary conditions, empty states, large data)
37
+ - Error states (API failures, invalid input, permission issues)
38
+ - Regressions (existing behaviours that must not break)
39
+
40
+ 5. Write ALL test cases to `milestone-tests/<milestone-name>-tests.md` — create the file if it doesn't exist. All test cases start with `⬜ Pending` status.
41
+
42
+ 6. Use this format for every test case:
43
+
44
+ ```markdown
45
+ ## TC-001 | Category: happy-path | ⬜ Pending
46
+ Given: <system or state precondition>
47
+ When: <user action or system trigger>
48
+ Then: <observable outcome — what the user sees or what changes in state>
49
+ ```
50
+
51
+ 7. After writing all test cases, exit. Do not write any source code.
52
+
53
+ ---
54
+
55
+ ### Feedback Mode
56
+
57
+ 1. Read the milestone document to understand the original scope.
58
+
59
+ 2. Read the feedback file. Identify the **active** (non-stale) feedback entry.
60
+
61
+ 3. Explore the codebase to understand the current state of the implementation for this milestone.
62
+
63
+ 4. Derive test cases scoped **only** to what the feedback describes. Write as many as needed to fully cover the feedback — happy path, edge cases, and regressions relevant to the fix.
64
+
65
+ 5. Append the new test cases to the existing `milestone-tests/<milestone-name>-tests.md` under a new section:
66
+
67
+ ```markdown
68
+ ## Feedback Round N
69
+
70
+ ### FTC-001 | Category: regression | ⬜ Pending
71
+ Given: <precondition>
72
+ When: <action>
73
+ Then: <expected outcome>
74
+ ```
75
+
76
+ Where `N` is incremented from the last existing Feedback Round number in the file.
77
+
78
+ 6. After appending, exit. Do not write any source code.
79
+
80
+ ---
81
+
82
+ ## Output
83
+
84
+ A `milestone-tests/<milestone-name>-tests.md` file (created or appended) with all new test cases set to `⬜ Pending`.
85
+
86
+ The `milestone-tests/` directory lives alongside the `milestones/` directory under the same parent.
87
+
88
+ ## Rules
89
+
90
+ - NEVER write source code
91
+ - NEVER mark any test case as passing — all new TCs start as `⬜ Pending`
92
+ - NEVER modify existing test case entries — only append new ones
93
+ - In Feedback Mode, only write TCs scoped to the active feedback — do not add unrelated cases
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hiver/skills",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Shared Claude Code skills & agents for Hiver teams",
5
5
  "type": "module",
6
6
  "bin": {