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
@@ -1,4 +1,4 @@
1
- # Revert changes in the current working tree back to the last commit.
1
+ # Move current working tree changes into a recoverable stash.
2
2
  # Usage: revert-phase.sh [phase-name]
3
3
 
4
4
  set -euo pipefail
@@ -7,11 +7,6 @@ PHASE="${1:-unknown}"
7
7
 
8
8
  echo "[$PHASE] ⚠️ Reverting changes due to failure..."
9
9
 
10
- # Stash any changes and drop them
11
- git stash push -m "code-archaeology-revert-$PHASE" --include-untracked 2>/dev/null || true
12
- git stash drop 2>/dev/null || true
10
+ git stash push -m "code-archaeology-revert-$PHASE" --include-untracked >/dev/null 2>&1 || true
13
11
 
14
- # Reset to HEAD
15
- git reset --hard HEAD
16
-
17
- echo "[$PHASE] ✅ Reverted to last commit"
12
+ echo "[$PHASE] Changes preserved in git stash"
@@ -0,0 +1,51 @@
1
+ # Update expedition status in session.json
2
+ # Usage: update-expedition.ps1 <phase> <status> [findings_count] [error_message]
3
+
4
+ $ErrorActionPreference = 'Stop'
5
+
6
+ $PHASE = $args[0]
7
+ $STATUS = $args[1]
8
+ $FINDINGS = if ($args[2]) { [int]$args[2] } else { 0 }
9
+ $ERROR_MSG = if ($args[3]) { $args[3] } else { "" }
10
+
11
+ $ARCHAEOLOGY_DIR = ".archaeology"
12
+ $SESSION_FILE = "$ARCHAEOLOGY_DIR/session.json"
13
+
14
+ if (!(Test-Path "$SESSION_FILE")) {
15
+ Write-Error "Error: session.json not found. Run init.ps1 first."
16
+ exit 1
17
+ }
18
+
19
+ $NOW = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
20
+
21
+ $session = Get-Content "$SESSION_FILE" -Raw | ConvertFrom-Json
22
+
23
+ foreach ($expedition in $session.expeditions) {
24
+ if ($expedition.phase -eq $PHASE) {
25
+ $expedition.status = $STATUS
26
+ $expedition.findings_count = $FINDINGS
27
+ if ($STATUS -eq "completed" -or $STATUS -eq "done") {
28
+ $expedition | Add-Member -MemberType NoteProperty -Name "completed_at" -Value $NOW -Force
29
+ }
30
+ if ($ERROR_MSG) {
31
+ $expedition | Add-Member -MemberType NoteProperty -Name "error" -Value $ERROR_MSG -Force
32
+ } else {
33
+ if ($expedition.PSObject.Properties["error"]) {
34
+ $expedition.PSObject.Properties.Remove("error")
35
+ }
36
+ }
37
+ }
38
+ }
39
+
40
+ $session.updated_at = $NOW
41
+
42
+ # Update total findings
43
+ $total = 0
44
+ foreach ($expedition in $session.expeditions) {
45
+ $total += $expedition.findings_count
46
+ }
47
+ $session.total_findings = $total
48
+
49
+ $session | ConvertTo-Json -Depth 10 | Set-Content "$SESSION_FILE" -Encoding UTF8
50
+
51
+ Write-Host "[$PHASE] Updated status: $STATUS (findings: $FINDINGS)"
@@ -19,6 +19,7 @@ const requiredFiles = [
19
19
  'hooks/opencode/verify-package.sh',
20
20
  'prompts/discovery.md',
21
21
  'schema/expedition-report.json',
22
+ 'docs/index.html',
22
23
  'docs/README.md',
23
24
  'wiki/Home.md',
24
25
  'assets/code-archaeology-banner.svg',
@@ -0,0 +1,35 @@
1
+ # Verify that tests pass and typecheck succeeds.
2
+ # Usage: verify-phase.ps1 [phase-name]
3
+
4
+ $ErrorActionPreference = 'Stop'
5
+
6
+ $PHASE = if ($args[0]) { $args[0] } else { "unknown" }
7
+ $ARCHAEOLOGY_DIR = ".archaeology"
8
+ $SESSION_FILE = "$ARCHAEOLOGY_DIR/session.json"
9
+ $SCRIPT_DIR = Split-Path -Parent $MyInvocation.MyCommand.Path
10
+ . (Join-Path $SCRIPT_DIR "../shared/command-utils.ps1")
11
+
12
+ # Verification commands must not be read from repository-local state.
13
+ # A malicious repository can pre-seed .archaeology/session.json; executing commands
14
+ # from that file would cross the repository-to-workstation trust boundary.
15
+ # Operators who intentionally need custom commands can approve them explicitly via
16
+ # environment variables for the current process.
17
+ $TEST_CMD = if ($env:CODE_ARCHAEOLOGY_TEST_COMMAND) { $env:CODE_ARCHAEOLOGY_TEST_COMMAND } else { "npm test" }
18
+ $TYPECHECK_CMD = if ($env:CODE_ARCHAEOLOGY_TYPECHECK_COMMAND) { $env:CODE_ARCHAEOLOGY_TYPECHECK_COMMAND } else { "npx tsc --noEmit" }
19
+
20
+ Write-Host "[$PHASE] Running test command: $TEST_CMD"
21
+ try {
22
+ Invoke-CheckedCommand -CommandLine $TEST_CMD | Out-Default
23
+ } catch {
24
+ Write-Error "[$PHASE] Tests FAILED"
25
+ exit 1
26
+ }
27
+
28
+ Write-Host "[$PHASE] Running typecheck: $TYPECHECK_CMD"
29
+ try {
30
+ Invoke-CheckedCommand -CommandLine $TYPECHECK_CMD 2>$null | Out-Default
31
+ } catch {
32
+ Write-Warning "[$PHASE] Typecheck reported errors (non-blocking for some languages)"
33
+ }
34
+
35
+ Write-Host "[$PHASE] Verification passed"
@@ -9,13 +9,13 @@ SESSION_FILE="$ARCHAEOLOGY_DIR/session.json"
9
9
 
10
10
  SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
11
11
 
12
- # Source config from session file if jq is available
13
- TEST_CMD="npm test"
14
- TYPECHECK_CMD="npx tsc --noEmit"
15
- if command -v jq >/dev/null 2>&1 && [[ -f "$SESSION_FILE" ]]; then
16
- TEST_CMD=$(jq -r '.config.test_command // "npm test"' "$SESSION_FILE")
17
- TYPECHECK_CMD=$(jq -r '.config.typecheck_command // "npx tsc --noEmit"' "$SESSION_FILE")
18
- fi
12
+ # Verification commands must not be read from repository-local state.
13
+ # A malicious repository can pre-seed .archaeology/session.json; executing commands
14
+ # from that file would cross the repository-to-workstation trust boundary.
15
+ # Operators who intentionally need custom commands can approve them explicitly via
16
+ # environment variables for the current process.
17
+ TEST_CMD="${CODE_ARCHAEOLOGY_TEST_COMMAND:-npm test}"
18
+ TYPECHECK_CMD="${CODE_ARCHAEOLOGY_TYPECHECK_COMMAND:-npx tsc --noEmit}"
19
19
 
20
20
  echo "[$PHASE] Running test command: $TEST_CMD"
21
21
  if ! bash -c "$TEST_CMD"; then
@@ -0,0 +1,100 @@
1
+ # Shared PowerShell command parsing and execution helpers for verification hooks.
2
+
3
+ function Convert-CommandElementToArgument {
4
+ param(
5
+ [Parameter(Mandatory=$true)]
6
+ [System.Management.Automation.Language.CommandElementAst]$Element,
7
+
8
+ [Parameter(Mandatory=$true)]
9
+ [string]$CommandLine
10
+ )
11
+
12
+ if ($Element -is [System.Management.Automation.Language.StringConstantExpressionAst]) {
13
+ return $Element.Value
14
+ }
15
+
16
+ if ($Element -is [System.Management.Automation.Language.ExpandableStringExpressionAst]) {
17
+ return $Element.Value
18
+ }
19
+
20
+ if ($Element -is [System.Management.Automation.Language.CommandParameterAst]) {
21
+ if ($null -ne $Element.Argument) {
22
+ $argumentValue = Convert-CommandElementToArgument -Element $Element.Argument -CommandLine $CommandLine
23
+ return "-$($Element.ParameterName):$argumentValue"
24
+ }
25
+
26
+ return "-$($Element.ParameterName)"
27
+ }
28
+
29
+ throw "Unsupported command syntax in command: $CommandLine"
30
+ }
31
+
32
+ function Split-CommandLine {
33
+ param([Parameter(Mandatory=$true)][string]$CommandLine)
34
+
35
+ [System.Management.Automation.Language.Token[]]$tokens = @()
36
+ [System.Management.Automation.Language.ParseError[]]$parseErrors = @()
37
+ $ast = [System.Management.Automation.Language.Parser]::ParseInput($CommandLine, [ref]$tokens, [ref]$parseErrors)
38
+
39
+ if ($parseErrors.Count -gt 0) {
40
+ $message = ($parseErrors | ForEach-Object { $_.Message }) -join "; "
41
+ throw "Invalid command syntax: $CommandLine. $message"
42
+ }
43
+
44
+ $statements = @($ast.EndBlock.Statements)
45
+ if ($statements.Count -ne 1 -or $statements[0] -isnot [System.Management.Automation.Language.PipelineAst]) {
46
+ throw "Only a single simple command is supported: $CommandLine"
47
+ }
48
+
49
+ $pipeline = [System.Management.Automation.Language.PipelineAst]$statements[0]
50
+ if ($pipeline.PipelineElements.Count -ne 1 -or $pipeline.PipelineElements[0] -isnot [System.Management.Automation.Language.CommandAst]) {
51
+ throw "Only a single simple command is supported: $CommandLine"
52
+ }
53
+
54
+ $commandAst = [System.Management.Automation.Language.CommandAst]$pipeline.PipelineElements[0]
55
+ if ($commandAst.Redirections.Count -gt 0) {
56
+ throw "Command must not contain redirections: $CommandLine"
57
+ }
58
+
59
+ $parts = [System.Collections.Generic.List[string]]::new()
60
+ foreach ($element in $commandAst.CommandElements) {
61
+ $parts.Add((Convert-CommandElementToArgument -Element $element -CommandLine $CommandLine))
62
+ }
63
+
64
+ return $parts.ToArray()
65
+ }
66
+
67
+ function Invoke-CheckedCommand {
68
+ param([Parameter(Mandatory=$true)][string]$CommandLine)
69
+
70
+ [string[]]$parts = @(Split-CommandLine -CommandLine $CommandLine)
71
+ if ($parts.Count -eq 0) {
72
+ throw "Empty command"
73
+ }
74
+
75
+ $command = $parts[0]
76
+ $arguments = @()
77
+ if ($parts.Count -gt 1) {
78
+ $arguments = $parts[1..($parts.Count - 1)]
79
+ }
80
+
81
+ $resolvedCommand = Get-Command -Name $command -ErrorAction Stop | Select-Object -First 1
82
+ $isExternalApplication = $resolvedCommand.CommandType -eq [System.Management.Automation.CommandTypes]::Application
83
+ if ($isExternalApplication) {
84
+ $global:LASTEXITCODE = 0
85
+ }
86
+
87
+ & $command @arguments
88
+
89
+ if ($isExternalApplication) {
90
+ $exitCode = $LASTEXITCODE
91
+ if ($exitCode -ne 0) {
92
+ throw "Command failed with exit code $exitCode: $CommandLine"
93
+ }
94
+ return
95
+ }
96
+
97
+ if (-not $?) {
98
+ throw "Command failed: $CommandLine"
99
+ }
100
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-code-archaeology",
3
- "version": "2.0.2",
3
+ "version": "2.2.1",
4
4
  "description": "Excavate, catalog, and restore a codebase by removing accumulated sediment—dead code, legacy fallbacks, circular dependencies, weak types, and defensive programming slop.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -16,6 +16,10 @@
16
16
  "./plugin": {
17
17
  "types": "./dist/plugin.d.ts",
18
18
  "default": "./dist/plugin.js"
19
+ },
20
+ "./types": {
21
+ "types": "./dist/types.d.ts",
22
+ "default": "./dist/types.js"
19
23
  }
20
24
  },
21
25
  "files": [
@@ -23,17 +27,16 @@
23
27
  "hooks",
24
28
  "commands",
25
29
  "skills",
26
- "plugins",
27
30
  "prompts",
28
31
  "schema",
29
32
  "docs/README.md",
33
+ "docs/index.html",
30
34
  "docs/INSTALL.md",
31
35
  "docs/ARCHITECTURE.md",
32
36
  "docs/RELEASE.md",
33
37
  "docs/SECURITY_AUDIT.md",
34
38
  "wiki",
35
39
  "assets",
36
- ".github",
37
40
  "AGENTS.md",
38
41
  "VERSION",
39
42
  "README.md",
@@ -73,9 +76,19 @@
73
76
  },
74
77
  "license": "MIT",
75
78
  "devDependencies": {
79
+ "@semantic-release/changelog": "^6.0.3",
80
+ "@semantic-release/commit-analyzer": "^13.0.1",
81
+ "@semantic-release/git": "^10.0.1",
82
+ "@semantic-release/github": "^12.0.6",
83
+ "@semantic-release/npm": "^13.1.5",
84
+ "@semantic-release/release-notes-generator": "^14.1.0",
76
85
  "@types/node": "^25.6.0",
86
+ "semantic-release": "^25.0.3",
77
87
  "typescript": "^6.0.3"
78
88
  },
89
+ "overrides": {
90
+ "npm": "^11.14.0"
91
+ },
79
92
  "engines": {
80
93
  "node": ">=18"
81
94
  }
@@ -76,8 +76,8 @@ With `strict_mode: true`, restore also applies MEDIUM confidence findings.
76
76
  | `language` | `typescript` | Primary language |
77
77
  | `mode` | `survey` | `survey`, `excavate`, or `restore` |
78
78
  | `strict_mode` | `false` | Auto-restore medium-confidence findings |
79
- | `test_command` | `npm test` | Test runner command |
80
- | `typecheck_command` | `npx tsc --noEmit` | Type check command |
79
+ | `test_command` | `npm test` | Recorded session default only; verification uses `CODE_ARCHAEOLOGY_TEST_COMMAND` for operator-approved overrides |
80
+ | `typecheck_command` | `npx tsc --noEmit` | Recorded session default only; verification uses `CODE_ARCHAEOLOGY_TYPECHECK_COMMAND` for operator-approved overrides |
81
81
  | `branch_name` | `refactor/archaeology` | Git branch to create |
82
82
 
83
83
  ## Language-Specific Tooling
@@ -0,0 +1,120 @@
1
+ # Code Archaeology Hermes Integration
2
+
3
+ ## Overview
4
+
5
+ Code Archaeology can run on Hermes Agent using cron-based phase execution. Each cron run executes exactly ONE expedition phase with test gates between phases.
6
+
7
+ ## Architecture
8
+
9
+ ```
10
+ Hermes Cron (every 15m)
11
+ → Read .archaeology/session.json
12
+ → Detect current phase (1 of 10)
13
+ → Execute ONE phase:
14
+ survey → excavate → restore (per phase)
15
+ → Run test/typecheck verification
16
+ → Keep or revert changes
17
+ → Advance to next phase
18
+ → STOP (next cron continues)
19
+ ```
20
+
21
+ ## Key Differences from OpenCode
22
+
23
+ | Feature | OpenCode | Hermes |
24
+ |---------|----------|--------|
25
+ | Entry | `/code-archaeology` slash command | `cronjob` |
26
+ | Phases | All in one session | One per cron run |
27
+ | Verification | Between expeditions | Between every phase |
28
+ | Revert | Manual or automatic | Automatic on failure |
29
+ | State | `.archaeology/session.json` | Same file |
30
+ | Background | Plugin stays active | Cron resumes automatically |
31
+
32
+ ## Setup
33
+
34
+ ```bash
35
+ # 1. Install Code Archaeology CLI
36
+ npm install -g opencode-code-archaeology
37
+
38
+ # 2. Setup Hermes runtime
39
+ cd ~/projects/Code-Archaeology
40
+ bash hooks/hermes/setup.sh
41
+
42
+ # 3. Create Hermes cronjob
43
+ hermes cronjob create \
44
+ --name "code-archaeology-expedition" \
45
+ --schedule "every 15m" \
46
+ --workdir ~/projects/Code-Archaeology \
47
+ --prompt "Run one Code Archaeology expedition phase. Read .archaeology/session.json, execute current phase with verification, advance to next phase."
48
+ ```
49
+
50
+ ## Hermes Prompt Template
51
+
52
+ See `skills/hermes/code-archaeology-prompt.md` for the full cron prompt.
53
+
54
+ ## Commands Mapping
55
+
56
+ | OpenCode | Hermes |
57
+ |----------|--------|
58
+ | `/code-archaeology` | `cronjob` runs expedition loop |
59
+ | `/code-archaeology-survey` | `mode = "survey"` in session.json |
60
+ | `/code-archaeology-excavate` | `mode = "excavate"` in session.json |
61
+ | `/code-archaeology-restore` | `mode = "restore"` in session.json |
62
+
63
+ ## Session File Format
64
+
65
+ Hermes uses the same `.archaeology/session.json` format as OpenCode:
66
+
67
+ ```json
68
+ {
69
+ "runtime": "hermes",
70
+ "status": "running",
71
+ "current_phase": "dead-code",
72
+ "completed_phases": ["site-survey"],
73
+ "mode": "survey",
74
+ "repo_path": ".",
75
+ "language": "typescript",
76
+ "test_command": "npm test",
77
+ "typecheck_command": "npx tsc --noEmit",
78
+ "branch_name": "refactor/archaeology",
79
+ "strict_mode": false,
80
+ "started_at": "2026-05-03T14:00:00Z"
81
+ }
82
+ ```
83
+
84
+ ## 10-Phase Expedition Order
85
+
86
+ | # | Phase | Hermes Action |
87
+ |---|-------|---------------|
88
+ | 1 | Site Survey & Baseline | Generate inventory report |
89
+ | 2 | Dead Code Excavation | Catalog unused code |
90
+ | 3 | Legacy Stratum Removal | Identify deprecated shims |
91
+ | 4 | Circular Dependency Cartography | Map dependency cycles |
92
+ | 5 | Type Catalog Consolidation | Find duplicate types |
93
+ | 6 | Type Restoration & Hardening | Flag weak types |
94
+ | 7 | DRY Stratification | Find semantic duplication |
95
+ | 8 | Error Handling Stratigraphy | Review error patterns |
96
+ | 9 | Artifact Cleaning & Documentation | Clean stale artifacts |
97
+ | 10 | Site Preservation & Final Catalog | Generate FINAL_CATALOG.md |
98
+
99
+ ## Safety Model
100
+
101
+ Same as OpenCode:
102
+ - `survey` is default — reports only, zero edits
103
+ - `restore` modifies code only after review
104
+ - Tests and type checks gate each phase
105
+ - Failed restores are automatically reverted
106
+ - Never remove try/catch from I/O boundaries
107
+
108
+ ## Limitations
109
+
110
+ - One phase per cron run (10 phases = ~2.5 hours minimum)
111
+ - No real-time slash command variants
112
+ - Phase order is fixed; cannot skip ahead
113
+ - Memory is session-based; use `memory` tool for persistence
114
+
115
+ ## Future Enhancements
116
+
117
+ - [ ] Auto-detect optimal phase interval based on repo size
118
+ - [ ] Parallel subagent analysis within a phase (Scout + Analyst)
119
+ - [ ] Cross-session memory for language-specific patterns
120
+ - [ ] Integration with Hermes checkpoint/rollback for safe resets
@@ -0,0 +1,167 @@
1
+ # Code Archaeology Hermes Skill
2
+
3
+ ## Installation
4
+
5
+ ```bash
6
+ # Clone Code Archaeology
7
+ git clone https://github.com/Maleick/Code-Archaeology.git
8
+ cd Code-Archaeology
9
+
10
+ # Install dependencies
11
+ npm install
12
+
13
+ # Verify
14
+ npm run typecheck
15
+ bash hooks/verify-package.sh
16
+ ```
17
+
18
+ ## Hermes Setup
19
+
20
+ ### 1. Setup Hermes Runtime
21
+
22
+ ```bash
23
+ cd ~/projects/Code-Archaeology
24
+ bash hooks/hermes/setup.sh
25
+ ```
26
+
27
+ ### 2. Create Session Config
28
+
29
+ ```bash
30
+ # Create session config
31
+ cat > .archaeology/session.json <<'EOF'
32
+ {
33
+ "runtime": "hermes",
34
+ "status": "running",
35
+ "current_phase": "site-survey",
36
+ "completed_phases": [],
37
+ "mode": "survey",
38
+ "repo_path": ".",
39
+ "language": "typescript",
40
+ "test_command": "npm test",
41
+ "typecheck_command": "npx tsc --noEmit",
42
+ "branch_name": "refactor/archaeology",
43
+ "strict_mode": false,
44
+ "started_at": "2026-05-03T14:00:00Z"
45
+ }
46
+ EOF
47
+ ```
48
+
49
+ ### 3. Create Cronjob
50
+
51
+ ```bash
52
+ hermes cronjob create \
53
+ --name "code-archaeology-expedition" \
54
+ --schedule "every 15m" \
55
+ --workdir ~/projects/Code-Archaeology \
56
+ --prompt "Run one Code Archaeology expedition phase. Read .archaeology/session.json, execute current phase with test/typecheck verification, advance to next phase. STOP after one phase."
57
+ ```
58
+
59
+ ## Usage
60
+
61
+ ### Start Expedition
62
+
63
+ ```bash
64
+ # Resume cron (first run auto-initializes)
65
+ hermes cronjob resume code-archaeology-expedition
66
+ ```
67
+
68
+ ### Check Status
69
+
70
+ ```bash
71
+ cat .archaeology/session.json | jq .
72
+ ls .archaeology/expedition*-report.md
73
+ ```
74
+
75
+ ### Change Mode
76
+
77
+ ```bash
78
+ # Switch from survey to excavate
79
+ jq '.mode = "excavate"' .archaeology/session.json > tmp.json && mv tmp.json .archaeology/session.json
80
+
81
+ # Switch from excavate to restore
82
+ jq '.mode = "restore"' .archaeology/session.json > tmp.json && mv tmp.json .archaeology/session.json
83
+ ```
84
+
85
+ ### Stop Expedition
86
+
87
+ ```bash
88
+ # Set stop flag
89
+ jq '.status = "stopped"' .archaeology/session.json > tmp.json && mv tmp.json .archaeology/session.json
90
+
91
+ # Or pause cron
92
+ hermes cronjob pause code-archaeology-expedition
93
+ ```
94
+
95
+ ## Phase Timeline
96
+
97
+ With 15-minute intervals:
98
+ - 10 phases × 15 min = **2.5 hours minimum**
99
+ - Survey mode: ~2.5 hours (reports only)
100
+ - Restore mode: ~2.5 hours + verification time
101
+
102
+ ## Reports Generated
103
+
104
+ | File | Content |
105
+ |------|---------|
106
+ | `.archaeology/site_survey.md` | Baseline inventory |
107
+ | `.archaeology/expedition1-report.md` | Site Survey |
108
+ | `.archaeology/expedition2-report.md` | Dead Code |
109
+ | `.archaeology/expedition3-report.md` | Legacy Removal |
110
+ | `.archaeology/expedition4-report.md` | Dependency Mapping |
111
+ | `.archaeology/expedition5-report.md` | Type Consolidation |
112
+ | `.archaeology/expedition6-report.md` | Type Hardening |
113
+ | `.archaeology/expedition7-report.md` | DRY Stratification |
114
+ | `.archaeology/expedition8-report.md` | Error Handling |
115
+ | `.archaeology/expedition9-report.md` | Artifact Cleaning |
116
+ | `.archaeology/FINAL_CATALOG.md` | Complete summary |
117
+ | `.archaeology/patches/*.patch` | Mock patches (excavate mode) |
118
+
119
+ ## Safety
120
+
121
+ Same as OpenCode:
122
+ - Survey mode: **zero file changes outside `.archaeology/`**
123
+ - Restore mode: **test-gated, auto-revert on failure**
124
+ - Never removes try/catch from I/O boundaries
125
+ - Never guesses types; flags for human review
126
+
127
+ ## Troubleshooting
128
+
129
+ ### Cron not running
130
+
131
+ ```bash
132
+ hermes cronjob list
133
+ hermes cronjob log code-archaeology-expedition
134
+ ```
135
+
136
+ ### Phase blocked
137
+
138
+ ```bash
139
+ # Check blocker
140
+ cat .archaeology/session.json | jq '.flags.blocked_reason'
141
+
142
+ # Reset and retry
143
+ jq '.status = "running" | del(.flags.blocked_reason)' .archaeology/session.json > tmp.json && mv tmp.json .archaeology/session.json
144
+ ```
145
+
146
+ ### Reports empty
147
+
148
+ - Ensure `mode` is set correctly in session.json
149
+ - Check that language tools are installed (`knip`, `madge`, etc.)
150
+ - Run `bash hooks/opencode/init.sh` to reinitialize
151
+
152
+ ## Comparison with OpenCode
153
+
154
+ | Feature | OpenCode | Hermes |
155
+ |---------|----------|--------|
156
+ | Entry | `/code-archaeology` | Cronjob |
157
+ | Phases | All in one session | One per 15-min cron |
158
+ | Real-time | Yes | Delayed |
159
+ | Slash variants | 3 commands | Mode flag in session |
160
+ | Background | Plugin active | Native cron |
161
+ | State | `.archaeology/session.json` | Same |
162
+
163
+ ## Links
164
+
165
+ - Code Archaeology repo: https://github.com/Maleick/Code-Archaeology
166
+ - Hermes docs: https://hermes-agent.nousresearch.com/docs
167
+ - OpenCode plugin: `opencode-code-archaeology`