get-shit-done-cc 1.20.2 → 1.20.4

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.
@@ -382,12 +382,25 @@ node ~/.claude/get-shit-done/bin/gsd-tools.cjs state record-session \
382
382
  --stopped-at "Completed ${PHASE}-${PLAN}-PLAN.md"
383
383
  ```
384
384
 
385
+ ```bash
386
+ # Update ROADMAP.md progress for this phase (plan counts, status)
387
+ node ~/.claude/get-shit-done/bin/gsd-tools.cjs roadmap update-plan-progress "${PHASE_NUMBER}"
388
+
389
+ # Mark completed requirements from PLAN.md frontmatter
390
+ # Extract the `requirements` array from the plan's frontmatter, then mark each complete
391
+ node ~/.claude/get-shit-done/bin/gsd-tools.cjs requirements mark-complete ${REQ_IDS}
392
+ ```
393
+
394
+ **Requirement IDs:** Extract from the PLAN.md frontmatter `requirements:` field (e.g., `requirements: [AUTH-01, AUTH-02]`). Pass all IDs to `requirements mark-complete`. If the plan has no requirements field, skip this step.
395
+
385
396
  **State command behaviors:**
386
397
  - `state advance-plan`: Increments Current Plan, detects last-plan edge case, sets status
387
398
  - `state update-progress`: Recalculates progress bar from SUMMARY.md counts on disk
388
399
  - `state record-metric`: Appends to Performance Metrics table
389
400
  - `state add-decision`: Adds to Decisions section, removes placeholders
390
401
  - `state record-session`: Updates Last session timestamp and Stopped At fields
402
+ - `roadmap update-plan-progress`: Updates ROADMAP.md progress table row with PLAN vs SUMMARY counts
403
+ - `requirements mark-complete`: Checks off requirement checkboxes and updates traceability table in REQUIREMENTS.md
391
404
 
392
405
  **Extract decisions from SUMMARY.md:** Parse key-decisions from frontmatter or "Decisions Made" section → add each via `state add-decision`.
393
406
 
@@ -399,7 +412,7 @@ node ~/.claude/get-shit-done/bin/gsd-tools.cjs state add-blocker "Blocker descri
399
412
 
400
413
  <final_commit>
401
414
  ```bash
402
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md
415
+ node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md .planning/REQUIREMENTS.md
403
416
  ```
404
417
 
405
418
  Separate from per-task commits — captures execution results only.
@@ -432,6 +445,7 @@ Plan execution complete when:
432
445
  - [ ] Authentication gates handled and documented
433
446
  - [ ] SUMMARY.md created with substantive content
434
447
  - [ ] STATE.md updated (position, decisions, issues, session)
435
- - [ ] Final metadata commit made
448
+ - [ ] ROADMAP.md updated with plan progress (via `roadmap update-plan-progress`)
449
+ - [ ] Final metadata commit made (includes SUMMARY.md, STATE.md, ROADMAP.md)
436
450
  - [ ] Completion format returned to orchestrator
437
451
  </success_criteria>
@@ -45,6 +45,12 @@ A "complete" codebase with broken wiring is a broken product.
45
45
 
46
46
  - Which phases should connect to which
47
47
  - What each phase provides vs. consumes
48
+
49
+ **Milestone Requirements:**
50
+
51
+ - List of REQ-IDs with descriptions and assigned phases (provided by milestone auditor)
52
+ - MUST map each integration finding to affected requirement IDs where applicable
53
+ - Requirements with no cross-phase wiring MUST be flagged in the Requirements Integration Map
48
54
  </inputs>
49
55
 
50
56
  <verification_process>
@@ -391,6 +397,15 @@ Return structured report to milestone auditor:
391
397
  #### Unprotected Routes
392
398
 
393
399
  {List each with path/reason}
400
+
401
+ #### Requirements Integration Map
402
+
403
+ | Requirement | Integration Path | Status | Issue |
404
+ |-------------|-----------------|--------|-------|
405
+ | {REQ-ID} | {Phase X export → Phase Y import → consumer} | WIRED / PARTIAL / UNWIRED | {specific issue or "—"} |
406
+
407
+ **Requirements with no cross-phase wiring:**
408
+ {List REQ-IDs that exist in a single phase with no integration touchpoints — these may be self-contained or may indicate missing connections}
394
409
  ```
395
410
 
396
411
  </output>
@@ -419,5 +434,7 @@ Return structured report to milestone auditor:
419
434
  - [ ] Orphaned code identified
420
435
  - [ ] Missing connections identified
421
436
  - [ ] Broken flows identified with specific break points
437
+ - [ ] Requirements Integration Map produced with per-requirement wiring status
438
+ - [ ] Requirements with no cross-phase wiring identified
422
439
  - [ ] Structured report returned to auditor
423
440
  </success_criteria>
package/bin/install.js CHANGED
@@ -456,7 +456,16 @@ function convertClaudeToGeminiAgent(content) {
456
456
  }
457
457
 
458
458
  const newFrontmatter = newLines.join('\n').trim();
459
- return `---\n${newFrontmatter}\n---${stripSubTags(body)}`;
459
+
460
+ // Escape ${VAR} patterns in agent body for Gemini CLI compatibility.
461
+ // Gemini's templateString() treats all ${word} patterns as template variables
462
+ // and throws "Template validation failed: Missing required input parameters"
463
+ // when they can't be resolved. GSD agents use ${PHASE}, ${PLAN}, etc. as
464
+ // shell variables in bash code blocks — convert to $VAR (no braces) which
465
+ // is equivalent bash and invisible to Gemini's /\$\{(\w+)\}/g regex.
466
+ const escapedBody = body.replace(/\$\{(\w+)\}/g, '$$$1');
467
+
468
+ return `---\n${newFrontmatter}\n---${stripSubTags(escapedBody)}`;
460
469
  }
461
470
 
462
471
  function convertClaudeToOpencodeFrontmatter(content) {
@@ -41,6 +41,10 @@
41
41
  * roadmap analyze Full roadmap parse with disk status
42
42
  * roadmap update-plan-progress <N> Update progress table row from disk (PLAN vs SUMMARY counts)
43
43
  *
44
+ * Requirements Operations:
45
+ * requirements mark-complete <ids> Mark requirement IDs as complete in REQUIREMENTS.md
46
+ * Accepts: REQ-01,REQ-02 or REQ-01 REQ-02 or [REQ-01, REQ-02]
47
+ *
44
48
  * Milestone Operations:
45
49
  * milestone complete <version> Archive milestone, create MILESTONES.md
46
50
  * [--name <name>]
@@ -3131,6 +3135,75 @@ function cmdRoadmapUpdatePlanProgress(cwd, phaseNum, raw) {
3131
3135
  }, raw, `${summaryCount}/${planCount} ${status}`);
3132
3136
  }
3133
3137
 
3138
+ // ─── Requirements Mark Complete ───────────────────────────────────────────────
3139
+
3140
+ function cmdRequirementsMarkComplete(cwd, reqIdsRaw, raw) {
3141
+ if (!reqIdsRaw || reqIdsRaw.length === 0) {
3142
+ error('requirement IDs required. Usage: requirements mark-complete REQ-01,REQ-02 or REQ-01 REQ-02');
3143
+ }
3144
+
3145
+ // Accept comma-separated, space-separated, or bracket-wrapped: [REQ-01, REQ-02]
3146
+ const reqIds = reqIdsRaw
3147
+ .join(' ')
3148
+ .replace(/[\[\]]/g, '')
3149
+ .split(/[,\s]+/)
3150
+ .map(r => r.trim())
3151
+ .filter(Boolean);
3152
+
3153
+ if (reqIds.length === 0) {
3154
+ error('no valid requirement IDs found');
3155
+ }
3156
+
3157
+ const reqPath = path.join(cwd, '.planning', 'REQUIREMENTS.md');
3158
+ if (!fs.existsSync(reqPath)) {
3159
+ output({ updated: false, reason: 'REQUIREMENTS.md not found', ids: reqIds }, raw, 'no requirements file');
3160
+ return;
3161
+ }
3162
+
3163
+ let reqContent = fs.readFileSync(reqPath, 'utf-8');
3164
+ const updated = [];
3165
+ const notFound = [];
3166
+
3167
+ for (const reqId of reqIds) {
3168
+ let found = false;
3169
+
3170
+ // Update checkbox: - [ ] **REQ-ID** → - [x] **REQ-ID**
3171
+ const checkboxPattern = new RegExp(`(-\\s*\\[)[ ](\\]\\s*\\*\\*${reqId}\\*\\*)`, 'gi');
3172
+ if (checkboxPattern.test(reqContent)) {
3173
+ reqContent = reqContent.replace(checkboxPattern, '$1x$2');
3174
+ found = true;
3175
+ }
3176
+
3177
+ // Update traceability table: | REQ-ID | Phase N | Pending | → | REQ-ID | Phase N | Complete |
3178
+ const tablePattern = new RegExp(`(\\|\\s*${reqId}\\s*\\|[^|]+\\|)\\s*Pending\\s*(\\|)`, 'gi');
3179
+ if (tablePattern.test(reqContent)) {
3180
+ // Re-read since test() advances lastIndex for global regex
3181
+ reqContent = reqContent.replace(
3182
+ new RegExp(`(\\|\\s*${reqId}\\s*\\|[^|]+\\|)\\s*Pending\\s*(\\|)`, 'gi'),
3183
+ '$1 Complete $2'
3184
+ );
3185
+ found = true;
3186
+ }
3187
+
3188
+ if (found) {
3189
+ updated.push(reqId);
3190
+ } else {
3191
+ notFound.push(reqId);
3192
+ }
3193
+ }
3194
+
3195
+ if (updated.length > 0) {
3196
+ fs.writeFileSync(reqPath, reqContent, 'utf-8');
3197
+ }
3198
+
3199
+ output({
3200
+ updated: updated.length > 0,
3201
+ marked_complete: updated,
3202
+ not_found: notFound,
3203
+ total: reqIds.length,
3204
+ }, raw, `${updated.length}/${reqIds.length} requirements marked complete`);
3205
+ }
3206
+
3134
3207
  // ─── Phase Complete (Transition) ──────────────────────────────────────────────
3135
3208
 
3136
3209
  function cmdPhaseComplete(cwd, phaseNum, raw) {
@@ -5078,6 +5151,16 @@ async function main() {
5078
5151
  break;
5079
5152
  }
5080
5153
 
5154
+ case 'requirements': {
5155
+ const subcommand = args[1];
5156
+ if (subcommand === 'mark-complete') {
5157
+ cmdRequirementsMarkComplete(cwd, args.slice(2), raw);
5158
+ } else {
5159
+ error('Unknown requirements subcommand. Available: mark-complete');
5160
+ }
5161
+ break;
5162
+ }
5163
+
5081
5164
  case 'phase': {
5082
5165
  const subcommand = args[1];
5083
5166
  if (subcommand === 'next-decimal') {
@@ -57,6 +57,8 @@ If a phase is missing VERIFICATION.md, flag it as "unverified phase" — this is
57
57
 
58
58
  With phase context collected:
59
59
 
60
+ Extract `MILESTONE_REQ_IDS` from REQUIREMENTS.md traceability table — all REQ-IDs assigned to phases in this milestone.
61
+
60
62
  ```
61
63
  Task(
62
64
  prompt="Check cross-phase integration and E2E flows.
@@ -65,6 +67,11 @@ Phases: {phase_dirs}
65
67
  Phase exports: {from SUMMARYs}
66
68
  API routes: {routes created}
67
69
 
70
+ Milestone Requirements:
71
+ {MILESTONE_REQ_IDS — list each REQ-ID with description and assigned phase}
72
+
73
+ MUST map each integration finding to affected requirement IDs where applicable.
74
+
68
75
  Verify cross-phase wiring and E2E user flows.",
69
76
  subagent_type="gsd-integration-checker",
70
77
  model="{integration_checker_model}"
@@ -77,12 +84,48 @@ Combine:
77
84
  - Phase-level gaps and tech debt (from step 2)
78
85
  - Integration checker's report (wiring gaps, broken flows)
79
86
 
80
- ## 5. Check Requirements Coverage
87
+ ## 5. Check Requirements Coverage (3-Source Cross-Reference)
88
+
89
+ MUST cross-reference three independent sources for each requirement:
90
+
91
+ ### 5a. Parse REQUIREMENTS.md Traceability Table
92
+
93
+ Extract all REQ-IDs mapped to milestone phases from the traceability table:
94
+ - Requirement ID, description, assigned phase, current status, checked-off state (`[x]` vs `[ ]`)
95
+
96
+ ### 5b. Parse Phase VERIFICATION.md Requirements Tables
97
+
98
+ For each phase's VERIFICATION.md, extract the expanded requirements table:
99
+ - Requirement | Source Plan | Description | Status | Evidence
100
+ - Map each entry back to its REQ-ID
101
+
102
+ ### 5c. Extract SUMMARY.md Frontmatter Cross-Check
103
+
104
+ For each phase's SUMMARY.md, extract `requirements-completed` from YAML frontmatter:
105
+ ```bash
106
+ for summary in .planning/phases/*-*/*-SUMMARY.md; do
107
+ node ~/.claude/get-shit-done/bin/gsd-tools.cjs summary-extract "$summary" --fields requirements_completed | jq -r '.requirements_completed'
108
+ done
109
+ ```
110
+
111
+ ### 5d. Status Determination Matrix
112
+
113
+ For each REQ-ID, determine status using all three sources:
114
+
115
+ | VERIFICATION.md Status | SUMMARY Frontmatter | REQUIREMENTS.md | → Final Status |
116
+ |------------------------|---------------------|-----------------|----------------|
117
+ | passed | listed | `[x]` | **satisfied** |
118
+ | passed | listed | `[ ]` | **satisfied** (update checkbox) |
119
+ | passed | missing | any | **partial** (verify manually) |
120
+ | gaps_found | any | any | **unsatisfied** |
121
+ | missing | listed | any | **partial** (verification gap) |
122
+ | missing | missing | any | **unsatisfied** |
123
+
124
+ ### 5e. FAIL Gate and Orphan Detection
125
+
126
+ **REQUIRED:** Any `unsatisfied` requirement MUST force `gaps_found` status on the milestone audit.
81
127
 
82
- For each requirement in REQUIREMENTS.md mapped to this milestone:
83
- - Find owning phase
84
- - Check phase verification status
85
- - Determine: satisfied | partial | unsatisfied
128
+ **Orphan detection:** Requirements present in REQUIREMENTS.md traceability table but absent from ALL phase VERIFICATION.md files MUST be flagged as orphaned. Orphaned requirements are treated as `unsatisfied` — they were assigned but never verified by any phase.
86
129
 
87
130
  ## 6. Aggregate into v{version}-MILESTONE-AUDIT.md
88
131
 
@@ -99,7 +142,14 @@ scores:
99
142
  integration: N/M
100
143
  flows: N/M
101
144
  gaps: # Critical blockers
102
- requirements: [...]
145
+ requirements:
146
+ - id: "{REQ-ID}"
147
+ status: "unsatisfied | partial | orphaned"
148
+ phase: "{assigned phase}"
149
+ claimed_by_plans: ["{plan files that reference this requirement}"]
150
+ completed_by_plans: ["{plan files whose SUMMARY marks it complete}"]
151
+ verification_status: "passed | gaps_found | missing | orphaned"
152
+ evidence: "{specific evidence or lack thereof}"
103
153
  integration: [...]
104
154
  flows: [...]
105
155
  tech_debt: # Non-critical, deferred
@@ -235,8 +285,13 @@ All requirements met. No critical blockers. Accumulated tech debt needs review.
235
285
  <success_criteria>
236
286
  - [ ] Milestone scope identified
237
287
  - [ ] All phase VERIFICATION.md files read
288
+ - [ ] SUMMARY.md `requirements-completed` frontmatter extracted for each phase
289
+ - [ ] REQUIREMENTS.md traceability table parsed for all milestone REQ-IDs
290
+ - [ ] 3-source cross-reference completed (VERIFICATION + SUMMARY + traceability)
291
+ - [ ] Orphaned requirements detected (in traceability but absent from all VERIFICATIONs)
238
292
  - [ ] Tech debt and deferred gaps aggregated
239
- - [ ] Integration checker spawned for cross-phase wiring
240
- - [ ] v{version}-MILESTONE-AUDIT.md created
293
+ - [ ] Integration checker spawned with milestone requirement IDs
294
+ - [ ] v{version}-MILESTONE-AUDIT.md created with structured requirement gap objects
295
+ - [ ] FAIL gate enforced — any unsatisfied requirement forces gaps_found status
241
296
  - [ ] Results presented with actionable next steps
242
297
  </success_criteria>
@@ -48,6 +48,12 @@ This returns all phases with plan/summary counts and disk status. Use this to ve
48
48
  - All phases complete (all plans have summaries)? Check `disk_status === 'complete'` for each.
49
49
  - `progress_percent` should be 100%.
50
50
 
51
+ **Requirements completion check (REQUIRED before presenting):**
52
+
53
+ Parse REQUIREMENTS.md traceability table:
54
+ - Count total v1 requirements vs checked-off (`[x]`) requirements
55
+ - Identify any non-Complete rows in the traceability table
56
+
51
57
  Present:
52
58
 
53
59
  ```
@@ -60,7 +66,24 @@ Includes:
60
66
  - Phase 4: Polish (1/1 plan complete)
61
67
 
62
68
  Total: {phase_count} phases, {total_plans} plans, all complete
69
+ Requirements: {N}/{M} v1 requirements checked off
70
+ ```
71
+
72
+ **If requirements incomplete** (N < M):
73
+
63
74
  ```
75
+ ⚠ Unchecked Requirements:
76
+
77
+ - [ ] {REQ-ID}: {description} (Phase {X})
78
+ - [ ] {REQ-ID}: {description} (Phase {Y})
79
+ ```
80
+
81
+ MUST present 3 options:
82
+ 1. **Proceed anyway** — mark milestone complete with known gaps
83
+ 2. **Run audit first** — `/gsd:audit-milestone` to assess gap severity
84
+ 3. **Abort** — return to development
85
+
86
+ If user selects "Proceed anyway": note incomplete requirements in MILESTONES.md under `### Known Gaps` with REQ-IDs and descriptions.
64
87
 
65
88
  <config-check>
66
89
 
@@ -669,6 +692,9 @@ Milestone completion is successful when:
669
692
  - [ ] STATE.md updated with fresh project reference
670
693
  - [ ] Git tag created (v[X.Y])
671
694
  - [ ] Milestone commit made (includes archive files and deletion)
695
+ - [ ] Requirements completion checked against REQUIREMENTS.md traceability table
696
+ - [ ] Incomplete requirements surfaced with proceed/audit/abort options
697
+ - [ ] Known gaps recorded in MILESTONES.md if user proceeded with incomplete requirements
672
698
  - [ ] User knows next step (/gsd:new-milestone)
673
699
 
674
700
  </success_criteria>
@@ -106,7 +106,7 @@ Execute each wave in sequence. Within a wave: parallel if `PARALLELIZATION=true`
106
106
  prompt="
107
107
  <objective>
108
108
  Execute plan {plan_number} of phase {phase_number}-{phase_name}.
109
- Commit each task atomically. Create SUMMARY.md. Update STATE.md.
109
+ Commit each task atomically. Create SUMMARY.md. Update STATE.md and ROADMAP.md.
110
110
  </objective>
111
111
 
112
112
  <execution_context>
@@ -128,6 +128,7 @@ Execute each wave in sequence. Within a wave: parallel if `PARALLELIZATION=true`
128
128
  - [ ] Each task committed individually
129
129
  - [ ] SUMMARY.md created in plan directory
130
130
  - [ ] STATE.md updated with position and decisions
131
+ - [ ] ROADMAP.md updated with plan progress (via `roadmap update-plan-progress`)
131
132
  </success_criteria>
132
133
  "
133
134
  )
@@ -386,11 +386,21 @@ node ~/.claude/get-shit-done/bin/gsd-tools.cjs roadmap update-plan-progress "${P
386
386
  Counts PLAN vs SUMMARY files on disk. Updates progress table row with correct count and status (`In Progress` or `Complete` with date).
387
387
  </step>
388
388
 
389
+ <step name="update_requirements">
390
+ Mark completed requirements from the PLAN.md frontmatter `requirements:` field:
391
+
392
+ ```bash
393
+ node ~/.claude/get-shit-done/bin/gsd-tools.cjs requirements mark-complete ${REQ_IDS}
394
+ ```
395
+
396
+ Extract requirement IDs from the plan's frontmatter (e.g., `requirements: [AUTH-01, AUTH-02]`). If no requirements field, skip.
397
+ </step>
398
+
389
399
  <step name="git_commit_metadata">
390
400
  Task code already committed per-task. Commit plan metadata:
391
401
 
392
402
  ```bash
393
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md
403
+ node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md .planning/REQUIREMENTS.md
394
404
  ```
395
405
  </step>
396
406
 
@@ -123,19 +123,34 @@ Add new phases to current milestone:
123
123
  ...
124
124
  ```
125
125
 
126
- ## 7. Create Phase Directories
126
+ ## 7. Update REQUIREMENTS.md Traceability Table (REQUIRED)
127
+
128
+ For each REQ-ID assigned to a gap closure phase:
129
+ - Update the Phase column to reflect the new gap closure phase
130
+ - Reset Status to `Pending`
131
+
132
+ Reset checked-off requirements the audit found unsatisfied:
133
+ - Change `[x]` → `[ ]` for any requirement marked unsatisfied in the audit
134
+ - Update coverage count at top of REQUIREMENTS.md
135
+
136
+ ```bash
137
+ # Verify traceability table reflects gap closure assignments
138
+ grep -c "Pending" .planning/REQUIREMENTS.md
139
+ ```
140
+
141
+ ## 8. Create Phase Directories
127
142
 
128
143
  ```bash
129
144
  mkdir -p ".planning/phases/{NN}-{name}"
130
145
  ```
131
146
 
132
- ## 8. Commit Roadmap Update
147
+ ## 9. Commit Roadmap and Requirements Update
133
148
 
134
149
  ```bash
135
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs(roadmap): add gap closure phases {N}-{M}" --files .planning/ROADMAP.md
150
+ node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs(roadmap): add gap closure phases {N}-{M}" --files .planning/ROADMAP.md .planning/REQUIREMENTS.md
136
151
  ```
137
152
 
138
- ## 9. Offer Next Steps
153
+ ## 10. Offer Next Steps
139
154
 
140
155
  ```markdown
141
156
  ## ✓ Gap Closure Phases Created
@@ -250,7 +265,10 @@ becomes:
250
265
  - [ ] Gaps grouped into logical phases
251
266
  - [ ] User confirmed phase plan
252
267
  - [ ] ROADMAP.md updated with new phases
268
+ - [ ] REQUIREMENTS.md traceability table updated with gap closure phase assignments
269
+ - [ ] Unsatisfied requirement checkboxes reset (`[x]` → `[ ]`)
270
+ - [ ] Coverage count updated in REQUIREMENTS.md
253
271
  - [ ] Phase directories created
254
- - [ ] Changes committed
272
+ - [ ] Changes committed (includes REQUIREMENTS.md)
255
273
  - [ ] User knows to run `/gsd:plan-phase` next
256
274
  </success_criteria>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "get-shit-done-cc",
3
- "version": "1.20.2",
3
+ "version": "1.20.4",
4
4
  "description": "A meta-prompting, context engineering and spec-driven development system for Claude Code, OpenCode and Gemini by TÂCHES.",
5
5
  "bin": {
6
6
  "get-shit-done-cc": "bin/install.js"