@nivora/matrix 0.1.0 → 0.1.1

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 (51) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +4 -4
  3. package/.next/build-manifest.json +2 -2
  4. package/.next/prerender-manifest.json +3 -3
  5. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  6. package/.next/server/app/_global-error.html +2 -2
  7. package/.next/server/app/_global-error.rsc +1 -1
  8. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/.next/server/app/_not-found.html +1 -1
  16. package/.next/server/app/_not-found.rsc +1 -1
  17. package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  18. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  19. package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  20. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  21. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  22. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  23. package/.next/server/app/builder/page.js +3 -3
  24. package/.next/server/app/builder/page_client-reference-manifest.js +1 -1
  25. package/.next/server/app/guide/page_client-reference-manifest.js +1 -1
  26. package/.next/server/app/matrix/page_client-reference-manifest.js +1 -1
  27. package/.next/server/app/page_client-reference-manifest.js +1 -1
  28. package/.next/server/app/releases/[id]/page.js +15 -15
  29. package/.next/server/app/releases/[id]/page_client-reference-manifest.js +1 -1
  30. package/.next/server/app/releases/page.js +2 -2
  31. package/.next/server/app/releases/page_client-reference-manifest.js +1 -1
  32. package/.next/server/app/specs/[id]/page.js +2 -2
  33. package/.next/server/app/specs/[id]/page_client-reference-manifest.js +1 -1
  34. package/.next/server/app-paths-manifest.json +4 -4
  35. package/.next/server/pages/404.html +1 -1
  36. package/.next/server/pages/500.html +2 -2
  37. package/.next/server/server-reference-manifest.js +1 -1
  38. package/.next/server/server-reference-manifest.json +1 -1
  39. package/.next/static/chunks/app/builder/{page-e10754eb65a4f784.js → page-e0a24ae820fa2c06.js} +2 -2
  40. package/.next/static/chunks/app/releases/[id]/page-ea66642a6a557b42.js +1 -0
  41. package/.next/static/chunks/app/releases/page-fc527101f56b36c5.js +1 -0
  42. package/.next/static/chunks/app/specs/[id]/page-49293bb634997108.js +1 -0
  43. package/.next/trace +11 -0
  44. package/.next/trace-build +1 -1
  45. package/README.md +220 -134
  46. package/package.json +1 -1
  47. package/.next/static/chunks/app/releases/[id]/page-d8069a1802686478.js +0 -1
  48. package/.next/static/chunks/app/releases/page-26a520d9789e69f5.js +0 -1
  49. package/.next/static/chunks/app/specs/[id]/page-7065af5d4d103f16.js +0 -1
  50. /package/.next/static/{8ZUFcYHRSRlY1FYWZ33gH → zmL75rl5Hq4TyiNVaXe8R}/_buildManifest.js +0 -0
  51. /package/.next/static/{8ZUFcYHRSRlY1FYWZ33gH → zmL75rl5Hq4TyiNVaXe8R}/_ssgManifest.js +0 -0
package/.next/trace-build CHANGED
@@ -1 +1 @@
1
- [{"name":"run-webpack","duration":6301639,"timestamp":1043981,"id":17,"parentId":1,"tags":{},"startTime":1768686136432,"traceId":"4d44b1760f605b08"},{"name":"run-typescript","duration":3800584,"timestamp":7468494,"id":1243,"parentId":1,"tags":{},"startTime":1768686142856,"traceId":"4d44b1760f605b08"},{"name":"static-check","duration":415221,"timestamp":11389726,"id":1246,"parentId":1,"tags":{},"startTime":1768686146778,"traceId":"4d44b1760f605b08"},{"name":"collect-build-traces","duration":6799256,"timestamp":11896109,"id":1269,"parentId":1,"tags":{},"startTime":1768686147284,"traceId":"4d44b1760f605b08"},{"name":"static-generation","duration":6939855,"timestamp":11904817,"id":1272,"parentId":1,"tags":{},"startTime":1768686147293,"traceId":"4d44b1760f605b08"},{"name":"telemetry-flush","duration":122,"timestamp":18878611,"id":1281,"parentId":1,"tags":{},"startTime":1768686154267,"traceId":"4d44b1760f605b08"},{"name":"next-build","duration":18213973,"timestamp":664779,"id":1,"tags":{"buildMode":"default","version":"16.1.1","bundler":"webpack","has-custom-webpack-config":"true","use-build-worker":"false"},"startTime":1768686136052,"traceId":"4d44b1760f605b08"}]
1
+ [{"name":"run-webpack","duration":6301956,"timestamp":1343499,"id":17,"parentId":1,"tags":{},"startTime":1768687151856,"traceId":"f1000a6551d797b7"},{"name":"run-typescript","duration":3617044,"timestamp":7758580,"id":1243,"parentId":1,"tags":{},"startTime":1768687158271,"traceId":"f1000a6551d797b7"},{"name":"static-check","duration":468693,"timestamp":11505520,"id":1246,"parentId":1,"tags":{},"startTime":1768687162018,"traceId":"f1000a6551d797b7"},{"name":"collect-build-traces","duration":6955911,"timestamp":12068136,"id":1269,"parentId":1,"tags":{},"startTime":1768687162581,"traceId":"f1000a6551d797b7"},{"name":"static-generation","duration":7114483,"timestamp":12076512,"id":1272,"parentId":1,"tags":{},"startTime":1768687162589,"traceId":"f1000a6551d797b7"},{"name":"telemetry-flush","duration":178,"timestamp":19204480,"id":1281,"parentId":1,"tags":{},"startTime":1768687169717,"traceId":"f1000a6551d797b7"},{"name":"next-build","duration":18323302,"timestamp":881376,"id":1,"tags":{"buildMode":"default","version":"16.1.1","bundler":"webpack","has-custom-webpack-config":"true","use-build-worker":"false"},"startTime":1768687151394,"traceId":"f1000a6551d797b7"}]
package/README.md CHANGED
@@ -1,35 +1,78 @@
1
- # GAMP 5 V-Model Traceability System
1
+ # Matrix - GAMP 5 Traceability System
2
2
 
3
- A streamlined requirements traceability and test management system designed for regulated environments, using **Gherkin as the source of truth** for Functional Specifications.
3
+ A **spec-as-code** requirements traceability system for regulated environments. Write Gherkin specs, run them as tests, and maintain automatic audit-ready traceability.
4
4
 
5
- 📚 **Documentation**:
6
- - [**User Guide**](./USER_GUIDE.md): How to use the dashboard and CLI.
7
- - [**Developer Guide**](./DEVELOPER_GUIDE.md): Architecture, setup, and development workflow.
8
- - [**Philosophy & Approach**](./GAMP_AND_V_MODEL.md): GAMP 5 principles, V-Model, and "Spec-as-Code" reasoning.
5
+ ## Quickstart
9
6
 
7
+ ```bash
8
+ bun add @nivora/matrix
9
+ bunx matrix init
10
+ bunx matrix serve
11
+ ```
12
+
13
+ Dashboard available at: http://localhost:3000
10
14
 
11
- ## Data Model
15
+ ---
12
16
 
13
- This system uses a **relational model** with 3 artifact types and no duplicate data:
17
+ ## Core Concepts
14
18
 
15
- | Artifact | Format | Location | Purpose |
16
- |----------|--------|----------|---------|
17
- | **URS** | Database | SQLite Table `urs` | High-level business requirements |
18
- | **FS** | Gherkin | `specs/fs/*.requirement` | Functional specs + embedded test scenarios |
19
- | **RISK** | Database | SQLite Table `risks` | Risk assessments linked to FS |
19
+ This system implements **GAMP 5** and **V-Model** compliance by making specifications executable:
20
20
 
21
- ### Key Insight: Gherkin IS the Functional Specification
21
+ | Artifact | Storage | Purpose |
22
+ |----------|---------|---------|
23
+ | **URS** | SQLite DB | High-level business requirements |
24
+ | **FS** | Gherkin `.requirement` files | Functional specs + test scenarios |
25
+ | **Risk** | SQLite DB | Risk assessments & mitigations |
26
+ | **Release** | SQLite DB | Version management & test results |
22
27
 
23
- Instead of maintaining separate FS documents and test files, we use Gherkin Feature files AS the functional specification:
28
+ **Key Insight**: The Gherkin Feature file IS the Functional Spec AND the test. No duplication.
24
29
 
25
30
  ```gherkin
26
31
  @URS-001 @RISK-001
27
- Feature: FS-001 User Login Authentication
28
- The system shall provide a login interface that authenticates users
29
- against stored credentials and establishes a secure session.
32
+ Feature: FS-001 User Login
33
+ The system shall authenticate users against stored credentials.
34
+
35
+ Scenario: Successful login
36
+ Given I am on the login page
37
+ When I enter valid credentials
38
+ Then I should see my dashboard
39
+ ```
40
+
41
+ ---
42
+
43
+ ## Workflow
44
+
45
+ ### 1. Create User Requirements (URS)
46
+
47
+ **Option A: Dashboard UI**
48
+ 1. Navigate to http://localhost:3000/specs
49
+ 2. Click "New Specification"
50
+ 3. Fill in Title, Business Need, Acceptance Criteria
51
+ 4. Save
52
+
53
+ **Option B: Stub Generation (Recommended)**
54
+
55
+ Reference URS IDs in your Gherkin files before they exist:
56
+
57
+ ```gherkin
58
+ @URS-011
59
+ Feature: FS-009 Password Reset
60
+ ```
61
+
62
+ Run `matrix sync` and the system creates a placeholder `URS-011` record. Fill in details via the dashboard later.
63
+
64
+ ### 2. Write Functional Specs (FS)
65
+
66
+ Create `.requirement` files in `specs/fs/`:
67
+
68
+ ```gherkin
69
+ @URS-001 @URS-002 @RISK-005
70
+ Feature: FS-001 User Authentication
71
+ The system shall authenticate users against stored credentials
72
+ and establish a secure session.
30
73
 
31
74
  Requirements:
32
- - FR-001.1: Display login form with email and password fields
75
+ - FR-001.1: Display login form with email and password
33
76
  - FR-001.2: Validate credentials against stored hash
34
77
  - FR-001.3: Rate limit after 5 failed attempts
35
78
 
@@ -37,149 +80,192 @@ Feature: FS-001 User Login Authentication
37
80
  Given I am on the login page
38
81
  When I enter valid credentials
39
82
  Then I should be redirected to my dashboard
83
+
84
+ Scenario: Failed login locks account after 5 attempts
85
+ Given I have failed login 4 times
86
+ When I enter invalid credentials
87
+ Then I should see "Account locked"
40
88
  ```
41
89
 
42
- **Benefits:**
43
- - **No duplication**: The Feature description IS the spec, scenarios ARE the tests
44
- - **Single source of truth**: Edit one file, both spec and tests are updated
45
- - **Clear traceability**: `@URS-xxx` and `@RISK-xxx` tags create automatic links
46
- - **Executable specs**: The `.requirement` files can be run by Cucumber
90
+ **Linking Tags:**
91
+ - `@URS-xxx` Links to User Requirement
92
+ - `@RISK-xxx` Links to Risk Assessment
47
93
 
48
- ## Directory Structure
94
+ ### 3. Create Risk Assessments
49
95
 
50
- ```
51
- docs/
52
- ├── specs/
53
- │ └── fs/ # Functional Specs (Gherkin)
54
- │ ├── FS-001-login.requirement
55
- │ ├── FS-002-session.requirement
56
- │ ├── FS-003-registration.requirement
57
- │ ├── FS-004-booking.requirement
58
- │ ├── FS-005-waitlist.requirement
59
- │ ├── FS-006-schedule.requirement
60
- │ └── FS-007-instructor.requirement
61
- └── src/ # Next.js Dashboard
62
- ```
96
+ **Option A: Dashboard UI** — Same flow as URS
63
97
 
64
- ## Linking Artifacts
98
+ **Option B: Stub Generation** — Reference `@RISK-xxx` in Gherkin, run sync, fill in details later
65
99
 
66
- ### URS to FS
67
- Use `@URS-xxx` tag in the Gherkin Feature:
68
- ```gherkin
69
- @URS-001
70
- Feature: FS-001 User Login
100
+ ### 4. Sync to Database
101
+
102
+ ```bash
103
+ matrix sync
71
104
  ```
72
105
 
73
- ### FS to Risk
74
- Use `@RISK-xxx` tag in the Gherkin Feature:
75
- ```gherkin
76
- @URS-001 @RISK-001
77
- Feature: FS-001 User Login
106
+ **What sync does:**
107
+ 1. Parses all `.requirement` files in `specs/fs/`
108
+ 2. Updates database with Feature titles, descriptions, and scenarios
109
+ 3. Extracts `@URS` and `@RISK` tags
110
+ 4. Auto-creates stub records for any referenced IDs that don't exist
111
+
112
+ > **Tip:** Write Gherkin first with new IDs, run sync, then fill in URS/Risk details via the dashboard.
113
+
114
+ ---
115
+
116
+ ## Release Management
117
+
118
+ ### 1. Create a Release
119
+
120
+ ```bash
121
+ matrix release create -v 1.0.0 -n "MVP Launch" --notes "Initial release"
78
122
  ```
79
123
 
80
- ### Verification Levels (V-Model)
81
- - **URS** Verified by **PQ** (Performance Qualification)
82
- - **FS** Verified by **OQ** (Operational Qualification)
83
- - **Scenarios** Verified by **IQ** (Installation Qualification)
124
+ Creates a release with:
125
+ - **Version**: Semantic version (e.g., 1.0.0)
126
+ - **Name**: Human-readable name
127
+ - **Status**: Defaults to "planning"
128
+ - **Notes**: Optional release notes
84
129
 
85
- ## Running the Dashboard
130
+ ### 2. Tag Features to Release
86
131
 
87
132
  ```bash
88
- cd docs
89
- bun install
90
- bun run dev
133
+ matrix release tag REL-001 --fs FS-001 FS-002 FS-003
91
134
  ```
92
135
 
93
- Access at: http://localhost:3000
136
+ ### 3. Run Tests
94
137
 
95
- ## Dashboard Pages
138
+ Execute Cucumber tests and export results:
96
139
 
97
- | Page | Description |
98
- |------|-------------|
99
- | `/` | Dashboard with stats, coverage, and traceability summary |
100
- | `/specs` | Browse URS (YAML), FS (Gherkin), and Risk (YAML) |
101
- | `/matrix` | Full traceability matrix: URS → FS → Scenarios → Risks |
102
- | `/builder` | Visual editor for creating new FS .requirement files |
103
- | `/search` | Search across all artifacts |
104
-
105
- ## Creating New Artifacts
106
-
107
- ### New URS (via Dashboard or manually)
108
- Create `specs/urs/URS-xxx.yaml`:
109
- ```yaml
110
- id: URS-004
111
- type: urs
112
- title: New Business Requirement
113
- status: draft
114
- priority: high
115
- owner: Product Team
116
- category: Core
117
- business_need: |
118
- Description of the business need...
119
- intended_use: |
120
- How the system will be used...
121
- acceptance_criteria:
122
- - Criterion 1
123
- - Criterion 2
124
- regulatory_refs:
125
- - GAMP 5
140
+ ```bash
141
+ npx cucumber-js specs/fs/**/*.requirement --format json:results.json
126
142
  ```
127
143
 
128
- ### New FS (via Builder or manually)
129
- Create `specs/fs/FS-xxx-name.requirement`:
130
- ```gherkin
131
- @URS-xxx @RISK-xxx
132
- Feature: FS-xxx Feature Title
133
- The system shall...
134
-
135
- Requirements:
136
- - FR-xxx.1: First requirement
137
- - FR-xxx.2: Second requirement
144
+ ### 4. Import Test Results
145
+
146
+ ```bash
147
+ matrix release import-results results.json --releaseId REL-001
148
+ ```
149
+
150
+ Or use the test command:
138
151
 
139
- Scenario: Test case 1
140
- Given ...
141
- When ...
142
- Then ...
152
+ ```bash
153
+ matrix test import results.json -r REL-001
143
154
  ```
144
155
 
145
- ### New Risk (manually)
146
- Create `specs/risk/RISK-xxx.yaml`:
147
- ```yaml
148
- id: RISK-004
149
- type: risk
150
- title: Risk Title
151
- status: draft
152
- category: Security
153
- gamp_category: 4
154
- fs_ids:
155
- - FS-001
156
- impact: high
157
- probability: medium
158
- risk_level: high
159
- risks:
160
- - id: R-004.1
161
- description: Risk description
162
- impact: high
163
- probability: medium
164
- mitigations:
165
- - risk_id: R-004.1
166
- control: Control measure
167
- test: How to test
168
- residual_risk: acceptable
156
+ The import process:
157
+ - Creates a test run record
158
+ - Stores individual scenario results (pass/fail)
159
+ - Warns if any tests failed
160
+ - Updates release status to "testing"
161
+
162
+ ### 5. View Test Results
163
+
164
+ ```bash
165
+ matrix test list REL-001
169
166
  ```
170
167
 
171
- ## Running Tests
168
+ ### 6. Handle Test Failures
169
+
170
+ If tests fail, you have two GAMP-compliant options:
171
+
172
+ **Option A: Fix the Code**
173
+ 1. Fix the failing functionality
174
+ 2. Re-run tests
175
+ 3. Import the new results
176
+
177
+ **Option B: Log a Defect/Deviation**
178
+ 1. Go to Release Detail page: `http://localhost:3000/releases/REL-001`
179
+ 2. Find the **Defects & Deviations** section
180
+ 3. Click **Log Defect** for the failing scenario
181
+ 4. Provide:
182
+ - **Description**: What failed and why
183
+ - **Justification**: Why it's acceptable (workaround exists, low impact, etc.)
184
+ - **Status**: Open, Investigating, Resolved, or Accepted
172
185
 
173
- The `.requirement` files are standard Gherkin and can be executed with Cucumber:
186
+ > [!IMPORTANT]
187
+ > You cannot mark a release as "Released" if it has failing tests without corresponding Defect records.
188
+
189
+ ### 7. Update Release Status
174
190
 
175
191
  ```bash
176
- # Configure cucumber to find .requirement files
177
- npx cucumber-js specs/fs/**/*.requirement
192
+ # Move to testing phase
193
+ matrix release status REL-001 --status testing
194
+
195
+ # Mark as released (requires all tests pass or defects logged)
196
+ matrix release status REL-001 --status released
178
197
  ```
179
198
 
199
+ ### 8. List All Releases
200
+
201
+ ```bash
202
+ matrix release list
203
+ ```
204
+
205
+ ---
206
+
207
+ ## CLI Reference
208
+
209
+ ### Core Commands
210
+
211
+ | Command | Description |
212
+ |---------|-------------|
213
+ | `matrix init` | Initialize a new specs directory |
214
+ | `matrix serve` | Start the dashboard server |
215
+ | `matrix sync` | Parse `.requirement` files and update database |
216
+ | `matrix search <query>` | Semantic search across specs |
217
+
218
+ ### Release Commands
219
+
220
+ | Command | Description |
221
+ |---------|-------------|
222
+ | `matrix release list` | List all releases |
223
+ | `matrix release create` | Create a new release |
224
+ | `matrix release tag <id>` | Tag FS records to a release |
225
+ | `matrix release status <id>` | Update release status |
226
+ | `matrix release import-results <file>` | Import Cucumber JSON results |
227
+
228
+ ### Test Commands
229
+
230
+ | Command | Description |
231
+ |---------|-------------|
232
+ | `matrix test import <file> -r <releaseId>` | Import Cucumber JSON results |
233
+ | `matrix test list <releaseId>` | List test runs for a release |
234
+
235
+ ### Common Options
236
+
237
+ | Option | Description |
238
+ |--------|-------------|
239
+ | `-p, --port <port>` | Port for serve (default: 3000) |
240
+ | `-s, --specs <dir>` | Specs directory (default: ./specs) |
241
+ | `-d, --db <path>` | Database path (default: ./matrix.db) |
242
+
243
+ ---
244
+
245
+ ## Dashboard Pages
246
+
247
+ | Page | URL | Description |
248
+ |------|-----|-------------|
249
+ | Home | `/` | Stats, coverage, and traceability overview |
250
+ | Specs | `/specs` | Browse and edit URS, FS, and Risks |
251
+ | Matrix | `/matrix` | Full traceability matrix: URS → FS → Scenarios → Risks |
252
+ | Releases | `/releases` | Release management and test results |
253
+ | Builder | `/builder` | Visual editor for creating FS files |
254
+ | Search | `/search` | Search across all artifacts |
255
+
256
+ ---
257
+
180
258
  ## GAMP 5 Compliance
181
259
 
182
- - **Category 4**: Configured products (authentication, session management)
183
- - **Category 5**: Custom applications (booking transactions)
184
- - **21 CFR Part 11**: Electronic records and signatures ready
185
- - **ALCOA+**: Data integrity principles for booking records
260
+ - **V-Model Integration**: FS files serve as both specification (FS) and test protocol (OQ)
261
+ - **Risk-Based Testing**: `@RISK-xxx` tags prioritize validation effort
262
+ - **Automatic Traceability**: Tag-based linking generates audit-ready matrices
263
+ - **Defect Management**: Failed tests require formal deviation records before release
264
+ - **21 CFR Part 11 Ready**: Full audit trail of changes and test results
265
+
266
+ ---
267
+
268
+ ## Additional Documentation
269
+
270
+ - [Developer Guide](./DEVELOPER_GUIDE.md) - Architecture and development setup
271
+ - [GAMP & V-Model Philosophy](./GAMP_AND_V_MODEL.md) - Design rationale
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nivora/matrix",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Requirements documentation system with semantic search",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[41],{4926:(e,t,r)=>{Promise.resolve().then(r.bind(r,6717))},6717:(e,t,r)=>{"use strict";r.d(t,{ReleaseDetailClient:()=>h});var s=r(5155),i=r(2115),a=r(8500),l=r.n(a),n=r(9339);let o=(0,n.createServerReference)("60b2b1ac09aa309cd62336a9a181a22f6a565110e8",n.callServer,void 0,n.findSourceMapURL,"updateReleaseAction"),d=(0,n.createServerReference)("60a507c03894e522051c1ddbaa648c22f3145f6f7b",n.callServer,void 0,n.findSourceMapURL,"tagFSToReleaseAction"),c=(0,n.createServerReference)("600920c1121365a4e4a2b74f81a2832b96fbcadc12",n.callServer,void 0,n.findSourceMapURL,"untagFSFromReleaseAction"),m=(0,n.createServerReference)("4098c7d1c9ece378d5dbdd69bf4aa352b2d12a9669",n.callServer,void 0,n.findSourceMapURL,"createDefectAction");function h({release:e,taggedFS:t,availableFS:r,testRuns:a,defects:n}){let[h,p]=(0,i.useState)(!1),[g,x]=(0,i.useState)(!1),[v,u]=(0,i.useState)([]),[y,j]=(0,i.useState)(null),[f,b]=(0,i.useState)({isOpen:!1}),[S,N]=(0,i.useState)({title:"",description:"",status:"open"}),[C,k]=(0,i.useState)({titleError:!1,descriptionError:!1}),[R,w]=(0,i.useTransition)(),[B,W]=(0,i.useState)({version:e.version,name:e.name,status:e.status,notes:e.notes||""}),_={planning:{bg:"rgba(168, 85, 247, 0.1)",color:"#a855f7"},testing:{bg:"rgba(59, 130, 246, 0.1)",color:"#3b82f6"},released:{bg:"rgba(34, 197, 94, 0.1)",color:"#22c55e"}}[e.status];return(0,s.jsxs)("div",{style:{maxWidth:"1200px",margin:"0 auto",padding:"2rem"},children:[(0,s.jsx)("div",{style:{marginBottom:"1.5rem"},children:(0,s.jsx)(l(),{href:"/releases",style:{color:"var(--text-secondary)",textDecoration:"none"},children:"← Back to Releases"})}),(0,s.jsxs)("header",{style:{marginBottom:"2rem"},children:[(0,s.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:"1rem",marginBottom:"0.5rem"},children:[(0,s.jsxs)("code",{style:{fontSize:"1.5rem",fontWeight:700,color:_.color},children:[" ",e.id," "]}),(0,s.jsxs)("span",{style:{fontSize:"1.25rem",fontWeight:600},children:["v",e.version]}),(0,s.jsx)("span",{className:"badge",style:{background:_.bg,color:_.color,padding:"0.5rem 1rem"},children:e.status}),(0,s.jsx)("button",{onClick:()=>p(!h),className:"btn btn-primary",style:{marginLeft:"auto"},children:h?"Cancel":"✏️ Edit"})]}),(0,s.jsx)("h1",{style:{fontSize:"2rem",fontWeight:700},children:e.name}),(0,s.jsxs)("p",{style:{color:"var(--text-secondary)"},children:["Created ",e.created_at,e.released_at&&` • Released ${e.released_at}`]})]}),h&&(0,s.jsxs)("div",{className:"card",style:{marginBottom:"1.5rem"},children:[(0,s.jsx)("h2",{className:"card-title",children:"Edit Release"}),(0,s.jsxs)("div",{style:{display:"grid",gridTemplateColumns:"1fr 2fr 1fr",gap:"1rem",marginBottom:"1rem"},children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{style:{display:"block",fontWeight:500,marginBottom:"0.5rem"},children:"Version"}),(0,s.jsx)("input",{type:"text",value:B.version,onChange:e=>W({...B,version:e.target.value}),className:"input"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{style:{display:"block",fontWeight:500,marginBottom:"0.5rem"},children:"Name"}),(0,s.jsx)("input",{type:"text",value:B.name,onChange:e=>W({...B,name:e.target.value}),className:"input"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{style:{display:"block",fontWeight:500,marginBottom:"0.5rem"},children:"Status"}),(0,s.jsxs)("select",{value:B.status,onChange:e=>W({...B,status:e.target.value}),className:"input",children:[(0,s.jsx)("option",{value:"planning",children:"Planning"}),(0,s.jsx)("option",{value:"testing",children:"Testing"}),(0,s.jsx)("option",{value:"released",children:"Released"})]})]})]}),(0,s.jsxs)("div",{style:{marginBottom:"1rem"},children:[(0,s.jsx)("label",{style:{display:"block",fontWeight:500,marginBottom:"0.5rem"},children:"Notes"}),(0,s.jsx)("textarea",{value:B.notes,onChange:e=>W({...B,notes:e.target.value}),rows:3,className:"input",style:{resize:"vertical"}})]}),(0,s.jsx)("button",{onClick:()=>{w(async()=>{await o(e.id,B),p(!1)})},className:"btn btn-primary",disabled:R,children:R?"Saving...":"Save Changes"})]}),e.notes&&!h&&(0,s.jsxs)("div",{className:"card",style:{marginBottom:"1.5rem"},children:[(0,s.jsx)("h2",{className:"card-title",children:"\uD83D\uDCDD Notes"}),(0,s.jsx)("p",{style:{color:"var(--text-secondary)",whiteSpace:"pre-wrap"},children:e.notes})]}),(0,s.jsxs)("div",{className:"card",style:{marginBottom:"1.5rem",borderLeft:"4px solid var(--error)"},children:[(0,s.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"1rem"},children:[(0,s.jsxs)("h2",{className:"card-title",children:["\uD83D\uDEA8 Defects & Deviations (",n.length,")"]}),(0,s.jsx)("button",{className:"btn",onClick:()=>{b({isOpen:!0,testResultId:void 0,fsId:void 0,scenarioName:void 0}),N({title:"",description:"",status:"open"})},children:"+ Log Defect"})]}),0===n.length?(0,s.jsx)("p",{style:{color:"var(--text-secondary)"},children:"No defects logged. Any failed tests must be resolved or logged as a defect."}):(0,s.jsx)("div",{style:{display:"grid",gap:"0.75rem"},children:n.map(e=>(0,s.jsxs)("div",{style:{padding:"1rem",background:"var(--bg-hover)",borderRadius:"8px",borderLeft:"open"===e.status?"3px solid red":"3px solid green"},children:[(0,s.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",marginBottom:"0.5rem"},children:[(0,s.jsxs)("div",{style:{fontWeight:600},children:[e.id,": ",e.title]}),(0,s.jsx)("div",{className:"badge",style:{background:"open"===e.status?"rgba(239, 68, 68, 0.1)":"rgba(34, 197, 94, 0.1)",color:"open"===e.status?"var(--error)":"var(--success)"},children:e.status.toUpperCase()})]}),(0,s.jsx)("div",{style:{fontSize:"0.875rem",color:"var(--text-secondary)",whiteSpace:"pre-wrap"},children:e.description}),e.test_result_id&&(0,s.jsxs)("div",{style:{marginTop:"0.5rem",fontSize:"0.75rem",color:"var(--warning)"},children:["Linked to failed test result #",e.test_result_id]})]},e.id))})]}),(0,s.jsxs)("div",{className:"card",style:{marginBottom:"1.5rem"},children:[(0,s.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"1rem"},children:[(0,s.jsxs)("h2",{className:"card-title",style:{margin:0},children:["⚙️ Features (",t.length,")"]}),(0,s.jsx)("button",{onClick:()=>x(!0),className:"btn",disabled:0===r.length,children:"+ Add Features"})]}),g&&(0,s.jsxs)("div",{style:{marginBottom:"1rem",padding:"1rem",background:"var(--bg-hover)",borderRadius:"8px"},children:[(0,s.jsx)("div",{style:{marginBottom:"0.5rem",fontWeight:500},children:"Select features to add:"}),(0,s.jsx)("div",{style:{display:"flex",flexWrap:"wrap",gap:"0.5rem",marginBottom:"1rem"},children:r.map(e=>(0,s.jsxs)("label",{style:{display:"flex",alignItems:"center",gap:"0.5rem",cursor:"pointer"},children:[(0,s.jsx)("input",{type:"checkbox",checked:v.includes(e.id),onChange:t=>{t.target.checked?u([...v,e.id]):u(v.filter(t=>t!==e.id))}}),(0,s.jsx)("code",{style:{color:"var(--warning)"},children:e.id}),(0,s.jsx)("span",{children:e.title})]},e.id))}),(0,s.jsxs)("div",{style:{display:"flex",gap:"0.5rem"},children:[(0,s.jsx)("button",{onClick:()=>{x(!1),u([])},className:"btn",children:"Cancel"}),(0,s.jsx)("button",{onClick:()=>{0!==v.length&&w(async()=>{await d(e.id,v),x(!1),u([])})},className:"btn btn-primary",disabled:R||0===v.length,children:R?"Adding...":`Add ${v.length} Feature${1!==v.length?"s":""}`})]})]}),0===t.length?(0,s.jsx)("p",{style:{color:"var(--text-secondary)"},children:"No features tagged yet. Add features to track them in this release."}):(0,s.jsx)("div",{style:{display:"grid",gap:"0.5rem"},children:t.map(t=>(0,s.jsxs)("div",{style:{display:"flex",alignItems:"center",padding:"0.75rem 1rem",background:"var(--bg-hover)",borderRadius:"8px"},children:[(0,s.jsxs)(l(),{href:`/specs/${t.id}`,style:{flex:1,textDecoration:"none"},children:[(0,s.jsx)("code",{style:{fontWeight:600,color:"var(--warning)",marginRight:"0.75rem"},children:t.id}),(0,s.jsx)("span",{style:{color:"var(--text-primary)"},children:t.title}),(0,s.jsxs)("span",{style:{marginLeft:"0.75rem",color:"var(--text-secondary)",fontSize:"0.875rem"},children:[t.scenario_count," scenarios"]})]}),(0,s.jsx)("button",{onClick:()=>{var r;return r=t.id,void w(async()=>{await c(e.id,r)})},className:"btn",style:{padding:"0.25rem 0.5rem",fontSize:"0.75rem"},disabled:R,children:"\xd7"})]},t.id))})]}),(0,s.jsxs)("div",{className:"card",children:[(0,s.jsxs)("h2",{className:"card-title",children:["\uD83E\uDDEA Test Runs (",a.length,")"]}),0===a.length?(0,s.jsxs)("p",{style:{color:"var(--text-secondary)"},children:["No test runs yet. Import Cucumber results: ",(0,s.jsxs)("code",{children:["machine release import-results results.json -r ",e.id]})]}):(0,s.jsx)("div",{style:{display:"grid",gap:"0.75rem"},children:a.map(e=>{let t=e.total>0?e.passed/e.total*100:0,r=y===e.id;return(0,s.jsxs)("div",{style:{padding:"1rem",background:"var(--bg-hover)",borderRadius:"8px"},children:[(0,s.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",cursor:"pointer"},onClick:()=>j(r?null:e.id),children:[(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{style:{fontWeight:600,marginBottom:"0.25rem"},children:[e.failed>0?"❌":"✅"," Run #",e.id," ",r?"\uD83D\uDD3D":"▶"]}),(0,s.jsxs)("div",{style:{fontSize:"0.875rem",color:"var(--text-secondary)"},children:[e.run_date," • ",e.source]})]}),(0,s.jsxs)("div",{style:{display:"flex",gap:"1rem",textAlign:"center"},children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{style:{fontWeight:700,color:"var(--success)"},children:e.passed}),(0,s.jsx)("div",{style:{fontSize:"0.75rem",color:"var(--text-secondary)"},children:"Passed"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{style:{fontWeight:700,color:"var(--error)"},children:e.failed}),(0,s.jsx)("div",{style:{fontSize:"0.75rem",color:"var(--text-secondary)"},children:"Failed"})]}),(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{style:{fontWeight:700,color:100===t?"var(--success)":t>=80?"var(--warning)":"var(--error)"},children:[t.toFixed(0),"%"]}),(0,s.jsx)("div",{style:{fontSize:"0.75rem",color:"var(--text-secondary)"},children:"Pass Rate"})]})]})]}),r&&(0,s.jsx)("div",{style:{marginTop:"1rem",paddingTop:"1rem",borderTop:"1px solid var(--border)"},children:(0,s.jsx)("p",{style:{fontStyle:"italic",color:"var(--text-secondary)"},children:"Detailed results view would go here. For now, check the console logs or database for failure details."})})]},e.id)})})]}),f.isOpen&&(0,s.jsx)("div",{style:{position:"fixed",top:0,left:0,right:0,bottom:0,background:"rgba(0,0,0,0.5)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:100},children:(0,s.jsxs)("div",{className:"card",style:{width:"500px",maxWidth:"90%"},children:[(0,s.jsx)("h2",{className:"card-title",children:"Log Defect / Deviation"}),(0,s.jsxs)("div",{style:{marginBottom:"1rem"},children:[(0,s.jsxs)("label",{style:{display:"block",marginBottom:"0.5rem"},children:["Title ",(0,s.jsx)("span",{style:{color:"var(--error)"},children:"*"})]}),(0,s.jsx)("input",{className:"input",value:S.title,onChange:e=>{N({...S,title:e.target.value}),e.target.value&&k(e=>({...e,titleError:!1}))},placeholder:"Defect summary",style:C.titleError?{borderColor:"var(--error)",boxShadow:"0 0 0 2px rgba(239, 68, 68, 0.2)"}:{}}),C.titleError&&(0,s.jsx)("div",{style:{color:"var(--error)",fontSize:"0.75rem",marginTop:"0.25rem"},children:"Title is required"})]}),(0,s.jsxs)("div",{style:{marginBottom:"1rem"},children:[(0,s.jsxs)("label",{style:{display:"block",marginBottom:"0.5rem"},children:["Description & Root Cause ",(0,s.jsx)("span",{style:{color:"var(--error)"},children:"*"})]}),(0,s.jsx)("textarea",{className:"input",rows:5,value:S.description,onChange:e=>{N({...S,description:e.target.value}),e.target.value&&k(e=>({...e,descriptionError:!1}))},placeholder:"Describe the failure, root cause, and why it is acceptable (if deviating) or mitigation plan.",style:C.descriptionError?{borderColor:"var(--error)",boxShadow:"0 0 0 2px rgba(239, 68, 68, 0.2)"}:{}}),C.descriptionError&&(0,s.jsx)("div",{style:{color:"var(--error)",fontSize:"0.75rem",marginTop:"0.25rem"},children:"Description is required"})]}),(0,s.jsxs)("div",{style:{marginBottom:"1rem"},children:[(0,s.jsx)("label",{style:{display:"block",marginBottom:"0.5rem"},children:"Status"}),(0,s.jsxs)("select",{className:"input",value:S.status,onChange:e=>N({...S,status:e.target.value}),children:[(0,s.jsx)("option",{value:"open",children:"Open (Needs Fix)"}),(0,s.jsx)("option",{value:"resolved",children:"Resolved (Fixed)"}),(0,s.jsx)("option",{value:"accepted",children:"Accepted (Permanent Deviation)"})]})]}),(0,s.jsxs)("div",{style:{display:"flex",gap:"0.5rem",justifyContent:"flex-end"},children:[(0,s.jsx)("button",{className:"btn",onClick:()=>{b({isOpen:!1}),k({titleError:!1,descriptionError:!1})},children:"Cancel"}),(0,s.jsx)("button",{className:"btn btn-primary",onClick:()=>{let t=!S.title.trim(),r=!S.description.trim();t||r?k({titleError:t,descriptionError:r}):w(async()=>{try{await m({releaseId:e.id,testResultId:f.testResultId,title:S.title,description:S.description,status:S.status}),b({isOpen:!1}),N({title:"",description:"",status:"open"})}catch(e){console.error("Failed to create defect:",e),alert("Failed to create defect. Check console for details.")}})},disabled:R,children:R?"Logging...":"Log Defect"})]})]})})]})}},9339:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});var s={callServer:function(){return a.callServer},createServerReference:function(){return n.createServerReference},findSourceMapURL:function(){return l.findSourceMapURL}};for(var i in s)Object.defineProperty(t,i,{enumerable:!0,get:s[i]});let a=r(7304),l=r(4060),n=r(7197)}},e=>{e.O(0,[500,441,794,358],()=>e(e.s=4926)),_N_E=e.O()}]);
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[549],{4815:(e,t,r)=>{"use strict";r.d(t,{ReleasesClient:()=>c});var s=r(5155),a=r(2115),l=r(8500),n=r.n(l),i=r(9339);let o=(0,i.createServerReference)("40d511dc3a76cac7d4c145452256536f04babc742d",i.callServer,void 0,i.findSourceMapURL,"createReleaseAction");function c({releases:e}){let[t,r]=(0,a.useState)(!1),[l,n]=(0,a.useState)(""),[i,c]=(0,a.useState)(""),[m,x]=(0,a.useState)(""),[h,g]=(0,a.useTransition)();return(0,s.jsxs)("div",{style:{maxWidth:"1200px",margin:"0 auto",padding:"2rem"},children:[(0,s.jsx)("header",{style:{marginBottom:"2rem"},children:(0,s.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h1",{style:{fontSize:"2rem",fontWeight:700,marginBottom:"0.5rem"},children:"\uD83D\uDCE6 Releases"}),(0,s.jsx)("p",{style:{color:"var(--text-secondary)"},children:"Manage releases, track test execution, and compare changes"})]}),(0,s.jsx)("button",{onClick:()=>r(!0),className:"btn btn-primary",children:"+ New Release"})]})}),t&&(0,s.jsxs)("div",{className:"card",style:{marginBottom:"1.5rem"},children:[(0,s.jsx)("h2",{className:"card-title",children:"Create New Release"}),(0,s.jsxs)("div",{style:{display:"grid",gridTemplateColumns:"1fr 2fr",gap:"1rem",marginBottom:"1rem"},children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{style:{display:"block",fontWeight:500,marginBottom:"0.5rem"},children:"Version"}),(0,s.jsx)("input",{type:"text",value:l,onChange:e=>n(e.target.value),placeholder:"1.0.0",className:"input"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{style:{display:"block",fontWeight:500,marginBottom:"0.5rem"},children:"Name"}),(0,s.jsx)("input",{type:"text",value:i,onChange:e=>c(e.target.value),placeholder:"Initial Release",className:"input"})]})]}),(0,s.jsxs)("div",{style:{marginBottom:"1rem"},children:[(0,s.jsx)("label",{style:{display:"block",fontWeight:500,marginBottom:"0.5rem"},children:"Notes (optional)"}),(0,s.jsx)("textarea",{value:m,onChange:e=>x(e.target.value),placeholder:"Release notes...",rows:3,className:"input",style:{resize:"vertical"}})]}),(0,s.jsxs)("div",{style:{display:"flex",gap:"0.5rem"},children:[(0,s.jsx)("button",{onClick:()=>r(!1),className:"btn",disabled:h,children:"Cancel"}),(0,s.jsx)("button",{onClick:()=>{g(async()=>{await o({version:l,name:i,notes:m||void 0}),r(!1),n(""),c(""),x("")})},className:"btn btn-primary",disabled:h||!l||!i,children:h?"Creating...":"Create Release"})]})]}),0===e.length?(0,s.jsxs)("div",{className:"card",style:{textAlign:"center",padding:"3rem"},children:[(0,s.jsx)("p",{style:{fontSize:"3rem",marginBottom:"1rem"},children:"\uD83D\uDCE6"}),(0,s.jsx)("h2",{style:{marginBottom:"0.5rem"},children:"No Releases Yet"}),(0,s.jsx)("p",{style:{color:"var(--text-secondary)",marginBottom:"1rem"},children:"Create your first release to start tracking features and test results."}),(0,s.jsx)("button",{onClick:()=>r(!0),className:"btn btn-primary",children:"Create First Release"})]}):(0,s.jsx)("div",{style:{display:"grid",gap:"1rem"},children:e.map(e=>(0,s.jsx)(d,{release:e},e.id))})]})}function d({release:e}){let t={planning:{bg:"rgba(168, 85, 247, 0.1)",color:"#a855f7"},testing:{bg:"rgba(59, 130, 246, 0.1)",color:"#3b82f6"},released:{bg:"rgba(34, 197, 94, 0.1)",color:"#22c55e"}}[e.status];return(0,s.jsx)(n(),{href:`/releases/${e.id}`,style:{textDecoration:"none"},children:(0,s.jsx)("div",{className:"card",style:{borderLeft:`4px solid ${t.color}`,transition:"transform 0.15s, box-shadow 0.15s",cursor:"pointer"},children:(0,s.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start"},children:[(0,s.jsxs)("div",{style:{flex:1},children:[(0,s.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:"0.75rem",marginBottom:"0.5rem"},children:[(0,s.jsx)("code",{style:{fontSize:"1.25rem",fontWeight:700,color:t.color},children:e.id}),(0,s.jsxs)("span",{style:{fontSize:"1rem",fontWeight:600,color:"var(--text-primary)"},children:["v",e.version]}),(0,s.jsx)("span",{className:"badge",style:{background:t.bg,color:t.color},children:e.status})]}),(0,s.jsx)("h3",{style:{fontSize:"1.125rem",fontWeight:600,marginBottom:"0.5rem",color:"var(--text-primary)"},children:e.name}),(0,s.jsxs)("p",{style:{fontSize:"0.875rem",color:"var(--text-secondary)"},children:["Created ",e.created_at,e.released_at&&` • Released ${e.released_at}`]})]}),(0,s.jsxs)("div",{style:{display:"flex",gap:"1.5rem",textAlign:"center"},children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{style:{fontSize:"1.5rem",fontWeight:700,color:"var(--warning)"},children:e.fs_count}),(0,s.jsx)("div",{style:{fontSize:"0.75rem",color:"var(--text-secondary)"},children:"Features"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{style:{fontSize:"1.5rem",fontWeight:700,color:"var(--accent)"},children:e.test_runs}),(0,s.jsx)("div",{style:{fontSize:"0.75rem",color:"var(--text-secondary)"},children:"Test Runs"})]}),null!==e.latest_pass_rate&&(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{style:{fontSize:"1.5rem",fontWeight:700,color:100===e.latest_pass_rate?"var(--success)":e.latest_pass_rate>=80?"var(--warning)":"var(--error)"},children:[e.latest_pass_rate.toFixed(0),"%"]}),(0,s.jsx)("div",{style:{fontSize:"0.75rem",color:"var(--text-secondary)"},children:"Pass Rate"})]})]})]})})})}},5411:(e,t,r)=>{Promise.resolve().then(r.bind(r,4815))},9339:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});var s={callServer:function(){return l.callServer},createServerReference:function(){return i.createServerReference},findSourceMapURL:function(){return n.findSourceMapURL}};for(var a in s)Object.defineProperty(t,a,{enumerable:!0,get:s[a]});let l=r(7304),n=r(4060),i=r(7197)}},e=>{e.O(0,[500,441,794,358],()=>e(e.s=5411)),_N_E=e.O()}]);
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[385],{275:(e,t,a)=>{"use strict";a.d(t,{URSDetailClient:()=>d});var r=a(5155),i=a(2115),s=a(8500),l=a.n(s),n=a(9339);let c=(0,n.createServerReference)("603c9bda0fbb0e0ca172cad506bef77f133f0f1640",n.callServer,void 0,n.findSourceMapURL,"updateURSAction");function d({urs:e,linkedFS:t,linkedRisks:a}){let[s,n]=(0,i.useState)(!1),[d,p]=(0,i.useTransition)(),[m,h]=(0,i.useState)({title:e.title,status:e.status,priority:e.priority,owner:e.owner,category:e.category,business_need:e.business_need,intended_use:e.intended_use,acceptance_criteria:e.acceptance_criteria}),u=e.title.includes("(Undefined)"),g=({value:e,onChange:t,multiline:a,placeholder:i})=>s?a?(0,r.jsx)("textarea",{value:e,onChange:e=>t(e.target.value),rows:4,className:"input",style:{width:"100%",resize:"vertical"}}):(0,r.jsx)("input",{type:"text",value:e,onChange:e=>t(e.target.value),className:"input",style:{width:"100%"}}):(0,r.jsx)("span",{style:{whiteSpace:"pre-wrap",color:"var(--text-secondary)",fontStyle:e?"normal":"italic"},children:e||i||"Not defined"}),x=({value:e,onChange:t,options:a})=>s?(0,r.jsx)("select",{value:e,onChange:e=>t(e.target.value),className:"input",children:a.map(e=>(0,r.jsx)("option",{value:e.value,children:e.label},e.value))}):(0,r.jsx)("span",{style:{textTransform:"capitalize"},children:e});return(0,r.jsxs)("div",{children:[(0,r.jsxs)("header",{className:"page-header",children:[(0,r.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:"1rem",marginBottom:"0.5rem",flexWrap:"wrap"},children:[(0,r.jsx)("code",{style:{fontSize:"1.5rem",fontWeight:700,color:"var(--success)",background:"rgba(16, 185, 129, 0.1)",padding:"0.5rem 1rem",borderRadius:"8px"},children:e.id}),s?(0,r.jsx)(x,{value:m.status,onChange:e=>h({...m,status:e}),options:[{value:"draft",label:"Draft"},{value:"review",label:"Review"},{value:"approved",label:"Approved"}]}):(0,r.jsx)("span",{className:`badge ${"approved"===e.status?"badge-success":"badge-warning"}`,children:m.status}),s?(0,r.jsx)(x,{value:m.priority,onChange:e=>h({...m,priority:e}),options:[{value:"critical",label:"Critical"},{value:"high",label:"High"},{value:"medium",label:"Medium"},{value:"low",label:"Low"}]}):(0,r.jsx)("span",{className:"badge",style:{background:"var(--bg-hover)"},children:m.priority}),u&&!s&&(0,r.jsx)("span",{className:"badge",style:{background:"rgba(239, 68, 68, 0.2)",color:"var(--error)"},children:"Needs Definition"}),(0,r.jsx)("div",{style:{marginLeft:"auto",display:"flex",gap:"0.5rem"},children:s?(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("button",{onClick:()=>{h({title:e.title,status:e.status,priority:e.priority,owner:e.owner,category:e.category,business_need:e.business_need,intended_use:e.intended_use,acceptance_criteria:e.acceptance_criteria}),n(!1)},className:"btn",disabled:d,children:"Cancel"}),(0,r.jsx)("button",{onClick:()=>{p(async()=>{await c(e.id,m),n(!1)})},className:"btn btn-primary",disabled:d,children:d?"Saving...":"\uD83D\uDCBE Save"})]}):(0,r.jsx)("button",{onClick:()=>n(!0),className:"btn btn-primary",children:"✏️ Edit"})})]}),s?(0,r.jsx)("input",{type:"text",value:m.title,onChange:e=>h({...m,title:e.target.value}),className:"input",style:{fontSize:"1.5rem",fontWeight:700,width:"100%",marginBottom:"0.5rem"}}):(0,r.jsx)("h1",{className:"page-title",children:m.title}),(0,r.jsxs)("p",{className:"page-subtitle",children:["User Requirement Specification • Owner: ",s?(0,r.jsx)("input",{type:"text",value:m.owner,onChange:e=>h({...m,owner:e.target.value}),className:"input",style:{width:"200px",display:"inline-block"}}):m.owner]})]}),u&&!s&&(0,r.jsx)("div",{className:"card",style:{marginBottom:"1.5rem",background:"rgba(239, 68, 68, 0.1)",borderLeft:"4px solid var(--error)"},children:(0,r.jsxs)("p",{style:{margin:0,color:"var(--error)"},children:["⚠️ This URS was auto-created from FS references. Click ",(0,r.jsx)("strong",{children:"Edit"})," to define its details."]})}),(0,r.jsxs)("div",{className:"card",style:{marginBottom:"1.5rem"},children:[(0,r.jsx)("h2",{className:"card-title",children:"\uD83D\uDD17 Traceability"}),(0,r.jsxs)("div",{style:{display:"flex",gap:"2rem",flexWrap:"wrap"},children:[(0,r.jsx)(o,{label:"Functional Specs",count:t.length,color:"var(--warning)"}),(0,r.jsx)(o,{label:"Test Scenarios",count:t.reduce((e,t)=>e+t.scenarios.length,0),color:"var(--accent)"}),(0,r.jsx)(o,{label:"Risk Assessments",count:a.length,color:"#f97316"})]})]}),(0,r.jsxs)("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"1.5rem"},children:[(0,r.jsxs)("div",{className:"card",children:[(0,r.jsx)("h2",{className:"card-title",children:"\uD83D\uDCCB Business Need"}),(0,r.jsx)("div",{style:{lineHeight:1.7},children:(0,r.jsx)(g,{value:m.business_need,onChange:e=>h({...m,business_need:e}),multiline:!0,placeholder:"Not defined"})})]}),(0,r.jsxs)("div",{className:"card",children:[(0,r.jsx)("h2",{className:"card-title",children:"\uD83C\uDFAF Intended Use"}),(0,r.jsx)("div",{style:{lineHeight:1.7},children:(0,r.jsx)(g,{value:m.intended_use,onChange:e=>h({...m,intended_use:e}),multiline:!0,placeholder:"Not defined"})})]})]}),(0,r.jsxs)("div",{className:"card",style:{marginTop:"1.5rem"},children:[(0,r.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"1rem"},children:[(0,r.jsx)("h2",{className:"card-title",style:{margin:0},children:"✅ Acceptance Criteria"}),s&&(0,r.jsx)("button",{onClick:()=>h({...m,acceptance_criteria:[...m.acceptance_criteria,""]}),className:"btn",style:{padding:"0.25rem 0.75rem"},children:"+ Add"})]}),0===m.acceptance_criteria.length?(0,r.jsx)("p",{style:{color:"var(--text-secondary)",fontStyle:"italic"},children:"No acceptance criteria defined"}):s?(0,r.jsx)("div",{style:{display:"grid",gap:"0.5rem"},children:m.acceptance_criteria.map((e,t)=>(0,r.jsxs)("div",{style:{display:"flex",gap:"0.5rem"},children:[(0,r.jsx)("input",{type:"text",value:e,onChange:e=>{let a=[...m.acceptance_criteria];a[t]=e.target.value,h({...m,acceptance_criteria:a})},className:"input",style:{flex:1},placeholder:`Criterion ${t+1}`}),(0,r.jsx)("button",{onClick:()=>h({...m,acceptance_criteria:m.acceptance_criteria.filter((e,a)=>a!==t)}),className:"btn",style:{padding:"0.5rem"},children:"\xd7"})]},t))}):(0,r.jsx)("ul",{style:{margin:0,paddingLeft:"1.5rem"},children:m.acceptance_criteria.map((e,t)=>(0,r.jsx)("li",{style:{marginBottom:"0.5rem",color:"var(--text-secondary)"},children:e},t))})]}),(0,r.jsxs)("div",{className:"card",style:{marginTop:"1.5rem"},children:[(0,r.jsx)("h2",{className:"card-title",children:"⚙️ Linked Functional Specifications"}),0===t.length?(0,r.jsx)("p",{style:{color:"var(--text-secondary)"},children:"No FS linked yet"}):(0,r.jsx)("div",{style:{display:"grid",gap:"1rem"},children:t.map(e=>(0,r.jsx)(l(),{href:`/specs/${e.id}`,style:{textDecoration:"none"},children:(0,r.jsx)("div",{style:{padding:"1rem",background:"var(--bg-hover)",borderRadius:"8px",borderLeft:"4px solid var(--warning)"},children:(0,r.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:"0.75rem"},children:[(0,r.jsx)("code",{style:{fontWeight:600,color:"var(--warning)"},children:e.id}),(0,r.jsx)("span",{style:{color:"var(--text-primary)"},children:e.title}),(0,r.jsxs)("span",{className:"badge badge-success",style:{marginLeft:"auto"},children:[e.scenario_count," tests"]})]})})},e.id))})]})]})}function o({label:e,count:t,color:a}){return(0,r.jsxs)("div",{children:[(0,r.jsx)("div",{style:{fontSize:"0.75rem",color:"var(--text-secondary)",marginBottom:"0.25rem"},children:e}),(0,r.jsx)("div",{style:{fontSize:"1.5rem",fontWeight:700,color:a},children:t})]})}},6164:(e,t,a)=>{Promise.resolve().then(a.t.bind(a,8500,23)),Promise.resolve().then(a.bind(a,8220)),Promise.resolve().then(a.bind(a,8169)),Promise.resolve().then(a.bind(a,275))},8169:(e,t,a)=>{"use strict";a.d(t,{ScenarioList:()=>l});var r=a(5155),i=a(2115);function s({scenario:e,isHighlighted:t}){return(0,r.jsxs)("div",{style:{padding:"1rem",background:t?"rgba(96, 165, 250, 0.1)":"var(--bg-hover)",borderRadius:"8px",border:t?"2px solid var(--accent)":"1px solid var(--border)"},children:[(0,r.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:"0.75rem",marginBottom:"0.75rem"},children:[(0,r.jsx)("span",{style:{color:"var(--accent)"},children:"\uD83E\uDDEA"}),(0,r.jsx)("span",{style:{fontWeight:600},children:e.name}),e.tags.length>0&&(0,r.jsx)("span",{style:{marginLeft:"auto",fontSize:"0.75rem",color:"var(--text-secondary)"},children:e.tags.join(" ")})]}),(0,r.jsx)("div",{style:{fontFamily:"monospace",fontSize:"0.8125rem",lineHeight:1.6},children:e.steps.map((e,t)=>{var a;return(0,r.jsx)("div",{style:{color:(a=e).startsWith("Given")?"#a78bfa":a.startsWith("When")?"#60a5fa":a.startsWith("Then")?"#34d399":"var(--text-secondary)"},children:e},t)})})]})}function l({scenarios:e,highlightScenario:t}){let a=(0,i.useRef)(null);return(0,i.useEffect)(()=>{t&&a.current&&setTimeout(()=>{a.current?.scrollIntoView({behavior:"smooth",block:"center"})},100)},[t]),(0,r.jsx)("div",{style:{display:"grid",gap:"0.75rem"},children:e.map((e,i)=>{let l=t===e.name;return(0,r.jsx)("div",{ref:l?a:void 0,children:(0,r.jsx)(s,{scenario:e,isHighlighted:l})},i)})})}a(8500)},8220:(e,t,a)=>{"use strict";a.d(t,{RiskDetailClient:()=>d});var r=a(5155),i=a(2115),s=a(8500),l=a.n(s),n=a(9339);let c=(0,n.createServerReference)("6019bc063222ae2970a4725211376e4841d01aea8b",n.callServer,void 0,n.findSourceMapURL,"updateRiskAction");function d({risk:e,linkedFS:t}){let[a,s]=(0,i.useState)(!1),[n,d]=(0,i.useTransition)(),[m,h]=(0,i.useState)({title:e.title,status:e.status,category:e.category,impact:e.impact,probability:e.probability,risk_level:e.risk_level,residual_risk:e.residual_risk}),u=e.title.includes("(Undefined)");return(0,r.jsxs)("div",{children:[(0,r.jsxs)("header",{className:"page-header",children:[(0,r.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:"1rem",marginBottom:"0.5rem",flexWrap:"wrap"},children:[(0,r.jsx)("code",{style:{fontSize:"1.5rem",fontWeight:700,color:"#f97316",background:"rgba(249, 115, 22, 0.1)",padding:"0.5rem 1rem",borderRadius:"8px"},children:e.id}),a?(0,r.jsx)(({value:e,onChange:t,options:i})=>a?(0,r.jsx)("select",{value:e,onChange:e=>t(e.target.value),className:"input",children:i.map(e=>(0,r.jsx)("option",{value:e.value,children:e.label},e.value))}):(0,r.jsx)("span",{style:{textTransform:"capitalize"},children:e}),{value:m.status,onChange:e=>h({...m,status:e}),options:[{value:"draft",label:"Draft"},{value:"review",label:"Review"},{value:"approved",label:"Approved"}]}):(0,r.jsx)("span",{className:`badge ${"approved"===e.status?"badge-success":"badge-warning"}`,children:m.status}),(0,r.jsx)(p,{level:m.risk_level}),u&&!a&&(0,r.jsx)("span",{className:"badge",style:{background:"rgba(239, 68, 68, 0.2)",color:"var(--error)"},children:"Needs Definition"}),(0,r.jsx)("div",{style:{marginLeft:"auto",display:"flex",gap:"0.5rem"},children:a?(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("button",{onClick:()=>{h({title:e.title,status:e.status,category:e.category,impact:e.impact,probability:e.probability,risk_level:e.risk_level,residual_risk:e.residual_risk}),s(!1)},className:"btn",disabled:n,children:"Cancel"}),(0,r.jsx)("button",{onClick:()=>{d(async()=>{await c(e.id,m),s(!1)})},className:"btn btn-primary",disabled:n,children:n?"Saving...":"\uD83D\uDCBE Save"})]}):(0,r.jsx)("button",{onClick:()=>s(!0),className:"btn btn-primary",children:"✏️ Edit"})})]}),a?(0,r.jsx)("input",{type:"text",value:m.title,onChange:e=>h({...m,title:e.target.value}),className:"input",style:{fontSize:"1.5rem",fontWeight:700,width:"100%",marginBottom:"0.5rem"}}):(0,r.jsx)("h1",{className:"page-title",children:m.title}),(0,r.jsxs)("p",{className:"page-subtitle",children:["Risk Assessment • Category: ",a?(0,r.jsx)("input",{type:"text",value:m.category,onChange:e=>h({...m,category:e.target.value}),className:"input",style:{width:"200px",display:"inline-block"}}):m.category," • GAMP Category ",e.gamp_category]})]}),u&&!a&&(0,r.jsx)("div",{className:"card",style:{marginBottom:"1.5rem",background:"rgba(239, 68, 68, 0.1)",borderLeft:"4px solid var(--error)"},children:(0,r.jsxs)("p",{style:{margin:0,color:"var(--error)"},children:["⚠️ This Risk was auto-created from FS references. Click ",(0,r.jsx)("strong",{children:"Edit"})," to define its details."]})}),(0,r.jsx)("div",{className:"card",style:{marginBottom:"1.5rem"},children:(0,r.jsxs)("div",{style:{display:"grid",gridTemplateColumns:"repeat(4, 1fr)",gap:"1rem"},children:[(0,r.jsx)(o,{label:"Impact",value:m.impact,isEditing:a,onChange:e=>h({...m,impact:e}),options:["low","medium","high","critical"]}),(0,r.jsx)(o,{label:"Probability",value:m.probability,isEditing:a,onChange:e=>h({...m,probability:e}),options:["low","medium","high"]}),(0,r.jsx)(o,{label:"Risk Level",value:m.risk_level,isEditing:a,onChange:e=>h({...m,risk_level:e}),options:["low","medium","high","critical"]}),(0,r.jsx)(o,{label:"Residual Risk",value:m.residual_risk,isEditing:a,onChange:e=>h({...m,residual_risk:e}),options:["acceptable","unacceptable","pending"]})]})}),(0,r.jsxs)("div",{className:"card",style:{marginBottom:"1.5rem"},children:[(0,r.jsx)("h2",{className:"card-title",children:"⚙️ Linked Functional Specifications"}),(0,r.jsx)("div",{style:{display:"flex",gap:"0.5rem",flexWrap:"wrap"},children:t.map(e=>(0,r.jsx)(l(),{href:`/specs/${e.id}`,children:(0,r.jsxs)("span",{className:"badge",style:{background:"rgba(245, 158, 11, 0.15)",color:"var(--warning)",padding:"0.5rem 1rem"},children:[e.id," - ",e.title]})},e.id))})]}),(0,r.jsxs)("div",{className:"card",style:{marginBottom:"1.5rem"},children:[(0,r.jsx)("h2",{className:"card-title",children:"\uD83D\uDD34 Identified Risks"}),0===e.risks.length?(0,r.jsx)("p",{style:{color:"var(--text-secondary)",fontStyle:"italic"},children:"No risks defined yet"}):(0,r.jsx)("div",{style:{display:"grid",gap:"0.5rem"},children:e.risks.map((e,t)=>(0,r.jsxs)("div",{style:{padding:"0.75rem 1rem",background:"var(--bg-hover)",borderRadius:"6px",display:"flex",alignItems:"center",gap:"1rem"},children:[(0,r.jsx)("code",{style:{fontWeight:600,color:"#f97316"},children:e.id}),(0,r.jsx)("span",{style:{flex:1,color:"var(--text-secondary)"},children:e.description}),(0,r.jsx)(p,{level:e.impact,small:!0})]},t))})]}),(0,r.jsxs)("div",{className:"card",children:[(0,r.jsx)("h2",{className:"card-title",children:"\uD83D\uDEE1️ Mitigations"}),0===e.mitigations.length?(0,r.jsx)("p",{style:{color:"var(--text-secondary)",fontStyle:"italic"},children:"No mitigations defined yet"}):(0,r.jsxs)("table",{className:"table",children:[(0,r.jsx)("thead",{children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("th",{children:"Risk"}),(0,r.jsx)("th",{children:"Control"}),(0,r.jsx)("th",{children:"Test"})]})}),(0,r.jsx)("tbody",{children:e.mitigations.map((e,t)=>(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:(0,r.jsx)("code",{children:e.risk_id})}),(0,r.jsx)("td",{children:e.control}),(0,r.jsx)("td",{style:{color:"var(--text-secondary)"},children:e.test})]},t))})]})]})]})}function o({label:e,value:t,isEditing:a,onChange:i,options:s}){let l=m(t);return(0,r.jsxs)("div",{style:{textAlign:"center",padding:"1rem",background:"var(--bg-hover)",borderRadius:"8px"},children:[(0,r.jsx)("div",{style:{fontSize:"0.75rem",color:"var(--text-secondary)",marginBottom:"0.25rem"},children:e}),a?(0,r.jsx)("select",{value:t,onChange:e=>i(e.target.value),className:"input",style:{width:"100%",textAlign:"center"},children:s.map(e=>(0,r.jsx)("option",{value:e,style:{textTransform:"capitalize"},children:e},e))}):(0,r.jsx)("div",{style:{fontSize:"1.25rem",fontWeight:700,color:l,textTransform:"capitalize"},children:t})]})}function p({level:e,small:t}){let a=m(e);return(0,r.jsx)("span",{className:"badge",style:{background:`${a}20`,color:a,padding:t?"0.25rem 0.5rem":"0.5rem 1rem",fontSize:t?"0.75rem":"0.875rem",textTransform:"capitalize"},children:e})}function m(e){switch(e){case"critical":case"unacceptable":return"#dc2626";case"high":return"#f97316";case"medium":case"pending":return"#eab308";case"low":case"acceptable":return"#22c55e";default:return"var(--text-secondary)"}}},9339:(e,t,a)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r={callServer:function(){return s.callServer},createServerReference:function(){return n.createServerReference},findSourceMapURL:function(){return l.findSourceMapURL}};for(var i in r)Object.defineProperty(t,i,{enumerable:!0,get:r[i]});let s=a(7304),l=a(4060),n=a(7197)}},e=>{e.O(0,[500,441,794,358],()=>e(e.s=6164)),_N_E=e.O()}]);