release: gcode 1.0.0, gwiki 0.3.0, gcore 0.4.0, patch gsqz/gloc/ghook#7
Conversation
… AI requests, and update research session scope.
Every project-scoped gcode read ran ensure_project_fresh, which took the per-project advisory lock and unconditionally re-hashed every discovered file before comparing against stored hashes. Under concurrent agent sessions these lock-holds overlapped, the 150ms brief-try window lost, and reads printed "gcode index refresh already running" despite nothing having changed. Add a lock-free, hash-free pre-gate in freshness::ensure_fresh for FreshnessScope::Project: read last_indexed_at + indexed paths read-only from the hub and call the new index::api::project_changed_since, which reuses walker::discover_files + DEFAULT_EXCLUDES and returns true on any modify/add (mtime newer than last_indexed_at minus a 2s skew margin) or delete (indexed path missing on disk). With no change it returns Checked without taking the lock or hashing anything; on a change it falls through to the existing lock + incremental reconcile, unchanged. No staleness window, no hub schema change, standalone backstop preserved. The 2s margin only ever makes the gate more eager, so it can never miss a change; backdated mtimes are reconciled by the periodic maintenance sweep. Discovery mirrors the indexer exactly, so the .gobby/plans/**/*.md allowlist (edits the daemon trigger never forwards) is covered. Tests: unit tests for project_changed_since (no-change/modify/add/delete and the 2s margin boundary) and postgres-gated freshness tests asserting Checked-without-lock on no change and SkippedBusy when a change is present while the lock is held. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ep fix, docs) Release prep for gobby-core 0.3.0, gcode 0.9.9, ghook 0.4.5, gsqz 0.4.5, gloc 0.1.3, and the first gwiki release (0.2.0). - gwiki: bump package version 0.1.0 -> 0.2.0 (first public release); Cargo.lock synced. - gloc: pin gobby-core dep to version = "0.3.0" (keep default-features = false) so the crate is releasable to crates.io, which rejects a path dependency with no version; update the gcore public_boundary test to match the corrected declaration. - CHANGELOG: reconcile gcode [0.9.9] and gobby-core [0.3.0] against all commits since 2026-05-31 (codewiki generator, LLM outlines, citation provenance, daemon-first embeddings, shared AI clients/probe, etc.), add gloc dep-fix and ghook review entries, and add the new gwiki [0.2.0] section. - Docs: README now lists five tools incl. gwiki (feature section, version table, install, links); release-guide and guides index include gwiki and document the gloc dep rule. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…suppression) GitHub Actions creates no tag push events when more than three tags arrive in a single push, so the batched tag push in the release runbook silently triggers no release workflows. Document one-at-a-time pushing plus the delete/re-push recovery. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gwiki's documents feature links pdfium (native, provisioned via pdfium-auto), which fails to build on the windows-msvc targets ('target was empty'). That failed the build matrix and blocked the crates.io publish job (needs: [test, build]), so gwiki 0.2.0 never published. gwiki now ships macOS + Linux binaries only; crates.io publishing is platform-independent and proceeds. Windows support is tracked as a follow-up.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… releases Each helper release workflow now emits `<asset>.sha256` (via sha256sum) for every .tar.gz/.zip and uploads them in the GitHub Release. The gobby installer fetches `<asset_url>.sha256` and verifies the archive before chmod/PATH placement, failing closed on a missing or mismatched checksum. Covers gsqz, ghook, gloc, gcode, and gwiki release workflows. Companion to gobby epic #15586 / M2 #15588. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ResearchStopReason::WriteConflict was a dead variant: the materializer
set a write_conflict bool on legitimate title-slug collisions, OR-
accumulated it into the output, and the loop continued — contradicting
docs/contracts/gwiki-research.md ("stop on the first matching rule",
"exits without overwriting").
research_note_file_state now compares the on-disk body of a completed,
draft-id-matching note against the validated draft and returns a new
CompletedConflict state on mismatch (a concurrent writer changed it).
write_accepted_note surfaces that as write_conflict without overwriting;
the loop maps it to StepOutcome::Stop(WriteConflict) (status Failed) and
records neither the note nor a changed path. Numeric-suffix title
collisions and create-marker races are no longer reported as conflicts.
Tests: write layer (draft-id collision with changed body -> write_conflict,
no overwrite, no suffix note) and loop layer (run stops with stop_reason
write_conflict, nothing recorded). Companion to gobby epic #15586 / M4 #15590.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gwiki research --format json echoed only max_steps/max_tokens/max_sources; the spec requires every enforced budget to be visible. Promote the hardcoded 900s wall-time / 24000-byte note budgets to named constants (RESEARCH_MAX_WALL_TIME_SECONDS, RESEARCH_MAX_NOTE_BYTES), add max_wall_time_seconds and max_note_bytes to ResearchOutcome and the ResearchOutput JSON struct, and add both keys to contract.rs json_output_keys. Regenerated the pinned crates/gwiki/contract/gwiki.contract.json. cargo fmt --check, clippy -D warnings, and cargo test -p gobby-wiki (contract_builder_matches_pinned_json + contract_command_emits_pinned_json) pass. Companion to gobby epic #15586 / M6 #15592. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The publish job hard-failed when gobby-wiki's version was already on crates.io (e.g. after a token-based first publish), which blocked the release job and its macOS/Linux binary upload. Add a pre-check that queries crates.io for the package version and skips the auth + upload steps when it already exists, so re-pushing the tag attaches binaries without re-uploading the crate. New versions still publish normally. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nder 1,000 lines
Decompose the 2,586-line crates/gcode/src/commands/codewiki.rs monolith into a
codewiki/ module directory, each file well under the 1,000-line limit:
- mod.rs facade: imports, consts, data types, SourceSpan impl, run/generate
orchestration, module decls + re-exports
- prompts.rs AI prompt builders + SymbolSummary/ChildSummary
- io.rs doc writing, incremental meta, safe path resolution
- graph.rs FalkorDB edge fetching
- cluster.rs module clustering / union-find
- build.rs file/module doc construction
- render.rs markdown + mermaid rendering
- text.rs AI text generation + citation grounding
- paths.rs module/file path + markdown helpers
- tests.rs relocated #[cfg(test)] suite (verbatim)
Public API preserved (run, write_doc_set, write_incremental_doc_set,
generate_hierarchical_docs, public types). Internal items scoped pub(crate).
No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…under 1,000 lines
Decompose the 1,734-line crates/gwiki/src/ingest/video.rs into a video/
directory with a facade mod.rs plus cohesive submodules, each well under
the 1,000-line limit:
mod.rs — imports, DEFAULT_FRAME_INTERVAL_SECONDS, public data types
(VideoSnapshot/VideoFileSnapshot/VideoIngestResult) and the
ingest entry functions; declares + re-exports submodules.
processing.rs— VideoMediaExtractor trait, ProductionVideoMediaExtractor,
the with-processing pipeline, frame description, degradation.
assets.rs — asset-backed ingest and frame-asset persistence/cleanup.
metadata.rs — VideoDegradationContext, VideoSnapshotRef, metadata and
raw-markdown rendering.
tests.rs — the relocated #[cfg(test)] suite.
Public API and behavior are preserved: external callers continue to reach
VideoFileSnapshot, VideoIngestResult, DEFAULT_FRAME_INTERVAL_SECONDS, and
ingest_video_file_with_production_processing_without_index via
crate::ingest::video::*. Cross-module items widened to pub(crate); no logic
changes. cargo build/clippy --tests/fmt --check clean; all gobby-wiki tests
pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…aarch64-windows for ghook gwiki was the only Gobby CLI binary with no Windows artifacts: #461 dropped both *-pc-windows-msvc legs because the build failed and gwiki's publish job (needs: [test, build]) was gated on the binary matrix, so that failure blocked the crates.io publish. gcode/gloc/gsqz already ship both Windows arches with the identical reqwest+rustls+ring stack, so the toolchain is proven; gwiki's only build-script delta is the `documents` feature's pdfium-auto (bundled) download. release-gwiki.yml: - Restore the x86_64 + aarch64 pc-windows-msvc matrix legs (the Package/MSVC steps were already present and dormant). - Provision pdfium deterministically on the Windows runners: download the pinned bblanchon chromium/7690 archive, verify its SHA-256 (fail-closed), and point pdfium-auto at it via PDFIUM_BUNDLE_LIB (its priority-1 source), so the build never depends on the build script's own network fetch. macOS/Linux keep pdfium-auto's auto-download, which already works in CI. - Decouple publish from build: `needs: test` + tag-only, so a single flaky binary target can never block the platform-independent crate publish again. - Add a workflow_dispatch trigger so the build matrix (incl. the Windows legs) can be dry-run on a branch without cutting a tag; publish/release stay tag-only. release-ghook.yml: - Add the aarch64-pc-windows-msvc leg + the Configure MSVC for Windows ARM64 step (mirrors gcode/gloc/gsqz). CI correction only — no version bumps, no tags. Validate via workflow_dispatch once on the default branch; then a future gwiki-v*/ghook-v* tag ships the Windows binaries automatically. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…odules under 1,000 lines Decompose crates/gcore/src/provisioning.rs (1,721 lines) into a facade plus cohesive submodules, each under 1,000 lines, preserving the public API (re-exported via pub use) and behavior: - mod.rs (171): imports, consts, StandaloneConfig + path helpers, wiring - hub.rs (463): hub identity/options types + hub resolution pipeline - docker.rs (410): docker service types, command/health runners, provisioning + pgsearch asset/process helpers - bootstrap.rs (139): EmbeddingBootstrap + standalone bootstrap/yaml - tests.rs (547): relocated test suite Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nder 1,000 lines Decompose the 1,678-line crates/gwiki/src/research.rs monolith into a research/ module directory, each file under the 1,000-line limit, preserving the public API (run, ResearchOptions/Outcome/Status/StopReason, AuditFinding, AuditSeverity, ResearchGap, AcceptedNoteDraft, resolve_scope, research_scope_from_resolved) and all behavior: - mod.rs (364): facade — imports, consts, materializing-wait signal, public types, and the run/enrichment orchestration entrypoints. - model.rs (182): GcoreResearchModel + Wiki ask/search/read/ingest command adapters + AcceptedNoteWriter. - outcome.rs (219): outcome/observation, scope, audit, and session helpers. - notes.rs (432): accepted-note materialization and note-file state. - storage.rs (172): raw-index locking, atomic writes, slug/util helpers. - tests.rs (330): relocated #[cfg(test)] module. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… 1,000 lines
Decompose the 1,488-line crates/gcore/src/config.rs into a config/ module
directory, each file under the 1,000-line limit, preserving the public API
surface via facade re-exports:
- config/mod.rs (17) facade: doc header, module wiring, pub use re-exports,
TEST_ENV_LOCK root (consumed as crate::config::TEST_ENV_LOCK)
- config/types.rs (347) data contracts: FalkorConfig/QdrantConfig/EmbeddingConfig,
AiRouting/AiCapability enums, embedding_keys/ai_keys modules
- config/resolve.rs (348) ConfigSource trait, EnvOnlySource, resolve_* machinery
- config/tests.rs (785) the #[cfg(test)] suite
AiCapability key methods widened to pub(crate) (resolve calls them cross-module);
EMBEDDING_DEFAULT_MODEL/_TIMEOUT_SECONDS widened to pub(crate) (tests reference them).
CI-guard tests updated for the new paths: include_str! scans the three production
files; the workspace embedding-key scan allows config/types.rs.
cargo fmt --check clean; clippy --workspace --all-targets -D warnings clean;
cargo test -p gobby-core --features full (148 lib + 3 integration) pass;
RUN_SLOW_TESTS=1 workspace embedding-key scan passes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dules under 1,000 lines Decompose the 1,243-line crates/gwiki/src/commands/refresh.rs into a refresh/ module directory, each file under 1,000 lines, preserving the public API (commands::refresh::execute) and all behavior: - mod.rs facade: imports, module wiring, execute orchestration - selection.rs source selection + replay-kind classification + url helpers - candidate.rs per-source refresh execution + changed-source replay + hashing - vault.rs vault filesystem path resolution + asset removal - render.rs refresh output rendering - model.rs refresh DTOs (Selection, RefreshPlan, RefreshRender, ...) - tests.rs the existing #[cfg(test)] suite, unchanged Cross-module helpers widened to pub(crate); render's super::scoped_outcome repointed to crate::commands::scoped_outcome for the deeper module depth. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dules under 1,000 lines Decompose the 1,213-line crates/gwiki/src/ingest/document.rs into a document/ directory of cohesive modules, each well under the 1,000-line limit, preserving the public ingest_document* API and all behavior: - mod.rs (facade): public types, entry fns + orchestrator, DocumentExtractor impl, shared helpers (document_error, decode_xml_entities, extension), module wiring - office.rs: docx/pptx/xlsx extraction + zip/xml/table helpers + bounded-extraction constants - html.rs: HTML extraction + visible-text walking - render.rs: raw + derived markdown rendering, atomic write, degradation mapping - tests.rs: the #[cfg(test)] mod tests body Cross-module helpers widened to pub(crate); sibling/test access routed through the facade re-export globs. clippy (-D warnings), fmt, and the 7 document unit tests all pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…er 1,000 lines Decompose the 1,214-line crates/gwiki/src/compile.rs by compile-pipeline stage into a compile/ directory, each module under 1,000 lines and the public API (compile_to_wiki, compile_to_wiki_with_options, prepare_handoff, the Compile* types) unchanged: - mod.rs (facade): imports, public types, orchestration entry points, CollectedSources, and index_lock_timeout (kept at crate::compile root so registry.rs/research::storage external references stay intact) - collect.rs: accepted-source collection + research-note parsing - index.rs: wiki-index update, provenance writing, source-marking, lock - render.rs: bundle render + target-page output - tests.rs: the unit-test module Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dules under 1,000 lines Convert the 1,176-line tests/cli_smoke.rs integration test into a tests/cli_smoke/ directory (Cargo auto-discovers main.rs as the cli_smoke target). main.rs holds the shared imports and helper fns; test groups move to config_postgres.rs, ingest_refresh.rs, and public_smoke.rs, each pulling shared items via use super::*. All 13 tests preserved and passing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ines Split the 1,054-line crates/gcode/src/db.rs into a db/ directory: mod.rs (35) facade with the connection primitives (connect_readwrite/readonly, read_config_value) plus pub re-export globs; resolution.rs (757) with the database-URL resolution chain, broker request, and all unit tests; queries.rs (271) with GraphFileFacts and the graph/file/symbol query fns. Public API preserved at crate::db::* via pub use globs. All 26 unit tests pass; clippy --all-targets -D warnings and fmt --check clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ser/ modules under 1,000 lines Decompose the 1,045-line per-language import-parser dispatcher into a parser/ facade plus five language-family submodules, each well under the 1,000-line limit: - mod.rs (171) facade: imports + parse_import_statement dispatcher, seed_import_bindings, resolve_external_callee + child mod decls/globs - python_js.rs (188), go_rust.rs (187), java_csharp.rs (141), php_kotlin.rs (223), rest.rs (179): per-language parse fns Facade-called parsers widened to pub(crate); children import sibling context/helpers/predicates via super::super and are otherwise self-contained. Public API and behavior unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…er 1,000 lines
Decompose crates/gwiki/src/sources.rs (1,019 lines) into a sources/ facade
with cohesive child modules, each well under the 1,000-line limit:
- mod.rs — facade: shared consts + public re-exports
- types.rs — SourceKind/IngestionMethod/CompileStatus/SourceDraft/
SourceDraftRef/SourceRecord/SourceReplay/SourceReplayOptions
- manifest.rs — SourceManifest + lock handling + SourceRecordParts
- render.rs — manifest rendering, index preservation, url/id helpers
- atomic.rs — atomic index file writes
Cross-module helpers (render_entry, canonicalize_location,
existing_index_without_manifest, source_id, PreservedSourceIndex,
write_atomic) widened to pub(crate). Public API and behavior unchanged.
Validation: cargo fmt --all --check clean; cargo clippy -p gobby-wiki
--all-targets -- -D warnings clean; cargo test -p gobby-wiki --lib sources
= 21 passed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…r 1,000 lines Decompose the 1,041-line ingest/pdf.rs into a pdf/ facade module: - mod.rs: facade wiring + the private cross-module summary structs - types.rs: public PDF data model (pub(crate) mod for crate reachability) - ingest.rs: ingest entry points (pub(crate) mod for crate reachability) - markdown.rs: vision-merged Markdown rendering - render.rs: pdfium page rendering + text-layer extraction - tests.rs: unit tests Public API and behavior preserved. Cross-module helpers widened to pub(crate); documents-feature-gated imports/re-exports kept cfg-correct so both default and --no-default-features build clean under -D warnings. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… modules under 1,000 lines Decompose the 1,090-line research_loop.rs monolith into a facade module directory, each file under the 1,000-line limit: - mod.rs facade: module decls + pub(crate) re-exports - types.rs public data model, config, and trait surface - engine.rs ResearchLoop struct + impl and internal loop state - helpers.rs prompt rendering, action parsing, source validation - tests.rs unit tests with fakes ResearchLoop (private fields, accessed by its impl) moves to engine.rs; ResearchLoopDeps and the API/data types stay in types.rs. Public API and behavior preserved. Validated under default and --no-default-features. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…drift Add docs/guides/gwiki-user-guide.md, a task-focused reference covering all 22 gwiki subcommands (install, scopes, ingest, search/ask, navigate, research/compile, maintenance, vault model, AI routing, degradation, troubleshooting), and link it from the guides index in place of the "forthcoming" note. Fix the compile entry in contract.rs and gwiki.contract.json to match the real clap CLI: positional [TOPIC], --outline (repeatable), --kind source|concept|topic, --target PAGE, --write-intent; drop the phantom --topic/--output flags and article|stub kind values. The cli_contract drift test now reflects the binary the daemon consumes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Captures the release-prep plan: gcode 1.0.0, gwiki 0.3.0, gcore 0.4.0, patch bumps for gsqz/gloc/ghook, gobby-core pin cascade, CHANGELOG/doc sync, PR-to-main flow, and the dependency-ordered tag/publish cycle. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…h gsqz/gloc/ghook Coordinated release across all six crates: - gobby-code 0.9.9 -> 1.0.0 (first stable) - gobby-wiki 0.2.0 -> 0.3.0 - gobby-core 0.3.0 -> 0.4.0 (breaking pre-1.0 minor) - gobby-squeeze 0.4.5 -> 0.4.6 - gobby-hooks 0.4.5 -> 0.4.6 - gobby-local 0.1.3 -> 0.1.4 Cascade the gobby-core path-dep pin to 0.4.0 in gcode, gwiki (dep + dev-dep), gloc, and ghook (a 0.x minor bump is breaking under Cargo semver). Update the public-boundary guardrail test to match. Regenerate Cargo.lock. Add the six new CHANGELOG sections and sync version references in README and docs/guides (release-guide, ghook/gcore guides). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Linter diff in the way? Review this PR in Change Stack to focus on meaningful changes and expand context only when needed. Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughMigrates CI to nextest and pins actions; introduces gcode 1.0 with new grep -w, symbol-at, and graph contracts; rebuilds Codewiki generation; enforces BM25-only FTS; adds DB connectors, broker validation, schema checks; refactors indexing/import-resolution; updates docs and manifests. ChangesGCode features, Codewiki rebuild, search/indexing, and CI updates
Sequence Diagram(s)sequenceDiagram
participant User
participant gcode-CLI
participant DB
participant FalkorDB
participant FS
User->>gcode-CLI: codewiki --edge-limit N --format json
gcode-CLI->>DB: read visible files/symbols (ro)
gcode-CLI->>FalkorDB: fetch CALLS/IMPORTS (edge_limit)
gcode-CLI->>FS: write incremental docs + metadata
gcode-CLI-->>User: run summary + generated docs
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
Coordinated tagged release
Prep for a full release across all six workspace crates. Effectively the entire
workspace changed since the last tags (58 commits since
gcode-v0.9.9).Version bumps
gobby-code0.9.9→1.0.0gcode-v1.0.0gobby-wiki0.2.0→0.3.0gwiki-v0.3.0gobby-core0.3.0→0.4.0gobby-core-v0.4.0gobby-squeeze0.4.5→0.4.6gsqz-v0.4.6gobby-local0.1.3→0.1.4gloc-v0.1.4gobby-hooks0.4.5→0.4.6ghook-v0.4.6What's here
gobby-core0.3.0 → 0.4.0 is breaking underCargo's pre-1.0 semver, so the
gobby-corepath-depversionpin moves to0.4.0in gcode, gwiki (dep + dev-dep), gloc, and ghook. The public-boundaryguardrail test was updated to match, and
Cargo.lockregenerated.tags (per-crate Added/Changed/Fixed + CI/CD).
docs/guides(release-guide,ghook/gcore guides) updated to the new versions.
Local validation (all green)
cargo fmt --all --checkcargo clippy --workspace --all-targets -- -D warningscargo nextest run --workspace --no-default-features— 1358 passedcargo test --doc --workspace --no-default-featuresAfter merge
Tags are pushed in dependency order —
gobby-core-v0.4.0first (wait forcrates.io indexing), then the five binary crates one tag per push (gwiki last,
since its release re-verifies the published
gobby-coreaifeature).🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
symbol-atcommand for locating symbols by file locationgrepcommand with whole-word (-w) matching for code searchcallersandusagescommands for dependency impact analysisgraphcommand family for visualization and relationship managementChanged
Bug Fixes