opencode-code-archaeology 2.0.2 → 2.2.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 (60) hide show
  1. package/AGENTS.md +42 -10
  2. package/CHANGELOG.md +66 -0
  3. package/CONTRIBUTING.md +2 -0
  4. package/INSTALL.md +90 -20
  5. package/README.md +90 -29
  6. package/VERSION +1 -1
  7. package/assets/code-archaeology-banner.svg +173 -44
  8. package/commands/code-archaeology.md +7 -5
  9. package/dist/cli.js +28 -2
  10. package/dist/cli.js.map +1 -1
  11. package/dist/index.d.ts +1 -5
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +1 -17
  14. package/dist/index.js.map +1 -1
  15. package/dist/platform.d.ts +4 -0
  16. package/dist/platform.d.ts.map +1 -0
  17. package/dist/platform.js +11 -0
  18. package/dist/platform.js.map +1 -0
  19. package/dist/plugin.d.ts +2 -2
  20. package/dist/plugin.d.ts.map +1 -1
  21. package/dist/plugin.js +2 -1
  22. package/dist/plugin.js.map +1 -1
  23. package/dist/runtime.d.ts +18 -0
  24. package/dist/runtime.d.ts.map +1 -0
  25. package/dist/runtime.js +49 -0
  26. package/dist/runtime.js.map +1 -0
  27. package/dist/types.d.ts +1 -6
  28. package/dist/types.d.ts.map +1 -1
  29. package/dist/types.js.map +1 -1
  30. package/docs/ARCHITECTURE.md +41 -10
  31. package/docs/INSTALL.md +50 -11
  32. package/docs/README.md +37 -9
  33. package/docs/RELEASE.md +20 -16
  34. package/docs/index.html +740 -0
  35. package/hooks/hermes/runner.ps1 +247 -0
  36. package/hooks/hermes/runner.sh +262 -0
  37. package/hooks/hermes/setup.ps1 +41 -0
  38. package/hooks/hermes/setup.sh +41 -0
  39. package/hooks/opencode/init.ps1 +83 -0
  40. package/hooks/opencode/revert-phase.ps1 +12 -0
  41. package/hooks/opencode/revert-phase.sh +3 -8
  42. package/hooks/opencode/update-expedition.ps1 +51 -0
  43. package/hooks/opencode/verify-package.sh +1 -0
  44. package/hooks/opencode/verify-phase.ps1 +35 -0
  45. package/hooks/opencode/verify-phase.sh +7 -7
  46. package/hooks/shared/command-utils.ps1 +100 -0
  47. package/package.json +16 -3
  48. package/skills/code-archaeology/SKILL.md +2 -2
  49. package/skills/hermes/INTEGRATION.md +120 -0
  50. package/skills/hermes/README.md +167 -0
  51. package/skills/hermes/code-archaeology-prompt.md +203 -0
  52. package/wiki/Expedition-Workflow.md +3 -1
  53. package/wiki/Home.md +2 -2
  54. package/wiki/Installation.md +2 -0
  55. package/wiki/Release-Process.md +6 -6
  56. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -63
  57. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -48
  58. package/.github/pull_request_template.md +0 -26
  59. package/.github/workflows/ci.yml +0 -45
  60. package/plugins/code-archaeology.ts +0 -8
@@ -0,0 +1,247 @@
1
+ # Hermes agent expedition runner - execute one Code Archaeology phase per cron run
2
+ $ErrorActionPreference = 'Stop'
3
+
4
+ $SCRIPT_DIR = Split-Path -Parent $MyInvocation.MyCommand.Path
5
+ $REPO_ROOT = Resolve-Path "$SCRIPT_DIR/../.." | Select-Object -ExpandProperty Path
6
+ $ARCHAEOLOGY_DIR = "$REPO_ROOT/.archaeology"
7
+ $SESSION_FILE = "$ARCHAEOLOGY_DIR/session.json"
8
+
9
+ # Restore mode can execute operator-provided verification commands. Keep the
10
+ # authorization outside repository-controlled files so a malicious checkout
11
+ # cannot enable unattended command execution by shipping .archaeology state.
12
+ $RESTORE_APPROVAL_ENV = "HERMES_RESTORE_APPROVED"
13
+
14
+ New-Item -ItemType Directory -Force -Path "$ARCHAEOLOGY_DIR" | Out-Null
15
+ . (Join-Path $SCRIPT_DIR "../shared/command-utils.ps1")
16
+
17
+ function Block-Session {
18
+ param(
19
+ [string]$Reason,
20
+ [string]$Message = $Reason
21
+ )
22
+ if (Test-Path "$SESSION_FILE") {
23
+ $session = Get-Content "$SESSION_FILE" -Raw | ConvertFrom-Json
24
+ $session.status = "blocked"
25
+ if (!($session.PSObject.Properties["flags"])) {
26
+ $session | Add-Member -MemberType NoteProperty -Name "flags" -Value @{}
27
+ }
28
+ $session.flags.blocked_reason = $Reason
29
+ $session | ConvertTo-Json -Depth 10 | Set-Content "$SESSION_FILE" -Encoding UTF8
30
+ }
31
+ Write-Host "ERROR: $Message" -ForegroundColor Red
32
+ exit 1
33
+ }
34
+
35
+ function Read-SessionString {
36
+ param([object]$Session, [string]$Key)
37
+ if (!($Session.PSObject.Properties[$Key]) -or !($Session.$Key -is [string]) -or [string]::IsNullOrWhiteSpace($Session.$Key)) {
38
+ Block-Session -Reason "invalid session field: $Key" -Message "Invalid Hermes session field: $Key"
39
+ }
40
+ return $Session.$Key
41
+ }
42
+
43
+ function Require-RestoreApproval {
44
+ if ([Environment]::GetEnvironmentVariable($RESTORE_APPROVAL_ENV) -ne "1") {
45
+ Block-Session `
46
+ -Reason "restore mode requires $RESTORE_APPROVAL_ENV=1" `
47
+ -Message "Hermes restore mode is disabled until the operator sets $RESTORE_APPROVAL_ENV=1 outside session.json"
48
+ }
49
+ }
50
+
51
+ function Validate-BranchName {
52
+ param([string]$Branch)
53
+ if ([string]::IsNullOrWhiteSpace($Branch) -or $Branch.StartsWith("-") -or $Branch -match "\s") {
54
+ Block-Session -Reason "invalid branch_name" -Message "Invalid Hermes branch_name: $Branch"
55
+ }
56
+ git check-ref-format --branch "$Branch" *> $null
57
+ if ($LASTEXITCODE -ne 0) {
58
+ Block-Session -Reason "invalid branch_name" -Message "Invalid Hermes branch_name: $Branch"
59
+ }
60
+ }
61
+
62
+ # Phase definitions (fixed order)
63
+ $PHASES = @(
64
+ "site-survey"
65
+ "dead-code"
66
+ "legacy-removal"
67
+ "dependency-mapping"
68
+ "type-consolidation"
69
+ "type-hardening"
70
+ "dry-stratification"
71
+ "error-handling"
72
+ "artifact-cleaning"
73
+ "final-catalog"
74
+ )
75
+
76
+ # Detect current phase from session file
77
+ $current_phase = ""
78
+ if (Test-Path "$SESSION_FILE") {
79
+ $session = Get-Content "$SESSION_FILE" -Raw | ConvertFrom-Json
80
+ if ($session.PSObject.Properties["current_phase"] -and $session.current_phase) {
81
+ $current_phase = $session.current_phase
82
+ } else {
83
+ Block-Session -Reason "invalid session.json" -Message "Invalid Hermes session file: $SESSION_FILE"
84
+ }
85
+ }
86
+
87
+ if (-not $current_phase) {
88
+ $current_phase = $PHASES[0]
89
+ # Initialize session
90
+ $NOW = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
91
+ $session = @{
92
+ runtime = "hermes"
93
+ status = "running"
94
+ current_phase = $current_phase
95
+ completed_phases = @()
96
+ mode = "survey"
97
+ repo_path = "."
98
+ language = "typescript"
99
+ test_command = "npm test"
100
+ typecheck_command = "npx tsc --noEmit"
101
+ branch_name = "refactor/archaeology"
102
+ strict_mode = $false
103
+ started_at = $NOW
104
+ }
105
+ $session | ConvertTo-Json -Depth 10 | Set-Content "$SESSION_FILE" -Encoding UTF8
106
+ Write-Host "Initialized Hermes session. Starting phase: $current_phase"
107
+ }
108
+
109
+ # Find phase index
110
+ $phase_idx = 0
111
+ $phase_found = $false
112
+ for ($i = 0; $i -lt $PHASES.Count; $i++) {
113
+ if ($PHASES[$i] -eq $current_phase) {
114
+ $phase_idx = $i
115
+ $phase_found = $true
116
+ break
117
+ }
118
+ }
119
+
120
+ if (-not $phase_found) {
121
+ Block-Session -Reason "unknown phase: $current_phase" -Message "Unknown Hermes phase: $current_phase"
122
+ }
123
+
124
+ $phase_number = $phase_idx + 1
125
+ $total_phases = $PHASES.Count
126
+
127
+ Write-Host "=== Code Archaeology Hermes Runner ==="
128
+ Write-Host "Phase $phase_number/$total_phases: $current_phase"
129
+ $session = Get-Content "$SESSION_FILE" -Raw | ConvertFrom-Json
130
+ Write-Host "Mode: $(Read-SessionString -Session $session -Key 'mode')"
131
+ Write-Host ""
132
+
133
+ # Run the phase
134
+ Set-Location "$REPO_ROOT"
135
+
136
+ $mode = Read-SessionString -Session $session -Key "mode"
137
+ if ($mode -eq "restore") {
138
+ Require-RestoreApproval
139
+ Block-Session -Reason "restore mode is not implemented in Hermes runner" -Message "Hermes restore mode is not implemented. Use OpenCode restore after reviewing generated patches."
140
+ }
141
+
142
+ # Create branch if needed
143
+ $branch = Read-SessionString -Session $session -Key "branch_name"
144
+ Validate-BranchName -Branch $branch
145
+ git checkout -b "$branch" 2>$null
146
+ if (-not $?) {
147
+ git checkout "$branch"
148
+ }
149
+
150
+ # Execute phase based on mode
151
+ if ($mode -eq "survey") {
152
+ Write-Host "Running SURVEY for phase $current_phase..."
153
+ # Generate reports only, no file changes
154
+ try {
155
+ & "$SCRIPT_DIR/../opencode/init.ps1" 2>$null
156
+ } catch {}
157
+
158
+ # Run phase-specific analysis
159
+ switch ($current_phase) {
160
+ "site-survey" { Write-Host "Generating site survey and baseline inventory..." }
161
+ "dead-code" { Write-Host "Cataloging dead code, unused exports, unreachable functions..." }
162
+ "legacy-removal" { Write-Host "Identifying legacy fallbacks, deprecated shims, compatibility layers..." }
163
+ "dependency-mapping" { Write-Host "Mapping circular dependencies..." }
164
+ "type-consolidation" { Write-Host "Finding duplicate type definitions..." }
165
+ "type-hardening" { Write-Host "Identifying weak types..." }
166
+ "dry-stratification" { Write-Host "Finding semantic duplication..." }
167
+ "error-handling" { Write-Host "Reviewing error-handling patterns..." }
168
+ "artifact-cleaning" { Write-Host "Identifying stale artifacts and documentation gaps..." }
169
+ "final-catalog" { Write-Host "Generating final excavation catalog..." }
170
+ }
171
+
172
+ # Write report
173
+ $report_file = "$ARCHAEOLOGY_DIR/expedition${phase_number}-report.md"
174
+ $reportTimestamp = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
175
+ @"
176
+ # Expedition $phase_number`: $current_phase
177
+
178
+ **Mode:** survey
179
+ **Phase:** $phase_number/$total_phases
180
+ **Runtime:** hermes
181
+ **Timestamp:** $reportTimestamp
182
+
183
+ ## Findings
184
+
185
+ Hermes recorded this phase handoff. It does not perform autonomous static analysis in this hook.
186
+
187
+ ## Recommendations
188
+
189
+ Run the matching Code Archaeology prompt with OpenCode, then keep this report with the reviewed findings.
190
+
191
+ ## Safety Notes
192
+
193
+ - All findings are reports only; no code changes made
194
+ - Review before proceeding to excavate or restore mode
195
+ "@ | Set-Content "$report_file" -Encoding UTF8
196
+
197
+ Write-Host "Report written: $report_file"
198
+
199
+ } elseif ($mode -eq "excavate") {
200
+ Write-Host "Running EXCAVATE for phase $current_phase..."
201
+ # Generate mock patches (no file changes)
202
+ New-Item -ItemType Directory -Force -Path "$ARCHAEOLOGY_DIR/patches" | Out-Null
203
+ $patch_file = "$ARCHAEOLOGY_DIR/patches/expedition${phase_number}-mock.patch"
204
+ @"
205
+ # Patch handoff for $current_phase
206
+ # Hermes does not generate code changes from this hook.
207
+ # Run the matching OpenCode prompt, review the diff, then restore manually.
208
+ "@ | Set-Content "$patch_file" -Encoding UTF8
209
+ Write-Host "Mock patch written: $patch_file"
210
+
211
+ } else {
212
+ Block-Session -Reason "unknown mode: $mode" -Message "Unknown Hermes mode: $mode"
213
+ }
214
+
215
+ # Update session: mark phase complete, advance to next
216
+ $session = Get-Content "$SESSION_FILE" -Raw | ConvertFrom-Json
217
+ $completed = if ($session.PSObject.Properties["completed_phases"]) {
218
+ if ($session.completed_phases -and $session.completed_phases.Count -gt 0) {
219
+ ($session.completed_phases -join ",") + ",$current_phase"
220
+ } else {
221
+ $current_phase
222
+ }
223
+ } else {
224
+ $current_phase
225
+ }
226
+
227
+ $next_phase = ""
228
+ if ($phase_idx -lt ($PHASES.Count - 1)) {
229
+ $next_phase = $PHASES[$phase_idx + 1]
230
+ }
231
+
232
+ $session.completed_phases = $completed -split ","
233
+ $session.current_phase = $next_phase
234
+ $session | ConvertTo-Json -Depth 10 | Set-Content "$SESSION_FILE" -Encoding UTF8
235
+
236
+ if ($next_phase) {
237
+ Write-Host ""
238
+ Write-Host "Phase $current_phase complete. Next: $next_phase"
239
+ Write-Host "STOP. Next cron run will execute phase: $next_phase"
240
+ } else {
241
+ Write-Host ""
242
+ Write-Host "=== ALL PHASES COMPLETE ==="
243
+ Write-Host "Final catalog: $ARCHAEOLOGY_DIR/FINAL_CATALOG.md"
244
+ $session = Get-Content "$SESSION_FILE" -Raw | ConvertFrom-Json
245
+ $session.status = "complete"
246
+ $session | ConvertTo-Json -Depth 10 | Set-Content "$SESSION_FILE" -Encoding UTF8
247
+ }
@@ -0,0 +1,262 @@
1
+ #!/usr/bin/env bash
2
+ # Hermes agent expedition runner — execute one Code Archaeology phase per cron run
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6
+ REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
7
+ ARCHAEOLOGY_DIR="$REPO_ROOT/.archaeology"
8
+ SESSION_FILE="$ARCHAEOLOGY_DIR/session.json"
9
+
10
+ # Restore mode can execute operator-provided verification commands. Keep the
11
+ # authorization outside repository-controlled files so a malicious checkout
12
+ # cannot enable unattended command execution by shipping .archaeology state.
13
+ RESTORE_APPROVAL_ENV="HERMES_RESTORE_APPROVED"
14
+
15
+ mkdir -p "$ARCHAEOLOGY_DIR"
16
+
17
+ block_session() {
18
+ local reason="$1"
19
+ local message="${2:-$reason}"
20
+ echo "ERROR: $message" >&2
21
+ if command -v jq >/dev/null 2>&1 && [[ -f "$SESSION_FILE" ]]; then
22
+ write_session_jq --arg reason "$reason" \
23
+ '.status = "blocked" | .flags = (.flags // {}) | .flags.blocked_reason = $reason' || true
24
+ fi
25
+ exit 1
26
+ }
27
+
28
+ require_jq() {
29
+ if ! command -v jq >/dev/null 2>&1; then
30
+ echo "ERROR: jq is required for Hermes session management" >&2
31
+ exit 1
32
+ fi
33
+ }
34
+
35
+ write_session_jq() {
36
+ local tmp
37
+ tmp=$(mktemp "$ARCHAEOLOGY_DIR/session.json.XXXXXX")
38
+ if jq "$@" "$SESSION_FILE" > "$tmp"; then
39
+ chmod 600 "$tmp" 2>/dev/null || true
40
+ mv -f "$tmp" "$SESSION_FILE"
41
+ else
42
+ rm -f "$tmp"
43
+ return 1
44
+ fi
45
+ }
46
+
47
+ read_session_string() {
48
+ local key="$1"
49
+ if ! jq -er --arg key "$key" '.[$key] | strings | select(test("\\S"))' "$SESSION_FILE" 2>/dev/null; then
50
+ block_session "invalid session field: $key" "Invalid Hermes session field: $key"
51
+ fi
52
+ }
53
+
54
+ require_restore_approval() {
55
+ if [[ "${!RESTORE_APPROVAL_ENV:-}" != "1" ]]; then
56
+ block_session \
57
+ "restore mode requires ${RESTORE_APPROVAL_ENV}=1" \
58
+ "Hermes restore mode is disabled until the operator sets ${RESTORE_APPROVAL_ENV}=1 outside session.json"
59
+ fi
60
+ }
61
+
62
+ validate_branch_name() {
63
+ local branch="$1"
64
+ if [[ -z "$branch" || "$branch" == -* || "$branch" =~ [[:space:]] ]]; then
65
+ block_session "invalid branch_name" "Invalid Hermes branch_name: $branch"
66
+ fi
67
+ if ! git check-ref-format --branch "$branch" >/dev/null 2>&1; then
68
+ block_session "invalid branch_name" "Invalid Hermes branch_name: $branch"
69
+ fi
70
+ }
71
+
72
+ require_jq
73
+
74
+ # Phase definitions (fixed order)
75
+ PHASES=(
76
+ "site-survey"
77
+ "dead-code"
78
+ "legacy-removal"
79
+ "dependency-mapping"
80
+ "type-consolidation"
81
+ "type-hardening"
82
+ "dry-stratification"
83
+ "error-handling"
84
+ "artifact-cleaning"
85
+ "final-catalog"
86
+ )
87
+
88
+ # Detect current phase from session file
89
+ current_phase=""
90
+ if [[ -f "$SESSION_FILE" ]]; then
91
+ if ! current_phase=$(jq -er '.current_phase // empty' "$SESSION_FILE" 2>/dev/null); then
92
+ block_session "invalid session.json" "Invalid Hermes session file: $SESSION_FILE"
93
+ fi
94
+ fi
95
+
96
+ if [[ -z "$current_phase" ]]; then
97
+ current_phase="${PHASES[0]}"
98
+ # Initialize session
99
+ cat > "$SESSION_FILE" <<EOF
100
+ {
101
+ "runtime": "hermes",
102
+ "status": "running",
103
+ "current_phase": "$current_phase",
104
+ "completed_phases": [],
105
+ "mode": "survey",
106
+ "repo_path": ".",
107
+ "language": "typescript",
108
+ "test_command": "npm test",
109
+ "typecheck_command": "npx tsc --noEmit",
110
+ "branch_name": "refactor/archaeology",
111
+ "strict_mode": false,
112
+ "started_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
113
+ }
114
+ EOF
115
+ echo "Initialized Hermes session. Starting phase: $current_phase"
116
+ fi
117
+
118
+ # Find phase index
119
+ phase_idx=0
120
+ phase_found=false
121
+ for i in "${!PHASES[@]}"; do
122
+ if [[ "${PHASES[$i]}" == "$current_phase" ]]; then
123
+ phase_idx=$i
124
+ phase_found=true
125
+ break
126
+ fi
127
+ done
128
+
129
+ if [[ "$phase_found" != true ]]; then
130
+ block_session "unknown phase: $current_phase" "Unknown Hermes phase: $current_phase"
131
+ fi
132
+
133
+ phase_number=$((phase_idx + 1))
134
+ total_phases=${#PHASES[@]}
135
+
136
+ echo "=== Code Archaeology Hermes Runner ==="
137
+ echo "Phase $phase_number/$total_phases: $current_phase"
138
+ echo "Mode: $(read_session_string mode)"
139
+ echo ""
140
+
141
+ # Run the phase
142
+ cd "$REPO_ROOT"
143
+
144
+ mode=$(read_session_string mode)
145
+ if [[ "$mode" == "restore" ]]; then
146
+ require_restore_approval
147
+ block_session \
148
+ "restore mode is not implemented in Hermes runner" \
149
+ "Hermes restore mode is not implemented. Use OpenCode restore after reviewing generated patches."
150
+ fi
151
+
152
+ # Create branch if needed
153
+ branch=$(read_session_string branch_name)
154
+ validate_branch_name "$branch"
155
+ git checkout -b "$branch" 2>/dev/null || git checkout "$branch"
156
+
157
+ # Execute phase based on mode
158
+ if [[ "$mode" == "survey" ]]; then
159
+ echo "Running SURVEY for phase $current_phase..."
160
+ # Generate reports only, no file changes
161
+ bash "$SCRIPT_DIR/../opencode/init.sh" 2>/dev/null || true
162
+
163
+ # Run phase-specific analysis
164
+ case "$current_phase" in
165
+ "site-survey")
166
+ echo "Generating site survey and baseline inventory..."
167
+ ;;
168
+ "dead-code")
169
+ echo "Cataloging dead code, unused exports, unreachable functions..."
170
+ ;;
171
+ "legacy-removal")
172
+ echo "Identifying legacy fallbacks, deprecated shims, compatibility layers..."
173
+ ;;
174
+ "dependency-mapping")
175
+ echo "Mapping circular dependencies..."
176
+ ;;
177
+ "type-consolidation")
178
+ echo "Finding duplicate type definitions..."
179
+ ;;
180
+ "type-hardening")
181
+ echo "Identifying weak types..."
182
+ ;;
183
+ "dry-stratification")
184
+ echo "Finding semantic duplication..."
185
+ ;;
186
+ "error-handling")
187
+ echo "Reviewing error-handling patterns..."
188
+ ;;
189
+ "artifact-cleaning")
190
+ echo "Identifying stale artifacts and documentation gaps..."
191
+ ;;
192
+ "final-catalog")
193
+ echo "Generating final excavation catalog..."
194
+ ;;
195
+ esac
196
+
197
+ # Write report
198
+ report_file="$ARCHAEOLOGY_DIR/expedition${phase_number}-report.md"
199
+ cat > "$report_file" <<EOF
200
+ # Expedition $phase_number: $current_phase
201
+
202
+ **Mode:** survey
203
+ **Phase:** $phase_number/$total_phases
204
+ **Runtime:** hermes
205
+ **Timestamp:** $(date -u +%Y-%m-%dT%H:%M:%SZ)
206
+
207
+ ## Findings
208
+
209
+ Hermes recorded this phase handoff. It does not perform autonomous static analysis in this hook.
210
+
211
+ ## Recommendations
212
+
213
+ Run the matching Code Archaeology prompt with OpenCode, then keep this report with the reviewed findings.
214
+
215
+ ## Safety Notes
216
+
217
+ - All findings are reports only; no code changes made
218
+ - Review before proceeding to excavate or restore mode
219
+ EOF
220
+
221
+ echo "Report written: $report_file"
222
+
223
+ elif [[ "$mode" == "excavate" ]]; then
224
+ echo "Running EXCAVATE for phase $current_phase..."
225
+ # Generate mock patches (no file changes)
226
+ mkdir -p "$ARCHAEOLOGY_DIR/patches"
227
+ patch_file="$ARCHAEOLOGY_DIR/patches/expedition${phase_number}-mock.patch"
228
+ echo "# Patch handoff for $current_phase" > "$patch_file"
229
+ echo "# Hermes does not generate code changes from this hook." >> "$patch_file"
230
+ echo "# Run the matching OpenCode prompt, review the diff, then restore manually." >> "$patch_file"
231
+ echo "Mock patch written: $patch_file"
232
+
233
+ else
234
+ block_session "unknown mode: $mode" "Unknown Hermes mode: $mode"
235
+ fi
236
+
237
+ # Update session: mark phase complete, advance to next
238
+ completed=$(jq -r '.completed_phases | join(",")' "$SESSION_FILE")
239
+ if [[ -n "$completed" ]]; then
240
+ completed="$completed,$current_phase"
241
+ else
242
+ completed="$current_phase"
243
+ fi
244
+
245
+ next_phase=""
246
+ if [[ $phase_idx -lt $((${#PHASES[@]} - 1)) ]]; then
247
+ next_phase="${PHASES[$((phase_idx + 1))]}"
248
+ fi
249
+
250
+ write_session_jq --arg completed "$completed" --arg next "$next_phase" \
251
+ '.completed_phases = ($completed | split(",")) | .current_phase = $next'
252
+
253
+ if [[ -n "$next_phase" ]]; then
254
+ echo ""
255
+ echo "Phase $current_phase complete. Next: $next_phase"
256
+ echo "STOP. Next cron run will execute phase: $next_phase"
257
+ else
258
+ echo ""
259
+ echo "=== ALL PHASES COMPLETE ==="
260
+ echo "Final catalog: $ARCHAEOLOGY_DIR/FINAL_CATALOG.md"
261
+ write_session_jq '.status = "complete"'
262
+ fi
@@ -0,0 +1,41 @@
1
+ # Hermes agent setup - discover Hermes capabilities for Code Archaeology
2
+ $ErrorActionPreference = 'Stop'
3
+
4
+ $SCRIPT_DIR = Split-Path -Parent $MyInvocation.MyCommand.Path
5
+ $REPO_ROOT = Resolve-Path "$SCRIPT_DIR/../.." | Select-Object -ExpandProperty Path
6
+ $ARCHAEOLOGY_DIR = "$REPO_ROOT/.archaeology"
7
+
8
+ New-Item -ItemType Directory -Force -Path "$ARCHAEOLOGY_DIR" | Out-Null
9
+
10
+ # Check if Hermes CLI is available
11
+ $HERMES_AVAILABLE = $false
12
+ try {
13
+ $null = Get-Command hermes -ErrorAction Stop
14
+ $HERMES_AVAILABLE = $true
15
+ } catch {}
16
+
17
+ # Check if we're running inside a Hermes session
18
+ $HERMES_ACTIVE = $false
19
+ if ($env:HERMES_SESSION_ID -or $env:HERMES_CWD -or $env:HERMES_PROVIDER) {
20
+ $HERMES_ACTIVE = $true
21
+ }
22
+
23
+ # Write Hermes runtime config
24
+ $hermesRuntime = @{
25
+ runtime = "hermes"
26
+ available = $HERMES_AVAILABLE
27
+ active_session = $HERMES_ACTIVE
28
+ max_concurrent = 1
29
+ dispatch_method = "cronjob"
30
+ phase_interval = "15m"
31
+ notes = "Code Archaeology runs one expedition phase per cron run. Test gates between phases."
32
+ }
33
+
34
+ $hermesRuntime | ConvertTo-Json -Depth 5 | Set-Content "$ARCHAEOLOGY_DIR/hermes-runtime.json" -Encoding UTF8
35
+
36
+ Write-Host "Hermes runtime configured for Code Archaeology:"
37
+ Write-Host " CLI available: $HERMES_AVAILABLE"
38
+ Write-Host " Active session: $HERMES_ACTIVE"
39
+ Write-Host " Max concurrent: 1 (one phase at a time)"
40
+ Write-Host " Phase interval: 15 minutes"
41
+ Write-Host " Config: $ARCHAEOLOGY_DIR/hermes-runtime.json"
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env bash
2
+ # Hermes agent setup — discover Hermes capabilities for Code Archaeology
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6
+ REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
7
+ ARCHAEOLOGY_DIR="$REPO_ROOT/.archaeology"
8
+
9
+ mkdir -p "$ARCHAEOLOGY_DIR"
10
+
11
+ # Check if Hermes CLI is available
12
+ HERMES_AVAILABLE=false
13
+ if command -v hermes &>/dev/null; then
14
+ HERMES_AVAILABLE=true
15
+ fi
16
+
17
+ # Check if we're running inside a Hermes session
18
+ HERMES_ACTIVE=false
19
+ if [[ -n "${HERMES_SESSION_ID:-}" || -n "${HERMES_CWD:-}" || -n "${HERMES_PROVIDER:-}" ]]; then
20
+ HERMES_ACTIVE=true
21
+ fi
22
+
23
+ # Write Hermes runtime config
24
+ cat > "$ARCHAEOLOGY_DIR/hermes-runtime.json" <<EOF
25
+ {
26
+ "runtime": "hermes",
27
+ "available": $HERMES_AVAILABLE,
28
+ "active_session": $HERMES_ACTIVE,
29
+ "max_concurrent": 1,
30
+ "dispatch_method": "cronjob",
31
+ "phase_interval": "15m",
32
+ "notes": "Code Archaeology runs one expedition phase per cron run. Test gates between phases."
33
+ }
34
+ EOF
35
+
36
+ echo "Hermes runtime configured for Code Archaeology:"
37
+ echo " CLI available: $HERMES_AVAILABLE"
38
+ echo " Active session: $HERMES_ACTIVE"
39
+ echo " Max concurrent: 1 (one phase at a time)"
40
+ echo " Phase interval: 15 minutes"
41
+ echo " Config: $ARCHAEOLOGY_DIR/hermes-runtime.json"
@@ -0,0 +1,83 @@
1
+ # Initialize .archaeology/ directory for Code Archaeology.
2
+
3
+ $ErrorActionPreference = 'Stop'
4
+
5
+ $ARCHAEOLOGY_DIR = ".archaeology"
6
+ $SESSION_FILE = "$ARCHAEOLOGY_DIR/session.json"
7
+
8
+ $SCRIPT_DIR = Split-Path -Parent $MyInvocation.MyCommand.Path
9
+ $RELEASE_ROOT = Resolve-Path "$SCRIPT_DIR/../.." | Select-Object -ExpandProperty Path
10
+ if (Test-Path "$RELEASE_ROOT/VERSION") {
11
+ $PLUGIN_VERSION = (Get-Content "$RELEASE_ROOT/VERSION" -Raw).Trim()
12
+ } else {
13
+ $PLUGIN_VERSION = "dev"
14
+ }
15
+
16
+ $REPO_ROOT = $null
17
+ try {
18
+ $REPO_ROOT = (git rev-parse --show-toplevel 2>$null).Trim()
19
+ } catch {
20
+ Write-Error "Error: not inside a git repository"
21
+ exit 1
22
+ }
23
+ Set-Location "$REPO_ROOT"
24
+
25
+ Write-Host "Code Archaeology v${PLUGIN_VERSION} initializing..."
26
+
27
+ New-Item -ItemType Directory -Force -Path "$ARCHAEOLOGY_DIR" | Out-Null
28
+ New-Item -ItemType Directory -Force -Path "$ARCHAEOLOGY_DIR/patches" | Out-Null
29
+
30
+ # Initialize session.json
31
+ if (!(Test-Path "$SESSION_FILE")) {
32
+ $NOW = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
33
+ $SESSION_ID = "archaeology-$([DateTimeOffset]::UtcNow.ToUnixTimeSeconds())-$PID"
34
+ $BASELINE_COMMIT = "unknown"
35
+ try {
36
+ $BASELINE_COMMIT = (git rev-parse HEAD 2>$null).Trim()
37
+ } catch {}
38
+
39
+ $session = @{
40
+ version = 1
41
+ plugin_version = $PLUGIN_VERSION
42
+ session_id = $SESSION_ID
43
+ config = @{
44
+ repo_path = "."
45
+ language = "typescript"
46
+ mode = "survey"
47
+ strict_mode = $false
48
+ test_command = "npm test"
49
+ typecheck_command = "npx tsc --noEmit"
50
+ branch_name = "refactor/archaeology"
51
+ }
52
+ started_at = $NOW
53
+ updated_at = $NOW
54
+ expeditions = @(
55
+ @{phase = "survey"; name = "Site Survey & Baseline"; status = "pending"; findings_count = 0}
56
+ @{phase = "dead_code"; name = "Dead Code Excavation"; status = "pending"; findings_count = 0}
57
+ @{phase = "legacy"; name = "Legacy Stratum Removal"; status = "pending"; findings_count = 0}
58
+ @{phase = "dependencies"; name = "Circular Dependency Cartography"; status = "pending"; findings_count = 0}
59
+ @{phase = "types_consolidate"; name = "Type Catalog Consolidation"; status = "pending"; findings_count = 0}
60
+ @{phase = "types_harden"; name = "Type Restoration & Hardening"; status = "pending"; findings_count = 0}
61
+ @{phase = "dry"; name = "DRY Stratification"; status = "pending"; findings_count = 0}
62
+ @{phase = "errors"; name = "Error Handling Stratigraphy"; status = "pending"; findings_count = 0}
63
+ @{phase = "polish"; name = "Artifact Cleaning & Documentation"; status = "pending"; findings_count = 0}
64
+ @{phase = "final_verify"; name = "Site Preservation & Final Catalog"; status = "pending"; findings_count = 0}
65
+ )
66
+ total_findings = 0
67
+ auto_fixable_count = 0
68
+ baseline_commit = $BASELINE_COMMIT
69
+ completed = $false
70
+ }
71
+
72
+ $session | ConvertTo-Json -Depth 10 | Set-Content "$SESSION_FILE" -Encoding UTF8
73
+ Write-Host "Initialized $SESSION_FILE"
74
+ } else {
75
+ $NOW = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
76
+ $session = Get-Content "$SESSION_FILE" -Raw | ConvertFrom-Json
77
+ $session.updated_at = $NOW
78
+ $session.plugin_version = $PLUGIN_VERSION
79
+ $session | ConvertTo-Json -Depth 10 | Set-Content "$SESSION_FILE" -Encoding UTF8
80
+ Write-Host "Refreshed $SESSION_FILE"
81
+ }
82
+
83
+ Write-Host "Code Archaeology workspace ready at $ARCHAEOLOGY_DIR"
@@ -0,0 +1,12 @@
1
+ # Move current working tree changes into a recoverable stash.
2
+ # Usage: revert-phase.ps1 [phase-name]
3
+
4
+ $ErrorActionPreference = 'Stop'
5
+
6
+ $PHASE = if ($args[0]) { $args[0] } else { "unknown" }
7
+
8
+ Write-Host "[$PHASE] Reverting changes due to failure..."
9
+
10
+ git stash push -m "code-archaeology-revert-$PHASE" --include-untracked *> $null
11
+
12
+ Write-Host "[$PHASE] Changes preserved in git stash"