opencode-code-archaeology 2.0.2 → 2.2.0
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.
- package/.github/pull_request_template.md +1 -0
- package/.github/workflows/release.yml +46 -0
- package/AGENTS.md +42 -10
- package/CHANGELOG.md +59 -0
- package/CONTRIBUTING.md +2 -0
- package/INSTALL.md +90 -20
- package/README.md +90 -29
- package/VERSION +1 -1
- package/assets/code-archaeology-banner.svg +173 -44
- package/commands/code-archaeology.md +7 -5
- package/dist/cli.js +28 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -17
- package/dist/index.js.map +1 -1
- package/dist/platform.d.ts +4 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +11 -0
- package/dist/platform.js.map +1 -0
- package/dist/plugin.d.ts +2 -2
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +2 -1
- package/dist/plugin.js.map +1 -1
- package/dist/runtime.d.ts +18 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +49 -0
- package/dist/runtime.js.map +1 -0
- package/dist/types.d.ts +1 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/docs/ARCHITECTURE.md +41 -10
- package/docs/INSTALL.md +50 -11
- package/docs/README.md +37 -9
- package/docs/RELEASE.md +20 -16
- package/docs/index.html +740 -0
- package/hooks/hermes/runner.ps1 +247 -0
- package/hooks/hermes/runner.sh +262 -0
- package/hooks/hermes/setup.ps1 +41 -0
- package/hooks/hermes/setup.sh +41 -0
- package/hooks/opencode/init.ps1 +83 -0
- package/hooks/opencode/revert-phase.ps1 +12 -0
- package/hooks/opencode/revert-phase.sh +3 -8
- package/hooks/opencode/update-expedition.ps1 +51 -0
- package/hooks/opencode/verify-package.sh +1 -0
- package/hooks/opencode/verify-phase.ps1 +35 -0
- package/hooks/opencode/verify-phase.sh +7 -7
- package/hooks/shared/command-utils.ps1 +100 -0
- package/package.json +16 -2
- package/skills/code-archaeology/SKILL.md +2 -2
- package/skills/hermes/INTEGRATION.md +120 -0
- package/skills/hermes/README.md +167 -0
- package/skills/hermes/code-archaeology-prompt.md +203 -0
- package/wiki/Expedition-Workflow.md +3 -1
- package/wiki/Home.md +2 -2
- package/wiki/Installation.md +2 -0
- package/wiki/Release-Process.md +5 -5
- package/plugins/code-archaeology.ts +0 -8
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
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)"
|
|
@@ -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
|
-
#
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
|
3
|
+
"version": "2.2.0",
|
|
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,10 +27,10 @@
|
|
|
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",
|
|
@@ -73,9 +77,19 @@
|
|
|
73
77
|
},
|
|
74
78
|
"license": "MIT",
|
|
75
79
|
"devDependencies": {
|
|
80
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
81
|
+
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
82
|
+
"@semantic-release/git": "^10.0.1",
|
|
83
|
+
"@semantic-release/github": "^12.0.6",
|
|
84
|
+
"@semantic-release/npm": "^13.1.5",
|
|
85
|
+
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
76
86
|
"@types/node": "^25.6.0",
|
|
87
|
+
"semantic-release": "^25.0.3",
|
|
77
88
|
"typescript": "^6.0.3"
|
|
78
89
|
},
|
|
90
|
+
"overrides": {
|
|
91
|
+
"npm": "^11.14.0"
|
|
92
|
+
},
|
|
79
93
|
"engines": {
|
|
80
94
|
"node": ">=18"
|
|
81
95
|
}
|
|
@@ -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` |
|
|
80
|
-
| `typecheck_command` | `npx tsc --noEmit` |
|
|
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`
|