wikifier 0.3.0__py3-none-any.whl

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.
wikifier/__init__.py ADDED
@@ -0,0 +1,9 @@
1
+ """
2
+ Wikifier - Agent-first, zero-dependency, self-maintaining codebase documentation system.
3
+
4
+ This package provides cross-platform access to the Wikifier tool.
5
+ """
6
+
7
+ __version__ = "0.3.0"
8
+ __author__ = "Aron Amos"
9
+ __license__ = "MIT"
wikifier/__main__.py ADDED
@@ -0,0 +1,4 @@
1
+ from .cli import main
2
+
3
+ if __name__ == "__main__":
4
+ main()
wikifier/cli.py ADDED
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Wikifier CLI Entry Point
4
+
5
+ Detects the current platform and launches the appropriate Wikifier script.
6
+ This allows users to run `wikifier` after `pip install wikifier`.
7
+ """
8
+
9
+ import os
10
+ import sys
11
+ import platform
12
+ import subprocess
13
+ from pathlib import Path
14
+
15
+ def get_script_path() -> Path:
16
+ """Return the path to the correct platform-specific Wikifier script."""
17
+ package_dir = Path(__file__).parent
18
+ scripts_dir = package_dir / "scripts"
19
+
20
+ system = platform.system().lower()
21
+
22
+ if system == "windows":
23
+ # Prefer PowerShell on Windows
24
+ ps_script = scripts_dir / "wikifier.ps1"
25
+ if ps_script.exists():
26
+ return ps_script
27
+ return scripts_dir / "wikifier.bat"
28
+ else:
29
+ # Linux, macOS, etc.
30
+ return scripts_dir / "wikifier.sh"
31
+
32
+
33
+ def main():
34
+ script_path = get_script_path()
35
+
36
+ if not script_path.exists():
37
+ print(f"Error: Could not find Wikifier script at {script_path}", file=sys.stderr)
38
+ sys.exit(1)
39
+
40
+ system = platform.system().lower()
41
+
42
+ if system == "windows":
43
+ # On Windows, use PowerShell to execute .ps1 or fall back to .bat
44
+ if script_path.suffix == ".ps1":
45
+ cmd = ["powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", str(script_path)] + sys.argv[1:]
46
+ else:
47
+ cmd = [str(script_path)] + sys.argv[1:]
48
+ else:
49
+ # Unix-like: execute the shell script directly
50
+ cmd = [str(script_path)] + sys.argv[1:]
51
+
52
+ try:
53
+ result = subprocess.run(cmd, check=False)
54
+ sys.exit(result.returncode)
55
+ except KeyboardInterrupt:
56
+ sys.exit(130)
57
+ except Exception as e:
58
+ print(f"Failed to launch Wikifier: {e}", file=sys.stderr)
59
+ sys.exit(1)
60
+
61
+
62
+ if __name__ == "__main__":
63
+ main()
@@ -0,0 +1,27 @@
1
+ @echo off
2
+ REM wikifier.bat — Wikifier v0.3 Windows launcher
3
+ REM Delegates to PowerShell for the real implementation (zero external deps).
4
+
5
+ setlocal
6
+
7
+ set SCRIPT_DIR=%~dp0
8
+
9
+ echo Wikifier v0.3 (Windows)
10
+ echo.
11
+
12
+ if exist "%SCRIPT_DIR%wikifier.ps1" (
13
+ powershell -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%wikifier.ps1" %*
14
+ ) else (
15
+ echo [WARNING] wikifier.ps1 not found.
16
+ echo Falling back to basic help...
17
+ echo.
18
+ echo Recommended: Use WSL / Git Bash / MSYS2 and run ./wikifier.sh directly.
19
+ echo Full cross-platform support is in wikifier.sh (bash).
20
+ echo.
21
+ echo Available via PowerShell:
22
+ echo .\wikifier.ps1 help
23
+ echo .\wikifier.ps1 check-changes
24
+ echo .\wikifier.ps1 record-change "path\to\file" "reason here"
25
+ )
26
+
27
+ endlocal
@@ -0,0 +1,166 @@
1
+ # wikifier.ps1 — Wikifier v0.3 PowerShell implementation (Windows)
2
+ # Zero-dependency. Mirrors the most important commands from wikifier.sh
3
+
4
+ param(
5
+ [Parameter(Position=0)]
6
+ [string]$Command = "help",
7
+
8
+ [Parameter(ValueFromRemainingArguments=$true)]
9
+ [string[]]$Arguments
10
+ )
11
+
12
+ $ErrorActionPreference = "Stop"
13
+ $WikifierRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
14
+ $Staging = Join-Path $WikifierRoot ".wikifier_staging"
15
+ $JournalRoot = Join-Path $WikifierRoot "journal"
16
+ $HealthFile = Join-Path $WikifierRoot "file_health.md"
17
+ $PendingFile = Join-Path $WikifierRoot "pending_updates.md"
18
+ $LastCheck = Join-Path $Staging ".last_check"
19
+ $Monitored = Join-Path $WikifierRoot "monitored_paths.txt"
20
+ $Excludes = Join-Path $WikifierRoot "exclude_patterns.txt"
21
+
22
+ New-Item -ItemType Directory -Path $Staging -Force | Out-Null
23
+
24
+ function Write-Log { param([string]$m) Write-Host "[wikifier] $m" }
25
+ function Write-Err { param([string]$m) Write-Host "[wikifier ERROR] $m" -ForegroundColor Red }
26
+
27
+ function Get-Timestamp { Get-Date -Format "yyyy-MM-dd HH:mm:ss" }
28
+
29
+ function Upsert-Health {
30
+ param([string]$file, [string]$status, [string]$reason = "")
31
+ $now = Get-Timestamp
32
+
33
+ if (-not (Test-Path $HealthFile)) {
34
+ @"
35
+ # Documentation Health Matrix
36
+
37
+ | File | Status | Last Updated | Reason / Intent |
38
+ |------|--------|--------------|-----------------|
39
+ "@ | Set-Content $HealthFile
40
+ }
41
+
42
+ $content = Get-Content $HealthFile -Raw
43
+ $pattern = [regex]::Escape("| $file |")
44
+
45
+ if ($content -match $pattern) {
46
+ $newLine = "| $file | $status | $now | $reason |"
47
+ $content = [regex]::Replace($content, "\| $file \| .*? \| .*? \| .*? \|", $newLine, 1)
48
+ Set-Content $HealthFile $content
49
+ } else {
50
+ Add-Content $HealthFile "| $file | $status | $now | $reason |"
51
+ }
52
+ }
53
+
54
+ function Add-Pending {
55
+ param([string]$file, [string]$msg)
56
+ if (-not (Test-Path $PendingFile)) { " # Pending Updates" | Set-Content $PendingFile }
57
+ Add-Content $PendingFile "- $file`: $msg"
58
+ }
59
+
60
+ function Write-Journal {
61
+ param([string]$action, [string]$file, [string]$reason)
62
+ $datePath = Join-Path $JournalRoot (Get-Date -Format "yyyy/MM")
63
+ New-Item -ItemType Directory -Path $datePath -Force | Out-Null
64
+ $dayFile = Join-Path $datePath ("{0:dd}.md" -f (Get-Date))
65
+ @"
66
+
67
+ ## [$(Get-Timestamp)] $action
68
+ **File:** $file
69
+ **Reason:** $reason
70
+
71
+ "@ | Add-Content $dayFile
72
+ }
73
+
74
+ # ---------------- Commands ----------------
75
+
76
+ switch ($Command.ToLower()) {
77
+ "help" {
78
+ Write-Host @"
79
+ Wikifier v0.3 (PowerShell/Windows)
80
+
81
+ Core:
82
+ check-changes
83
+ record-change <file> "<reason>"
84
+ mark-green <file>
85
+ health
86
+ monitor
87
+ update-maps
88
+ init
89
+
90
+ See wikifier.sh for the full Unix implementation (recommended on WSL/macOS/Linux).
91
+ "@
92
+ }
93
+ "init" {
94
+ if (-not (Test-Path $Monitored)) { "." | Set-Content $Monitored }
95
+ if (-not (Test-Path $Excludes)) {
96
+ @"
97
+ node_modules
98
+ .git
99
+ build
100
+ dist
101
+ "@ | Set-Content $Excludes
102
+ }
103
+ if (-not (Test-Path $HealthFile)) {
104
+ @"
105
+ # Documentation Health Matrix
106
+
107
+ | File | Status | Last Updated | Reason / Intent |
108
+ |------|--------|--------------|-----------------|
109
+ "@ | Set-Content $HealthFile
110
+ }
111
+ Upsert-Health "wikifier.ps1" "🟢 Green" "Windows PowerShell CLI initialised."
112
+ Write-Log "Wikifier Windows state initialised."
113
+ }
114
+ "check-changes" {
115
+ Write-Log "Running change detection (PowerShell)..."
116
+ $last = if (Test-Path $LastCheck) { Get-Content $LastCheck } else { "1970-01-01" }
117
+ $roots = if (Test-Path $Monitored) { Get-Content $Monitored | Where-Object { $_ -notmatch '^\s*#' } } else { @(".") }
118
+
119
+ $changed = 0
120
+ foreach ($root in $roots) {
121
+ if (-not (Test-Path $root)) { continue }
122
+ Get-ChildItem -Path $root -Recurse -File -ErrorAction SilentlyContinue |
123
+ Where-Object { $_.LastWriteTime -gt [datetime]$last } |
124
+ ForEach-Object {
125
+ $rel = $_.FullName.Replace($WikifierRoot, "").TrimStart('\','/')
126
+ if ($rel -match '(\.git|node_modules|Logged_issues|journal|\.wikifier)') { return }
127
+ Upsert-Health $rel "🟡 Yellow" "mtime changed (PowerShell auto-detect)"
128
+ Add-Pending $rel "Auto-detected change on Windows"
129
+ $changed++
130
+ }
131
+ }
132
+ Get-Date -Format "yyyy-MM-dd HH:mm:ss" | Set-Content $LastCheck
133
+ Write-Log "Detected $changed file(s) changed."
134
+ }
135
+ "record-change" {
136
+ $file = $Arguments[0]
137
+ $reason = if ($Arguments.Count -gt 1) { $Arguments[1] } else { "No reason" }
138
+ if (-not $file) { Write-Err "Usage: wikifier record-change <file> <reason>"; exit 1 }
139
+ Upsert-Health $file "🟡 Yellow" $reason
140
+ Add-Pending $file "record-change: $reason"
141
+ Write-Journal "record-change" $file $reason
142
+ Write-Log "Recorded change for $file"
143
+ }
144
+ "mark-green" {
145
+ $file = $Arguments[0]
146
+ if (-not $file) { Write-Err "Usage: wikifier mark-green <file>"; exit 1 }
147
+ Upsert-Health $file "🟢 Green" "Verified on Windows."
148
+ if (Test-Path $PendingFile) {
149
+ (Get-Content $PendingFile) | Where-Object { $_ -notmatch [regex]::Escape($file) } | Set-Content $PendingFile
150
+ }
151
+ Write-Log "🟢 $file marked Green."
152
+ }
153
+ "health" {
154
+ if (Test-Path $HealthFile) { Get-Content $HealthFile } else { Write-Host "Run init or check-changes first." }
155
+ }
156
+ "monitor" {
157
+ Write-Log "Starting heartbeat monitor (Windows PowerShell)..."
158
+ while ($true) {
159
+ & $PSCommandPath check-changes
160
+ Start-Sleep -Seconds 30
161
+ }
162
+ }
163
+ default {
164
+ Write-Err "Unknown command '$Command'. Try 'wikifier help'."
165
+ }
166
+ }
@@ -0,0 +1,498 @@
1
+ #!/bin/bash
2
+ # wikifier.sh — Wikifier v0.3 Core CLI (Zero-Dependency)
3
+ # Agent-first shell tool for codebase documentation health & semantic change tracking.
4
+ #
5
+ # Usage:
6
+ # ./wikifier.sh <command> [args]
7
+ # (Optionally symlink or alias as 'wikifier' in your PATH)
8
+ #
9
+ # Commands implemented:
10
+ # help, check-changes, health, record-change, record-deletion,
11
+ # prepare-edit, mark-green, monitor, update-maps, validate,
12
+ # journal, issues, init
13
+
14
+ set -euo pipefail
15
+
16
+ # ----------------------------- Configuration -----------------------------
17
+ WIKIFIER_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
18
+ LAST_CHECK_FILE="$WIKIFIER_ROOT/.wikifier_staging/.last_check"
19
+ STAGING_DIR="$WIKIFIER_ROOT/.wikifier_staging"
20
+ JOURNAL_ROOT="$WIKIFIER_ROOT/journal"
21
+ LOGGED_ISSUES_ROOT="$WIKIFIER_ROOT/Logged_issues"
22
+ MONITORED_PATHS_FILE="$WIKIFIER_ROOT/monitored_paths.txt"
23
+ EXCLUDE_PATTERNS_FILE="$WIKIFIER_ROOT/exclude_patterns.txt"
24
+ FILE_HEALTH="$WIKIFIER_ROOT/file_health.md"
25
+ PENDING_UPDATES="$WIKIFIER_ROOT/pending_updates.md"
26
+ LIBRARY_MD="$WIKIFIER_ROOT/library.md"
27
+ POLL_INTERVAL="${WIKIFIER_POLL_INTERVAL:-30}"
28
+
29
+ mkdir -p "$STAGING_DIR" "$JOURNAL_ROOT/$(date +%Y/%m)" "$LOGGED_ISSUES_ROOT"
30
+
31
+ # ----------------------------- Helper Functions -----------------------------
32
+
33
+ log() {
34
+ echo "[wikifier] $*"
35
+ }
36
+
37
+ error() {
38
+ echo "[wikifier ERROR] $*" >&2
39
+ }
40
+
41
+ # Get current timestamp in consistent format
42
+ timestamp() {
43
+ date '+%Y-%m-%d %H:%M:%S %Z'
44
+ }
45
+
46
+ # Read monitored paths (one per line, ignore comments/blank)
47
+ get_monitored_paths() {
48
+ if [[ -f "$MONITORED_PATHS_FILE" ]]; then
49
+ grep -vE '^\s*(#|$)' "$MONITORED_PATHS_FILE" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
50
+ else
51
+ echo "."
52
+ fi
53
+ }
54
+
55
+ # Build find exclude expression from exclude_patterns.txt
56
+ build_exclude_expr() {
57
+ local expr=""
58
+ if [[ -f "$EXCLUDE_PATTERNS_FILE" ]]; then
59
+ while IFS= read -r pat; do
60
+ [[ -z "$pat" || "$pat" =~ ^\s*# ]] && continue
61
+ pat=$(echo "$pat" | xargs)
62
+ [[ -z "$pat" ]] && continue
63
+ if [[ -n "$expr" ]]; then
64
+ expr="$expr -o -path \"*/$pat/*\" -o -path \"*/$pat\""
65
+ else
66
+ expr="-path \"*/$pat/*\" -o -path \"*/$pat\""
67
+ fi
68
+ done < "$EXCLUDE_PATTERNS_FILE"
69
+ fi
70
+ if [[ -n "$expr" ]]; then
71
+ echo "! ( $expr )"
72
+ else
73
+ echo ""
74
+ fi
75
+ }
76
+
77
+ # Upsert a row in the Markdown health table (very simple but effective)
78
+ # We treat file_health.md as the single source of truth.
79
+ upsert_health() {
80
+ local file="$1"
81
+ local status="$2" # 🟢 or 🟡 or 🔴
82
+ local reason="${3:-}"
83
+
84
+ local now
85
+ now=$(timestamp)
86
+
87
+ # Ensure file exists with header
88
+ if [[ ! -f "$FILE_HEALTH" ]]; then
89
+ cat > "$FILE_HEALTH" << 'EOT'
90
+ # Documentation Health Matrix
91
+
92
+ | File | Status | Last Updated | Reason / Intent |
93
+ |------|--------|--------------|-----------------|
94
+ EOT
95
+ fi
96
+
97
+ # Escape for sed (basic)
98
+ local safe_file
99
+ safe_file=$(printf '%s' "$file" | sed 's/[\/&]/\\&/g')
100
+
101
+ # Check if file already has an entry
102
+ if grep -qF "| $file |" "$FILE_HEALTH" 2>/dev/null; then
103
+ # Update existing row (replace the whole line)
104
+ local new_line="| $file | $status | $now | $reason |"
105
+ sed -i.bak "s#| $safe_file | .* | .* | .* |#$new_line#" "$FILE_HEALTH" && rm -f "$FILE_HEALTH.bak"
106
+ else
107
+ # Append new row
108
+ echo "| $file | $status | $now | $reason |" >> "$FILE_HEALTH"
109
+ fi
110
+ }
111
+
112
+ # Mark a file Green (convenience)
113
+ mark_green() {
114
+ local file="$1"
115
+ local reason="${2:-Summary updated and verified accurate.}"
116
+ upsert_health "$file" "🟢 Green" "$reason"
117
+ # Remove from pending if present
118
+ if [[ -f "$PENDING_UPDATES" ]]; then
119
+ grep -vF "$file" "$PENDING_UPDATES" > "$PENDING_UPDATES.tmp" || true
120
+ mv "$PENDING_UPDATES.tmp" "$PENDING_UPDATES"
121
+ fi
122
+ }
123
+
124
+ # Append to pending_updates.md
125
+ add_pending() {
126
+ local file="$1"
127
+ local msg="$2"
128
+ echo "- $file: $msg" >> "$PENDING_UPDATES"
129
+ }
130
+
131
+ # Write a journal entry
132
+ write_journal() {
133
+ local action="$1" # "record-change", "record-deletion", "auto-detected", etc.
134
+ local file="$2"
135
+ local reason="$3"
136
+
137
+ local day_dir
138
+ day_dir="$JOURNAL_ROOT/$(date +%Y/%m)"
139
+ mkdir -p "$day_dir"
140
+ local journal_file="$day_dir/$(date +%d).md"
141
+
142
+ cat >> "$journal_file" << EOM
143
+ ## [$(timestamp)] $action
144
+ **File:** $file
145
+ **Reason:** $reason
146
+
147
+ EOM
148
+ }
149
+
150
+ # Simple cross-language import discovery (extendable)
151
+ discover_imports() {
152
+ local target="$1"
153
+ # Very lightweight — only common patterns. Real projects can extend.
154
+ grep -rE \
155
+ '^(import |from .* import |require\(|#include |import .* from |using |package )' \
156
+ "$target" 2>/dev/null | head -200 || true
157
+ }
158
+
159
+ # ----------------------------- Command Implementations -----------------------------
160
+
161
+ cmd_help() {
162
+ cat << 'EOF'
163
+ Wikifier v0.3 — Agent-First Codebase Wiki (Zero Dependencies)
164
+
165
+ Usage: wikifier <command> [arguments]
166
+
167
+ Core Commands:
168
+ check-changes Scan monitored paths for mtime changes since last run.
169
+ Marks changed files Yellow + adds to pending_updates.
170
+ health Pretty-print the current Documentation Health Matrix.
171
+ record-change <file> "<reason>"
172
+ Log a semantic change (why you edited). Updates health to Yellow.
173
+ record-deletion <file> "<reason>"
174
+ Log intentional deletion with reasoning.
175
+ prepare-edit <file> Stage a file for diff capture (captures current mtime).
176
+ mark-green <file> [reason]
177
+ Mark a wiki summary as accurate (Green). Clears pending entry.
178
+ update-maps Rebuild library.md with import/dependency Mermaid graph.
179
+ validate Check that every monitored file has at least a stub wiki entry.
180
+ monitor Background heartbeat: runs check-changes every 30s forever.
181
+
182
+ Information Commands:
183
+ journal [date] Show today's (or given YYYY-MM-DD) journal entries.
184
+ issues [severity] List Logged_issues (simple|moderate|high|critical).
185
+ help This message.
186
+
187
+ Workflow (for LLMs / new sessions):
188
+ 1. wikifier check-changes
189
+ 2. Read file_health.md + pending_updates.md
190
+ 3. Prioritise 🔴 Red → 🟡 Yellow
191
+ 4. After editing a file: wikifier record-change "path/to/file" "reason"
192
+ 5. After updating the wiki summary: wikifier mark-green "path/to/file"
193
+ 6. wikifier update-maps (when imports change)
194
+
195
+ Configuration files (edit these):
196
+ monitored_paths.txt Paths to scan (one per line). Default: "."
197
+ exclude_patterns.txt Glob patterns to ignore (node_modules, .git, dist, etc.)
198
+
199
+ The system is fully usable from the shell or exposed as MCP tools via skills/run.md.
200
+ EOF
201
+ }
202
+
203
+ cmd_check_changes() {
204
+ log "Running incremental change detection..."
205
+
206
+ local last_ts
207
+ if [[ -f "$LAST_CHECK_FILE" ]]; then
208
+ last_ts=$(cat "$LAST_CHECK_FILE")
209
+ else
210
+ last_ts="1970-01-01 00:00:00"
211
+ echo "$last_ts" > "$LAST_CHECK_FILE"
212
+ fi
213
+
214
+ local exclude
215
+ exclude=$(build_exclude_expr)
216
+
217
+ local changed=0
218
+
219
+ # For each monitored root, find files newer than last check
220
+ while IFS= read -r root; do
221
+ [[ -z "$root" ]] && continue
222
+ [[ ! -e "$root" ]] && { log "Warning: monitored path does not exist: $root"; continue; }
223
+
224
+ # shellcheck disable=SC2086
225
+ while IFS= read -r -d '' file; do
226
+ # Skip the wikifier tool's own internal files
227
+ if [[ "$file" == *"/.wikifier_staging/"* || "$file" == *"/journal/"* || \
228
+ "$file" == *"/Logged_issues/"* || "$file" == *"/.git/"* ]]; then
229
+ continue
230
+ fi
231
+
232
+ local rel_file
233
+ rel_file=$(realpath --relative-to="$WIKIFIER_ROOT" "$file" 2>/dev/null || echo "$file")
234
+
235
+ upsert_health "$rel_file" "🟡 Yellow" "mtime changed since last check-changes (auto-detected)"
236
+ add_pending "$rel_file" "Auto-detected modification — review and run mark-green after wiki update"
237
+ write_journal "auto-detected" "$rel_file" "File mtime changed (check-changes)"
238
+
239
+ ((changed++))
240
+ done < <(find "$root" -type f -newermt "$last_ts" -print0 2>/dev/null || true)
241
+ done < <(get_monitored_paths)
242
+
243
+ date '+%Y-%m-%d %H:%M:%S' > "$LAST_CHECK_FILE"
244
+
245
+ if (( changed > 0 )); then
246
+ log "Detected $changed changed file(s). See pending_updates.md and file_health.md."
247
+ else
248
+ log "No new changes detected."
249
+ fi
250
+ }
251
+
252
+ cmd_health() {
253
+ if [[ -f "$FILE_HEALTH" ]]; then
254
+ cat "$FILE_HEALTH"
255
+ else
256
+ echo "Health matrix not initialised yet. Run 'wikifier check-changes' or 'wikifier init'."
257
+ fi
258
+ }
259
+
260
+ cmd_record_change() {
261
+ local file="${1:-}"
262
+ local reason="${2:-No reason provided.}"
263
+
264
+ if [[ -z "$file" ]]; then
265
+ error "Usage: wikifier record-change <file> \"<concise reason>\""
266
+ exit 1
267
+ fi
268
+
269
+ upsert_health "$file" "🟡 Yellow" "$reason"
270
+ add_pending "$file" "LLM/agent edit — $reason"
271
+ write_journal "record-change" "$file" "$reason"
272
+
273
+ log "✅ Recorded semantic change for $file"
274
+ log " Reason: $reason"
275
+ log " → file_health.md updated to Yellow. Run mark-green after wiki summary is refreshed."
276
+ }
277
+
278
+ cmd_record_deletion() {
279
+ local file="${1:-}"
280
+ local reason="${2:-No reason provided.}"
281
+
282
+ if [[ -z "$file" ]]; then
283
+ error "Usage: wikifier record-deletion <file> \"<reason>\""
284
+ exit 1
285
+ fi
286
+
287
+ upsert_health "$file" "🔴 Red" "DELETED — $reason"
288
+ add_pending "$file" "File was deleted. Consider removing wiki entry or marking archival."
289
+ write_journal "record-deletion" "$file" "$reason"
290
+
291
+ log "🗑️ Recorded deletion for $file"
292
+ }
293
+
294
+ cmd_prepare_edit() {
295
+ local file="${1:-}"
296
+ if [[ -z "$file" || ! -f "$file" ]]; then
297
+ error "Usage: wikifier prepare-edit <existing-file>"
298
+ exit 1
299
+ fi
300
+
301
+ local mtime
302
+ mtime=$(stat -c %Y "$file" 2>/dev/null || stat -f %m "$file" 2>/dev/null || echo "0")
303
+ echo "$mtime" > "$STAGING_DIR/$(basename "$file").mtime"
304
+ log "Staged $file for later diff (mtime=$mtime)"
305
+ }
306
+
307
+ cmd_mark_green() {
308
+ local file="${1:-}"
309
+ local reason="${2:-Wiki summary verified accurate after change.}"
310
+ if [[ -z "$file" ]]; then
311
+ error "Usage: wikifier mark-green <file> [optional reason]"
312
+ exit 1
313
+ fi
314
+ mark_green "$file" "$reason"
315
+ log "🟢 $file marked Green. Pending entry cleared."
316
+ }
317
+
318
+ cmd_monitor() {
319
+ log "Starting Wikifier heartbeat monitor (interval: ${POLL_INTERVAL}s). Press Ctrl+C to stop."
320
+ log "Logs will be written to .wikifier_staging/monitor.log if run with nohup."
321
+
322
+ while true; do
323
+ cmd_check_changes
324
+ sleep "$POLL_INTERVAL"
325
+ done
326
+ }
327
+
328
+ cmd_update_maps() {
329
+ log "Rebuilding library.md (import map + Mermaid)..."
330
+
331
+ cat > "$LIBRARY_MD" << 'EOT'
332
+ # Library & Imports Map (auto-generated by wikifier update-maps)
333
+
334
+ > This file is regenerated. Manual edits will be overwritten.
335
+ > Run `wikifier record-change library.md "..."` if you need to annotate.
336
+
337
+ ## Dependency Graph (Mermaid)
338
+
339
+ ```mermaid
340
+ graph TD
341
+ EOT
342
+
343
+ # Very basic discovery — can be greatly improved per language
344
+ local paths
345
+ paths=$(get_monitored_paths)
346
+
347
+ echo " %% Auto-detected imports (lightweight scan)" >> "$LIBRARY_MD"
348
+
349
+ # Placeholder nodes for now; real impl would parse and connect
350
+ echo " Main[\"(root)\"] --> Wikifier[\"wikifier.sh\"]" >> "$LIBRARY_MD"
351
+
352
+ # Add a few real files if they exist in the tree
353
+ find $paths -type f \( -name "*.py" -o -name "*.sh" -o -name "*.js" -o -name "*.ts" -o -name "*.md" \) \
354
+ ! -path "*/.git/*" ! -path "*/node_modules/*" 2>/dev/null | head -30 | while read -r f; do
355
+ local base
356
+ base=$(basename "$f")
357
+ echo " $base[\"$base\"]" >> "$LIBRARY_MD"
358
+ done
359
+
360
+ cat >> "$LIBRARY_MD" << 'EOT'
361
+
362
+ ```
363
+
364
+ ## Files with Imports (summary)
365
+
366
+ | File | Detected Import Lines (truncated) |
367
+ |------|-----------------------------------|
368
+ EOT
369
+
370
+ # Append a few example import lines
371
+ discover_imports "." | head -30 | while IFS= read -r line; do
372
+ echo "| $(echo "$line" | cut -c1-60) |" >> "$LIBRARY_MD"
373
+ done
374
+
375
+ echo "" >> "$LIBRARY_MD"
376
+ log "✅ library.md updated. You can now embed the Mermaid diagram in index.html or any Markdown viewer."
377
+ }
378
+
379
+ cmd_validate() {
380
+ log "Validating that every monitored file has a health entry..."
381
+
382
+ local missing=0
383
+ local exclude
384
+ exclude=$(build_exclude_expr)
385
+
386
+ while IFS= read -r root; do
387
+ [[ -z "$root" ]] && continue
388
+ find "$root" -type f ! -path "*/.git/*" ! -path "*/.wikifier_staging/*" 2>/dev/null | while read -r f; do
389
+ local rel
390
+ rel=$(realpath --relative-to="$WIKIFIER_ROOT" "$f" 2>/dev/null || echo "$f")
391
+ if ! grep -qF "| $rel |" "$FILE_HEALTH" 2>/dev/null; then
392
+ echo "🔴 MISSING WIKI ENTRY: $rel"
393
+ ((missing++)) || true
394
+ fi
395
+ done
396
+ done < <(get_monitored_paths)
397
+
398
+ if (( missing == 0 )); then
399
+ log "✅ All monitored files have health entries."
400
+ else
401
+ log "⚠️ $missing file(s) lack wiki entries. Run update-maps + create summaries."
402
+ fi
403
+ }
404
+
405
+ cmd_journal() {
406
+ local date_spec="${1:-$(date +%Y-%m-%d)}"
407
+ local year month day
408
+ year=$(date -d "$date_spec" +%Y 2>/dev/null || date +%Y)
409
+ month=$(date -d "$date_spec" +%m 2>/dev/null || date +%m)
410
+ day=$(date -d "$date_spec" +%d 2>/dev/null || date +%d)
411
+
412
+ local jf="$JOURNAL_ROOT/$year/$month/$day.md"
413
+ if [[ -f "$jf" ]]; then
414
+ cat "$jf"
415
+ else
416
+ echo "No journal entries for $date_spec yet."
417
+ fi
418
+ }
419
+
420
+ cmd_issues() {
421
+ local sev="${1:-all}"
422
+ echo "=== Logged Issues (severity: $sev) ==="
423
+ if [[ "$sev" == "all" ]]; then
424
+ find "$LOGGED_ISSUES_ROOT" -type f -name "*.md" | sort
425
+ else
426
+ find "$LOGGED_ISSUES_ROOT/$sev" -type f -name "*.md" 2>/dev/null | sort
427
+ fi
428
+ echo ""
429
+ echo "See Logged_issues/map.md for the categorised overview."
430
+ }
431
+
432
+ cmd_init() {
433
+ log "Initialising fresh Wikifier state..."
434
+
435
+ [[ ! -f "$MONITORED_PATHS_FILE" ]] && echo "." > "$MONITORED_PATHS_FILE"
436
+ [[ ! -f "$EXCLUDE_PATTERNS_FILE" ]] && cat > "$EXCLUDE_PATTERNS_FILE" << 'EOT'
437
+ node_modules
438
+ .git
439
+ build
440
+ dist
441
+ __pycache__
442
+ *.pyc
443
+ EOT
444
+
445
+ [[ ! -f "$FILE_HEALTH" ]] && cat > "$FILE_HEALTH" << 'EOT'
446
+ # Documentation Health Matrix
447
+
448
+ | File | Status | Last Updated | Reason / Intent |
449
+ |------|--------|--------------|-----------------|
450
+ EOT
451
+
452
+ [[ ! -f "$PENDING_UPDATES" ]] && cat > "$PENDING_UPDATES" << 'EOT'
453
+ # Pending Updates
454
+
455
+ (no pending items — run check-changes after making edits)
456
+ EOT
457
+
458
+ [[ ! -f "$LIBRARY_MD" ]] && cat > "$LIBRARY_MD" << 'EOT'
459
+ # Library & Imports Map
460
+
461
+ Run `wikifier update-maps` to populate.
462
+ EOT
463
+
464
+ # Seed a first health entry for the tool itself
465
+ upsert_health "wikifier.sh" "🟢 Green" "Core CLI implemented and documented."
466
+
467
+ log "✅ Wikifier initialised. Edit monitored_paths.txt to point at your real codebase."
468
+ }
469
+
470
+ # ----------------------------- Main Dispatcher -----------------------------
471
+
472
+ main() {
473
+ local cmd="${1:-help}"
474
+ shift || true
475
+
476
+ case "$cmd" in
477
+ help|--help|-h) cmd_help ;;
478
+ check-changes) cmd_check_changes ;;
479
+ health) cmd_health ;;
480
+ record-change) cmd_record_change "$@" ;;
481
+ record-deletion) cmd_record_deletion "$@" ;;
482
+ prepare-edit) cmd_prepare_edit "$@" ;;
483
+ mark-green) cmd_mark_green "$@" ;;
484
+ monitor) cmd_monitor ;;
485
+ update-maps) cmd_update_maps ;;
486
+ validate) cmd_validate ;;
487
+ journal) cmd_journal "$@" ;;
488
+ issues) cmd_issues "$@" ;;
489
+ init) cmd_init ;;
490
+ *)
491
+ error "Unknown command: $cmd"
492
+ echo "Run 'wikifier help' for the full list."
493
+ exit 1
494
+ ;;
495
+ esac
496
+ }
497
+
498
+ main "$@"
@@ -0,0 +1,137 @@
1
+ Metadata-Version: 2.4
2
+ Name: wikifier
3
+ Version: 0.3.0
4
+ Summary: Agent-first, zero-dependency, self-maintaining codebase documentation & change tracking system
5
+ Author-email: Aron Amos <aron@example.com>
6
+ Maintainer: Aron Amos
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/IronAdamant/wikifier
9
+ Project-URL: Repository, https://github.com/IronAdamant/wikifier
10
+ Project-URL: Documentation, https://github.com/IronAdamant/wikifier#readme
11
+ Project-URL: Bug Tracker, https://github.com/IronAdamant/wikifier/issues
12
+ Keywords: wiki,documentation,llm,agent,mcp,codebase,health-matrix,zero-dependency,shell
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Operating System :: OS Independent
23
+ Classifier: Topic :: Software Development :: Documentation
24
+ Classifier: Topic :: Software Development :: Version Control
25
+ Classifier: Topic :: Text Processing :: Markup :: Markdown
26
+ Requires-Python: >=3.8
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Dynamic: license-file
30
+
31
+ # Wikifier v0.3
32
+
33
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
34
+ [![GitHub Stars](https://img.shields.io/github/stars/IronAdamant/wikifier?style=social)](https://github.com/IronAdamant/wikifier/stargazers)
35
+
36
+ **Agent-first • Zero-dependency • LLM-operated codebase wiki**
37
+
38
+ Wikifier turns any codebase (tiny scripts → large monorepos) into a living, token-efficient map that LLMs/agents operate autonomously.
39
+
40
+ > **GitHub**: https://github.com/IronAdamant/wikifier
41
+ > **PyPI**: `pip install wikifier` (coming very soon)
42
+
43
+ ---
44
+
45
+ ## 🚀 Get Started in 30 Seconds
46
+
47
+ ### Option 1: Via pip (Recommended)
48
+
49
+ ```bash
50
+ pip install wikifier
51
+
52
+ # Then run
53
+ wikifier init
54
+ wikifier check-changes
55
+ ```
56
+
57
+ ### Option 2: From source
58
+
59
+ ```bash
60
+ git clone https://github.com/IronAdamant/wikifier.git
61
+ cd wikifier
62
+ chmod +x wikifier.sh
63
+
64
+ # Point it at your codebase
65
+ nano monitored_paths.txt
66
+
67
+ ./wikifier.sh init
68
+ ./wikifier.sh check-changes
69
+ ```
70
+
71
+ Then open `index.html` in your browser for the live dashboard.
72
+
73
+ ### Mandatory Rule for Every LLM / Grok Build Session
74
+
75
+ Copy this into the **start of every new prompt** when working in a Wikifier-managed project:
76
+
77
+ ```text
78
+ You are operating inside a Wikifier v0.3 project.
79
+
80
+ MANDATORY FIRST STEPS:
81
+ 1. Run: wikifier check-changes
82
+ 2. Read file_health.md + pending_updates.md
83
+ 3. Prioritise 🔴 Red → 🟡 Yellow items
84
+ 4. For every code edit: wikifier record-change "path/to/file" "I did X because Y"
85
+ 5. After updating the wiki summary: wikifier mark-green "path/to/file"
86
+ 6. Re-validate before finishing
87
+ ```
88
+
89
+ ---
90
+
91
+ ## What Wikifier Gives You
92
+
93
+ - **Per-file Documentation Health Matrix** — 🟢 Green / 🟡 Yellow / 🔴 Red status with reasons
94
+ - **Semantic Change Logging** — `record-change "file" "I did X because Y"` (the "why", not just the "what")
95
+ - **Background Heartbeat Monitor** — Passive `monitor &` loop keeps everything fresh while you sleep
96
+ - **Automated Journal + Categorized Issues** — Dated entries + `Logged_issues/{simple,moderate,high,critical}/...`
97
+ - **Beautiful Static Dashboard** — `index.html` with live health lights, Mermaid graphs, and one-click command reference
98
+ - **MCP / Agent Ready** — Full `skills/run.md` contract so Grok, Claude, Cline, etc. can drive it natively
99
+ - **True Zero Dependencies** — Pure Bash + PowerShell. Works on any machine, no Docker, no Node, no Python packages.
100
+
101
+ **This is agent-first.** LLMs operate the system via shell commands. Humans just watch the dashboard.
102
+
103
+ ## Core Commands
104
+
105
+ | Command | Purpose |
106
+ |---------------------------|----------------------------------------------|
107
+ | `wikifier check-changes` | Incremental mtime scan + health update |
108
+ | `wikifier record-change <file> "reason"` | Log *why* you made an edit (required) |
109
+ | `wikifier mark-green <file>` | Mark wiki summary as accurate after editing |
110
+ | `wikifier monitor &` | Background heartbeat (30s polling) |
111
+ | `wikifier update-maps` | Rebuild `library.md` + Mermaid dependency graph |
112
+ | `wikifier health` | Show current Documentation Health Matrix |
113
+
114
+ Full reference → [`skills/run.md`](skills/run.md)
115
+
116
+ ## Quick Links
117
+
118
+ - [spec.md](spec.md) — Immutable user requirements
119
+ - [Basis-v0.3.md](Basis-v0.3.md) — Implementation reference & data formats
120
+ - [TRADEOFFS.md](TRADEOFFS.md) — Why we made the design choices we did
121
+ - [index.html](index.html) — Open this in a browser for the live dashboard
122
+
123
+ ## Differentiation
124
+
125
+ Unlike heavy "LLM Wiki" approaches (e.g. Karpathy-style personal knowledge bases), Wikifier is the **ultra-light, shell-native** implementation:
126
+
127
+ - Per-file health matrix with clear Red/Yellow/Green workflow
128
+ - Semantic `record-change` intent logging for future self-review
129
+ - True background monitor + zero external dependencies
130
+ - Native cross-platform (Linux/macOS/Windows via PowerShell)
131
+ - Designed from day one to be driven by LLMs via MCP/tools
132
+
133
+ **License**: MIT — fork freely and use in any project.
134
+
135
+ ---
136
+
137
+ *Built for agents, by agents, with just `bash` and stubbornness.*
@@ -0,0 +1,12 @@
1
+ wikifier/__init__.py,sha256=-vs1e2uzVbyNyn_o2_SKu0WUAllCbtPn0A4AY833xYc,232
2
+ wikifier/__main__.py,sha256=MSmt_5Xg84uHqzTN38JwgseJK8rsJn_11A8WD99VtEo,61
3
+ wikifier/cli.py,sha256=41Xpl0bYEM7OkCx6ooN484R4d7_lASUoZuReef-0I1E,1789
4
+ wikifier/scripts/wikifier.bat,sha256=nJbmn_HwZtmIJ4IOwkBwekjC2DITUPceQHmPUxXv7to,775
5
+ wikifier/scripts/wikifier.ps1,sha256=dD66CY1gpLJboUgpcxx2fS67MvurMOiPU5EswUnm7Uk,5778
6
+ wikifier/scripts/wikifier.sh,sha256=NQtwUgp6MYf7O5Ngsph8xKj5ZwKjRBPqHxHBu5IliXY,16025
7
+ wikifier-0.3.0.dist-info/licenses/LICENSE,sha256=2gWF8A-6q5_o_h1JrDhvE5yXow_mC0S9aeK1JR43rFg,1066
8
+ wikifier-0.3.0.dist-info/METADATA,sha256=qUORaho7oEO4bf5CU_neDjCWqwuhUAXw9eu2I9afi0M,5467
9
+ wikifier-0.3.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
10
+ wikifier-0.3.0.dist-info/entry_points.txt,sha256=LA9ZFMcXAo1_uEOA8DSLwqoiVCVq7zg4iPK2VBgD9IM,47
11
+ wikifier-0.3.0.dist-info/top_level.txt,sha256=pkXHR-6vEAXPAWzFbj3p0vn6k5rDRFFVD9CtVgmi6e0,9
12
+ wikifier-0.3.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ wikifier = wikifier.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Aron Amos
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ wikifier