Commit Graph

326 Commits

Author SHA1 Message Date
Simone c0f31e375a fix: streamline elapsed time extraction in _read_events function
Lint / pssa (push) Successful in 9s
Lint / python (push) Failing after 17s
2026-05-26 21:27:13 +02:00
Simone 8dc7a4fb99 Add coverage gap tests for command functionalities
Lint / pssa (push) Successful in 10s
Lint / python (push) Successful in 1m22s
- Implement tests for disk alert JSON output to include a message field when below threshold.
- Add tests for runner status when Gitea is online but no webhook URL is provided.
- Introduce tests for job report details to ensure no error line appears when there are no failure events.
- Add tests to skip empty JSONL files in job report listing.
2026-05-26 21:18:20 +02:00
Simone 0a1c455e54 refactor: simplify shutil usage in workstation backend tests
Lint / pssa (push) Successful in 9s
Lint / python (push) Successful in 22s
2026-05-26 19:00:38 +02:00
Simone 189b865a52 test: add unit tests for VmState and VmHandle functionality in protocol.py
Lint / pssa (push) Successful in 10s
Lint / python (push) Failing after 15s
2026-05-26 18:57:58 +02:00
Simone 1a1560ec3d test: update IP pool test to use Windows VMX and clarify test purpose
Lint / pssa (push) Successful in 11s
Lint / python (push) Successful in 23s
2026-05-26 18:51:01 +02:00
Simone 58d04d3bc1 chore: remove accidentally tracked C:test-vcpkg submodule ref
Lint / pssa (push) Successful in 10s
Lint / python (push) Failing after 22s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 18:43:59 +02:00
Simone 5d1ec39b1d refactor: streamline error handling with contextlib in template preparation 2026-05-26 18:42:32 +02:00
Simone 9c84e66dc3 fix(lint): change Python job runner from Windows to Linux and update shell to Bash
Lint / pssa (push) Successful in 10s
Lint / python (push) Failing after 17s
fix(script): add CmdletBinding attribute to Set-GuestInfoIP function for better process support
2026-05-26 18:38:56 +02:00
Simone a190282757 fix(lint): change job runner from windows to linux and update shell to pwsh
Lint / python (push) Failing after 3s
Lint / pssa (push) Failing after 16s
2026-05-26 18:35:19 +02:00
Simone 6d205386dc fix(job): handle SIGTERM and skip static IP for Linux guests
- Install SIGTERM handler that raises KeyboardInterrupt so act_runner
  workflow cancellations trigger the existing VM cleanup path
- Resolve guest_os before the ip_pool block and skip guestinfo IP
  injection for Linux (template doesn't read VMX guestinfo to configure
  network, causing SSH probe to fail against the wrong IP)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 01:03:16 +02:00
Simone 64f800019d docs(runbook): add three-way B6/B7/B8 comparison to static IP baseline
Lint / pssa (push) Failing after 5s
Lint / python (push) Failing after 4s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 22:28:24 +02:00
Simone 138fe8d19f docs(runbook): fix B8 template name (WinBuild2025, not 2022)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 22:27:00 +02:00
Simone c9549c1db2 docs(runbook): add B8 static IP baseline (WinBuild2022, 4 iterations)
Static IP via ip_pool: 24 s boot-to-ready vs 102 s DHCP (4x faster),
IP acquire now deterministic (σ < 0.03 s vs σ ≈ 57 s with DHCP).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 22:26:09 +02:00
Simone e538c0c037 feat(benchmark): add static IP support to Measure-CIBenchmark
- Add -StaticIP/-Netmask/-Gateway params; injects guestinfo into cloned
  VMX before start, mirroring job.py _inject_guestinfo_ip behaviour
- Add -GuestInfoOnly switch to Get-GuestIPAddress: skips vmrun
  getGuestIPAddress fallback to prevent race where transient DHCP address
  is returned before ci-static-ip.ps1 finishes reconfiguring the NIC
- Benchmark passes -GuestInfoOnly automatically when -StaticIP is set
- staticIP field added to benchmark.jsonl for DHCP vs static comparison

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 22:21:27 +02:00
Simone 87d440b672 chore: add .venv and .coverage to .gitignore
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 22:04:22 +02:00
Simone f090365d57 fix(template): make prepare-win robust without prior Deploy run
- WinRM MaxProcessesPerShell: apply 100 if below threshold before asserting
- DesktopHeap SharedSection: apply 4096 KB registry value if below threshold before asserting
- Replace cleanmgr (hangs in WinRM Session 0, no window station) with direct
  PowerShell cleanup for dumps, WER files and Recycle Bin; DISM already covers
  component store and WU cache
- vcpkg git clone/checkout: wrap with EAP=Continue to suppress PS5.1
  NativeCommandError on git stderr (gotcha #3 from AGENTS.md)
- template.py: filter CI_EXITCODE:N marker from displayed output
- ci-static-ip.ps1: switch from vmware-rpctool (removed in recent Tools) to
  vmtoolsd --cmd; use temp-file redirect to capture output from native cmd

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 22:03:49 +02:00
Simone faf5b9e29b fix(template): move disk cleanup after final reboot, before shutdown
Cleanup now runs after the system reboots post-install (fully settled
state), not right after the WU loop. Sequence: WU loop → static IP →
validation → final reboot → WinRM ready → [cleanup] → autologin →
shutdown → snapshot.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 02:47:45 +02:00
Simone f96b9953c5 feat(template): cleanup-after-update + ruff fixes
Move disk cleanup out of the Windows Update loop:
- PS scripts: extract Invoke-DiskCleanup function, add -CleanupOnly switch
  for standalone post-update cleanup pass.
- Python command: always pass -SkipCleanup:$true during WU loop; after
  loop exits 0, run a separate -CleanupOnly invocation (skipped if
  --skip-cleanup). Fails fast if cleanup-only returns nonzero.
- Tests: 3 new tests for cleanup-runs-after-loop, skip-cleanup suppresses
  it, and cleanup-failure propagates as ClickException.
- ruff --fix: remove unused shutil import, sort imports, fix UP037/UP035.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 02:41:15 +02:00
Simone d5f362b8dc fix(template): restore tty state before snapshot prompt to fix ^M issue
pypsrp alters terminal tty settings during WinRM sessions. This causes
readline() at the snapshot prompt to receive \r (not \n) on Enter,
printing ^M repeatedly without ever unblocking.

Fix: save termios attributes at command start (before any WinRM work,
terminal is clean) and restore them with tcsetattr(TCSADRAIN) before
the interactive snapshot prompt. Gracefully skips save/restore when
stdin is not a tty (tests, pipes, CI).

Revert the pre-flight snapshot check approach (commit f6f8ffc) — checking
at start was architecturally wrong (snapshot state may change during
provisioning). The prompt stays at the end where it belongs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 02:19:05 +02:00
Simone f6f8ffc3d2 fix(template): move snapshot conflict check to pre-flight (before WinRM)
pypsrp alters terminal tty state during remote sessions. Any readline()
call after WinRM work receives \r instead of \n on Enter (terminal in
raw mode), causing the prompt to spin printing ^M and never return.

Fix: check for existing snapshot and ask the user at the very beginning
of the command, before any WinRM/pypsrp connections are opened, when the
terminal is still in canonical mode. If the user declines, abort early.
At the end, if the snapshot still exists (race-safe), delete silently
and recreate — no second prompt needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 02:15:51 +02:00
Simone 5d3214d10c fix(template): use sys.stdin.readline() for snapshot confirm prompt
input() with a prompt string on some terminals (zsh + Linux Mint) echoes
^M and the prompt doesn't flush before reading, causing the prompt to
appear stuck or not accept input.

Replace with explicit sys.stdout.write()+flush() + sys.stdin.readline()
which guarantees the prompt is flushed before blocking on stdin, and
readline() + .strip() handles both \n and \r\n line endings correctly.

Tests updated to use CliRunner(input=) which populates sys.stdin inside
the runner context (monkeypatching sys.stdin.readline directly is ignored
by CliRunner which replaces sys.stdin entirely).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 02:07:36 +02:00
Simone 258ef3a7e7 fix(template): replace click.confirm with input() to avoid ^M on Linux terminals
click.confirm() doesn't strip \r — "y\r" doesn't match "y" and the prompt
loops or fails. Replace with raw input().strip().rstrip('\r').lower() which
handles both \n and \r\n line endings.

Also add --recreate-snapshot flag to skip the interactive prompt entirely
(useful for scripted re-provisioning).

Update snapshot_exists_skip/recreate tests to monkeypatch builtins.input
instead of using CliRunner input=.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 02:02:22 +02:00
Simone 483dd51a3b feat(template): heartbeat thread for long-running toolchain install
execute_ps is fully blocking with no streaming. Add _run_with_heartbeat()
which runs the WinRM call in a daemon thread and prints
"  ... still running (Ns elapsed) ..." every 30 s so the operator can
distinguish a hung session from a slow Windows Update pass.

Used only for the toolchain script invocation (the slow step); all other
transport.run() calls keep the direct path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 01:52:27 +02:00
Simone 84746d2232 feat(template): add --store-credential to prepare-win + full docstring
- --store-credential: after snapshot, writes build-user credentials into
  the system keyring using the two-entry scheme (service:meta + service)
  that KeyringCredentialStore.get() reads. Works on Windows (Credential
  Manager) and Linux (SecretService / file backend).
- --credential-target: keyring target name, default BuildVMGuest (matches
  config.guest_cred_target).
- Rewrote module docstring: full prose documentation of both `template
  backup` and `template prepare-win` including all 12 provisioning steps.
- 2 new tests covering --store-credential with custom and default targets.
- mypy --strict clean; coverage 90.03%.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 01:30:57 +02:00
Simone 9e84d89823 feat(template): add template prepare-win Python command via pypsrp
Replaces the abandoned PSWSMan approach (New-PSSession hangs on Linux)
with a Python-native implementation using the proven pypsrp WinRmTransport.

- New `template prepare-win` command in commands/template.py: starts VM,
  waits for WinRM, uploads and runs Install-CIToolchain-*.ps1, handles
  Windows Update 3010 reboot loop (max 10 iterations), installs CI-StaticIp
  scheduled task, runs post-setup validation, graceful shutdown, snapshot.
- Helpers: _ps_escape, _wait_tcp, _parse_exit_marker, _wait_winrm.
- 40 new tests in test_commands_template.py covering all major branches.
- Fix test_commands_job.py: patch load_config in _patch_common so tests
  don't pick up live /var/lib/ci/config.toml ip_pool and fail on lock.
- Coverage gate: 90.06% (was 88.95% before fix).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 01:22:53 +02:00
Simone 6b76115b6a fix(templates): import PSWSMan module on Linux before New-PSSession
Without Import-Module PSWSMan the native WSMan library isn't registered
and New-PSSession hangs/fails silently. Import guarded by $IsWindows so
Windows PS 5.1 is unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 00:53:19 +02:00
Simone de6858e3df fix(templates): skip TrustedHosts config on Linux host
WSMan TrustedHosts is a Windows WinRM client concept — does not exist
on Linux. Guard the configure+restore blocks with $isLinuxHost so the
Prepare scripts run without elevation errors from a Linux host.
-SkipCACheck/-SkipCNCheck in sessionOptions is sufficient on Linux.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 00:50:25 +02:00
Simone 04b716149c fix(templates): drop -SkipRevocationCheck from New-PSSessionOption
Parameter not available in PS 7 on Linux. -SkipCACheck -SkipCNCheck
sufficient for self-signed lab certs; revocation check is irrelevant
for self-signed certs regardless.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 00:48:13 +02:00
Simone de33e9f723 fix(templates): replace Test-NetConnection with TcpClient in Prepare scripts
Test-NetConnection is Windows-only. Replace with cross-platform TcpClient
async-connect helper (same pattern as Measure-CIBenchmark.ps1) so the
Prepare scripts run on the Linux host under PowerShell.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 00:46:19 +02:00
Simone 41a0a113df feat(templates): install ci-static-ip/ci-report-ip via Prepare+Install scripts
Windows (Prepare-WinBuild2025/2022): read ci-static-ip.ps1 from
guest-setup/windows/ on the host, push content over WinRM, register the
CI-StaticIp scheduled task (AtStartup/SYSTEM). Adds StaticIpTask and
StaticIpScript post-setup assertions.

Linux (Install-CIToolchain-Linux2404.sh): embed ci-report-ip.sh and
ci-report-ip.service content inline via heredoc tee, replacing the broken
cp-from-relative-path approach (the script runs inside the VM where the
host-side guest-setup/ directory does not exist).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 00:37:07 +02:00
Simone 1bc3ec601c feat(ip-pool): add guest-side static-IP boot scripts
template/guest-setup/linux/ci-report-ip.sh
  Updated version: checks guestinfo.ip-assignment first (static path),
  falls back to DHCP detection if absent.  Applies static IP before
  network-online.target so SSH starts on the correct address immediately.

template/guest-setup/linux/ci-report-ip.service
  Drops 'network.target' from After= — runs before network is up so the
  static IP is configured before SSH/other services start.

template/guest-setup/windows/ci-static-ip.ps1
  Reads guestinfo.ip-assignment via vmware-rpctool at system startup (SYSTEM
  account Task Scheduler task).  Disables DHCP, applies static IP+gateway,
  reports back via guestinfo.ci-ip.  No-op when ip-assignment is absent.

template/Install-CIToolchain-Linux2404.sh
  Step 7b now copies scripts from guest-setup/linux/ instead of embedding
  the old DHCP-only inline script.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 00:27:10 +02:00
Simone 927d6927fd feat(ip-pool): pre-assign static IPs to build VMs via VMX guestinfo
Eliminates VMware-Tools IP-detect polling (observed: 39–177 s variance on
Linux host B7 benchmark).  When [ip_pool] is configured the orchestrator:

  1. Allocates a slot IP from a JSON-backed pool (fcntl-locked on Linux)
  2. Injects guestinfo.ip-assignment / netmask / gateway into the cloned VMX
     before vmrun start
  3. Skips _wait_for_ip entirely — uses the pre-assigned IP immediately
  4. Releases the slot in _destroy_clone (all paths: success/failure/interrupt)

New modules / changes:
  src/ci_orchestrator/ip_pool.py      IpSlotPool + _file_lock context manager
  src/ci_orchestrator/config.py       IpPoolConfig dataclass; [ip_pool] TOML
  src/ci_orchestrator/commands/job.py _inject_guestinfo_ip helper; pool wiring
  tests/python/test_ip_pool.py        12 unit tests (acquire/release/persist)
  tests/python/test_config.py         ip_pool config parsing tests
  tests/python/test_commands_job.py   pool path + _inject_guestinfo_ip tests
  config.example.toml                 [ip_pool] section (commented example)

Coverage 90.02%; mypy --strict clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 00:26:59 +02:00
Simone 203515f5d7 docs(runbook): add Linux host benchmark baseline (B7 result)
4-iteration run on Linux Mint host, WinBuild2025/BaseClean.
Clone/Start/Ready/Destroy within ±20% of Windows baseline.
IP-acquire avg 99.7 s vs 58.2 s Windows — high variance (39–177 s),
attributed to VMware Tools reporting latency, not orchestrator regression.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 00:08:42 +02:00
Simone 855e9d7b3f fix(benchmark): totalBootSec null when readySec=0 (PS falsy 0.0)
if ($t.ready) evaluates false when ready=0.0 — use $null -ne guard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 00:07:04 +02:00
Simone 4f9149f7e2 fix(benchmark): adapt Measure-CIBenchmark to Linux host
Measure-CIBenchmark.ps1:
- Default params now Linux-aware via $IsWindows conditional
  (TemplatePath, CloneBaseDir, VmrunPath, OutputDir)
- Add -GuestOS Auto/Windows/Linux param; Auto reads VMX guestOS field
  (ubuntu-* → Linux, else Windows)
- Replace Test-NetConnection (Windows-only) with Test-TcpPort helper
  using raw TcpClient async connect — works on PS5.1 and PS7/Linux
- Probe SSH/22 for Linux guests, WinRM/5986 for Windows guests
- Rename winrm→ready throughout ($t, JSONL field readySec, column header)
- Add guestOS field to JSONL output

_Common.psm1 / Invoke-VmrunBounded:
- Replace taskkill /F /T with platform-aware kill:
  Windows → taskkill; Linux → Process.Kill(entireProcessTree) (.NET 5+)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 23:57:32 +02:00
Simone c1147c5b19 docs(runbook): fix table alignment in B7 baseline section
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 23:50:01 +02:00
Simone 77f72f71b9 fix(burn-in): migrate Start-BurnInTest wrappers to Linux host paths
Replace Windows-hardcoded paths with Linux equivalents:
- RepoUrl → local Gitea instance (10.10.20.11:3100/Simone/burnin-dummy)
- TemplatePath/CloneBaseDir/ArtifactBaseDir/VmrunPath → /var/lib/ci/…
- `$scriptDir\Test-CapacityBurnIn.ps1` → Join-Path $PSScriptRoot (cross-platform)
- Remove `Split-Path -Parent $MyInvocation.MyCommand.Path` (redundant)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 23:49:59 +02:00
Simone 0b69155b02 fix(plans): switch B7 burn-in to burnin-dummy repo
nsis-plugin-ns7zip is a real C++ project — wrong for lifecycle testing.
burnin-dummy simulates ~30s work and writes to dist/ with no external
deps. Documents one-time prerequisites (group, keyring, Gitea push).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 23:44:07 +02:00
Simone 40aae7ad16 fix(plans): add -BuildCommand to B7 burn-in commands
Without an explicit build command, job.py runs dotnet build (which fails
on nsis-plugin-ns7zip in a fresh VM) and expects bin\CIOutput as artifact
source. With a trivial BuildCommand, artifact_source defaults to "dist"
and the lightweight command always succeeds.

Also documents one-time simone group/keyring prerequisites for running
the burn-in as simone with ci-runner group access.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 23:03:52 +02:00
Simone 5982a88041 fix(plans): prefix B7 burn-in commands with sudo -u ci-runner
/var/lib/ci/ is owned by ci-runner; running as simone causes
PermissionError on artifact dir creation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:45:43 +02:00
Simone 10998247a0 fix(shims): add Linux fallback for venv Python path in all PS shims
All shims defaulted to F:\CI\python\venv\Scripts\python.exe when
CI_VENV_PYTHON was not set. On Linux host this caused instant failure.

Now uses $IsWindows (PS 6+ automatic var; absent on PS 5.1 = Windows)
to select /opt/ci/venv/bin/python on Linux. Windows paths unchanged.

Affects: Invoke-CIJob, Get-BuildArtifacts, Cleanup-OrphanedBuildVMs,
New-BuildVM, Remove-BuildVM, Wait-VMReady, Get-CIJobSummary,
Invoke-RemoteBuild, Watch-DiskSpace, Watch-RunnerHealth,
Set-CIGuestCredential, Test-CIGuestWinRM.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:43:48 +02:00
Simone 568740ed17 fix(burn-in): move psExe detection inside Start-Job scriptblock
Passing $psExe as a second -ArgumentList item caused double-wrapping of
the string array, collapsing all args into one string when splatted.
Computing $IsWindows inside the worker avoids the extra param entirely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:41:28 +02:00
Simone 5d59446114 fix(burn-in): use pwsh instead of powershell.exe on Linux host
powershell.exe does not exist on Linux — child process launch failed
instantly (ExitCode null, Elapsed 00:00). Now selects powershell.exe
on Windows and pwsh on Linux via $IsWindows automatic variable.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:39:32 +02:00
Simone ce84afd901 fix(plans): correct Test-CapacityBurnIn.ps1 commands in B7
-Concurrency → -Parallelism, -Template → -TemplatePath; add mandatory
-RepoUrl and Linux-host paths (-CloneBaseDir, -ArtifactBaseDir,
-VmrunPath). Add explicit LinuxBuild2404 command with -GuestOS Linux.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:37:18 +02:00
Simone c1137bc5cf docs(runbook): record Windows host pre-migration baseline for B7
Data from Measure-CIBenchmark.ps1 × 4 (2026-05-17, commit 36913ab):
avg boot 60.6s, IP-acquire dominant (20–85s, σ≈26s). Adds ±20% ranges
for B7 comparison and guidance on sample size given IP-phase variance.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:25:11 +02:00
Simone defb95bd22 fix(plans): restore PhaseB-user-checklist.md — phase not fully complete
Burn-in (4 jobs × 10 rounds), 7-day stability run, and RUNBOOK.md
Linux section are still open. Checklist stays active until all
acceptance criteria are met.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:02:38 +02:00
Simone 758f86c11c docs(lifecycle): add CI/CD job lifecycle documentation with flowchart and phase breakdown
Lint / pssa (push) Failing after 3s
Lint / python (push) Failing after 3s
2026-05-23 21:56:59 +02:00
Simone 0d6486b19b chore(plans): archive Phase A and B completed documents
Moves all A/B closeouts, checklists, idea docs, and implementation plans
to plans/archived/2026-05-23/. Both phases are production-stable.

Active plans remaining in plans/:
  - idea-3-powershell-removal.md  (Phase C — in progress)
  - idea-3-esxi-support.md        (Phase D — future)
  - ideas-overview.md             (roadmap reference)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 19:52:09 +02:00
Simone 222c41dd16 chore(tools): add graph_query.py dev utility under tools/
Relocates the graphify BFS/path query script from scripts/ (a PowerShell
folder) into a new tools/ directory for Python developer utilities.

The script is not part of the CI pipeline — it's a local query tool for
navigating graphify-out/graph.json during codebase investigation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 19:50:21 +02:00
Simone 915a04b5c3 chore(gitignore): ignore graphify-out/ generated directory
graphify-out/ contains the knowledge graph, AST/semantic cache, and
HTML report — all regenerated by /graphify. No value in tracking them.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 19:50:14 +02:00