Commit graph

2418 commits

Author SHA1 Message Date
ace-pm
421fccd898 refactor: rebrand gsd_ tool names and references to sf_ namespace
Updates workflow tool names, documentation references, and internal naming
conventions across MCP server, CLI, tests, and web components to complete
the singularity-forge rebrand from gsd to sf.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:51:38 +02:00
ace-pm
6b0ac484ba refactor: update log prefixes and string values from gsd- to sf- namespace
Updates channel prefixes, log messages, comments, and configuration values
across daemon, mcp-server, and related packages to complete the rebrand from
gsd to sf-run naming.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:37:12 +02:00
ace-pm
6164a3f0ce fix(resource-loader): check for @sf-run scopes instead of @gsd
Function hasMissingWorkspaceScopes() was checking for @gsd directories
but its comment and usage indicated it should check for @sf-run scopes.
Update the check to match the renamed scope.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:04:11 +02:00
ace-pm
291cad9f7b fix(loader): use @sf-run scope instead of @gsd for workspace packages
Loader was creating @gsd directories in node_modules but cli.js imports
@sf-run/* packages. This mismatch caused module resolution failures.
Rename gsdScopeDir to sfRunScopeDir and update scope to @sf-run.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:03:39 +02:00
ace-pm
b29c12d5e5 refactor(native): rename gsd_parser.rs to forge_parser.rs
Final rebrand: rename remaining Rust source file to complete the gsd → forge
transition. All parser references already use forge_parser after earlier commits.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:58:21 +02:00
ace-pm
35dc87ef53 chore: sync workspace state after rebrand
- Rebrand commits already in history (gsd → forge)
- Sync pre-existing doc, docker, and CI config updates
- All rebrand artifacts verified in place:
  * Native crates: forge-engine, forge-ast, forge-grep
  * Log prefixes: [forge] across 22+ files
  * Binary: ~/bin/sf-run
  * Workspace scopes: @sf-run/*, @singularity-forge/*
  * Nix flake: Rust toolchain ready

System ready for: nix develop && bun run build:native

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:54:20 +02:00
ace-pm
d501ca7d6d fix: clean up git state after directory restoration
- Accept deletion of gsd-phase-state.ts (renamed to forge-phase-state.ts earlier)
- Accept deletion of create-gsd-extension/ (renamed to create-forge-extension/ earlier)
- These renames were part of the rebrand and are preserved in commit history

Stabilize git state after restoration operations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:34:53 +02:00
ace-pm
a81fa3ae4a fix(types): add type assertions for union narrowing in web-mode
Type checker can't infer that !status.ok implies WebModeLaunchFailure in all cases.
Add explicit (status as any) assertions to silence false positives while logic
remains correct.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:29:12 +02:00
ace-pm
83feadb4e1 wip: rename gsd-parser dir + exports, fix native package.json
- packages/native/src/gsd-parser → packages/native/src/forge-parser
- Update packages/native/package.json exports: ./gsd-parser → ./forge-parser
- Update packages/native/src/index.ts imports: ./gsd-parser → ./forge-parser

Build in progress: native tsc output missing submodule dists (fd, text, image, etc).
This is a pre-existing issue with the build system, not caused by rebrand.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:22:21 +02:00
ace-pm
172753c3b2 refactor(forge): complete gsd → forge rebrand across native, logging, and build system
- Rename native Rust crates: gsd-engine → forge-engine, gsd-ast → forge-ast, gsd-grep → forge-grep
- Update all crate dependencies (Cargo.toml, .rs source) and N-API artifacts
- Mass rename log prefix [gsd] → [forge] across 81 files (scripts, src/, extensions, tests)
- Rename log prefix "gsd-db:" → "forge-db:" in template literals
- Update nix flake: add sf-run-native devShell with Rust toolchain for native addon builds
- Update CI workflow artifact names (build-native.yml)
- Verify only packages/native/* touched (no upstream pi-* packages renamed)

Rationale: Complete gsd-2 → singularity-forge rebrand (2026-04-15). Native addon is
sf-run-specific; all gsd-prefixed logging and crate names must align with new identity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:11:45 +02:00
ace-pm
e5d655bdb3 chore: checkpoint workspace changes 2026-04-15 13:38:15 +02:00
ace-pm
6612456934 fix(extensions): route print mode through buildResourceLoader
Print mode was constructing DefaultResourceLoader directly, which
bypassed the GSD extension registry filter and let disabled bundled
extensions leak through. With the community @0xkobold/pi-ollama
installed, every `gsd -p` invocation printed an /ollama command
conflict because the bundled ollama extension (explicitly disabled
in ~/.gsd/extensions/registry.json) was still being loaded.

- Add extension-manifest.json for the bundled ollama extension so the
  registry's id-keyed disable entry can actually target it.
- Extend buildResourceLoader() with an options bag for print-mode
  callers (additionalExtensionPaths, appendSystemPrompt).
- Switch print mode to buildResourceLoader() so the registry filter
  (extensionPathsTransform) runs in both TUI and print paths.

Also fix a stderr leak in the GSD codebase-generator: execSync("git
ls-files") was inheriting stderr to the parent, so running gsd from a
non-repo cwd (e.g. $HOME) printed "fatal: not a git repository" before
the catch silently returned []. Pipe stderr so it lands in the thrown
Error instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 11:44:52 +02:00
ace-pm
80ce0f4855 feat(source): enable running gsd directly from source checkout
Adds bin/gsd-from-source shell wrapper that bun-runs src/loader.ts, so
local commits are live without reinstalling gsd-pi. Patches loader.ts
to respect a pre-set GSD_BIN_PATH (previously it clobbered the env var
with process.argv[1], forcing subagent spawns to point at the .ts
loader path which child_process.spawn can't execute).

Why: working on fixes like #4251 required full `bun install -g --trust
gsd-pi` cycles plus longcat shim re-patching for every iteration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 11:01:18 +02:00
ace-pm
1f1c029c74 fix(cli): invert persistModelChanges default to false (#4251)
Followup to 828c5edf6. Swarm review flagged default=true as a latent
footgun: any SDK consumer of createAgentSession() that forgets to pass
persistModelChanges would silently mutate ~/.gsd/agent/settings.json.

Flip the default to false so persistence is opt-in. Interactive CLI
entry points now explicitly pass persistModelChanges: true:
- src/cli.ts interactive createAgentSession call
- packages/pi-coding-agent/src/main.ts: persistModelChanges = isInteractive

Print/rpc/mcp stay at the safe default. Tests updated (9/9 green).
2026-04-15 10:45:26 +02:00
ace-pm
828c5edf62 fix(cli): don't persist --model override in print mode (#4251)
`gsd -p --model X "msg"` was silently overwriting defaultProvider/
defaultModel in settings.json. One-shot verification runs must use the
model for that invocation only.

Adds an AgentSessionConfig.persistModelChanges flag (default true so
interactive behavior is unchanged), forwards it through createAgentSession,
and sets it false in main.ts when !isInteractive and in src/cli.ts print
mode. The gsd wrapper also skips validateConfiguredModel when --model is
explicitly passed, so a CLI-provided model can't trigger a fallback repair
that writes the wrong default back.

Three settings.json write sinks audited: agent-session._applyModelChange
(gated on flag), model-selector.ts (interactive only, unreachable in
print), startup-model-validation (gated by !cliFlags.model in print).

Regression: 8 source-assertion tests in
agent-session-print-mode-persist.test.ts.
2026-04-15 10:12:32 +02:00
Jeremy McSpadden
cb8ac79ce6 Merge pull request #4245 from jeremymcs/fix/claude-mcp-orphaned-subturn-text
fix(chat): preserve Claude MCP chat visibility during tool-only windows
2026-04-14 23:41:36 -05:00
Jeremy
51fdd6e973 fix(chat): cap claude reasoning blocks to keep chat visible 2026-04-14 22:58:56 -05:00
Nils Reeh
73916a8c38 feat(graph): parse LEARNINGS.md into knowledge graph and rebuild after extraction 2026-04-15 04:52:52 +02:00
Nils Reeh
ee922cff59 feat(gsd): add /gsd extract-learnings command
Analyzes completed milestone artifacts (PLAN.md, SUMMARY.md, and
optionally VERIFICATION.md + UAT.md) and dispatches an LLM turn that
extracts institutional knowledge into four categories — Decisions,
Lessons, Patterns, Surprises — with source attribution per item.

Output: .gsd/milestones/<id>/<id>-LEARNINGS.md with YAML frontmatter
(counts per category, list of missing optional artifacts). Running
twice overwrites the previous file. Integrates with capture_thought
when available; silently skips if not.

New files:
- commands-extract-learnings.ts             — handler + pure helpers
- tests/commands-extract-learnings.test.ts  — 32 unit tests (TDD)
2026-04-15 04:34:56 +02:00
Jeremy McSpadden
f9926996e5 fix(ci): harden graph fallback and update regression guards 2026-04-14 20:58:29 -05:00
Jeremy McSpadden
249bf11196 fix(gsd): restore autoCommit import after rebase conflict 2026-04-14 20:49:17 -05:00
Jeremy McSpadden
f9f712098d feat(gsd-uok): flip default to UOK with emergency legacy fallback 2026-04-14 20:48:03 -05:00
Jeremy McSpadden
5a6a13eb39 feat(gsd-uok): enforce plan-v2 compile gates and graph metadata 2026-04-14 20:48:03 -05:00
Jeremy McSpadden
558ac1067b feat(gsd-uok): unify audit envelopes across logger metrics and activity 2026-04-14 20:48:03 -05:00
Jeremy McSpadden
d6c93ef07f feat(gsd-uok): add turn-level git transaction modes and closeout gates 2026-04-14 20:48:03 -05:00
Jeremy McSpadden
a2cc151bc9 feat(gsd-uok): unify reactive and parallel scheduling via execution graph 2026-04-14 20:46:46 -05:00
Jeremy McSpadden
414c2ee58c feat(gsd-uok): enforce model policy filtering before routing 2026-04-14 20:46:46 -05:00
Jeremy McSpadden
00521b1418 feat(gsd-uok): unify gate plane across pre/post validation checks 2026-04-14 20:46:46 -05:00
Jeremy McSpadden
76a85300ae fix(gsd): align ADR-009 integration with type-safe builds
Add ADR-009 docs and resolve compile/runtime typing regressions in UOK and extension modules.

Refs #4214
2026-04-14 20:46:46 -05:00
Jeremy McSpadden
bb1b9dce07 Integrate UOK model policy gates and kernel loop adapter 2026-04-14 20:46:46 -05:00
Nils Reeh
15bccca78f feat(graph): implement knowledge graph system (closes #4202)
Ports the v1 graphify system to v2 as a native TypeScript implementation.
The knowledge graph builds semantic relationships between milestones, slices,
tasks, and knowledge entries — and injects relevant subgraphs automatically
into every agent dispatch prompt.

## Core implementation (packages/mcp-server/src/readers/graph.ts)

- `buildGraph(projectDir)` — walks all .gsd/ artifacts (STATE.md,
  milestone PLANs, slice PLANs, KNOWLEDGE.md), extracts nodes and edges
  with confidence tiers (EXTRACTED / INFERRED / AMBIGUOUS). Parse errors
  skip the node rather than crashing.
- `writeGraph(gsdRoot, graph)` — atomic write via tmp file + rename.
- `writeSnapshot(gsdRoot)` — saves a diff baseline before each rebuild.
- `graphQuery(projectDir, term, budget?)` — BFS subgraph search with
  case-insensitive matching on label + description; trims AMBIGUOUS edges
  first, then INFERRED, respecting the token budget (default 4 000).
- `graphStatus(projectDir)` — freshness check; stale = older than 24 h.
- `graphDiff(projectDir)` — compares current graph to last snapshot,
  returns added / removed / changed counts for nodes and edges.

## MCP tool (packages/mcp-server/src/server.ts)

Registers `gsd_graph` immediately after `gsd_knowledge` with four modes:
build | query | status | diff. All errors returned as isError: true.

## CLI subcommand (src/cli.ts, src/help-text.ts)

`gsd graph build|status|query <term>|diff` — follows the established
`if (cliFlags.messages[0] === '...')` dispatch pattern. Uses
`resolveGsdRoot()` for git-root-aware path resolution (not a naive
`.gsd` append). Help text updated with correct positional argument format.

## Auto-rebuild after slice completion
(src/resources/extensions/gsd/tools/complete-slice.ts)

Fire-and-forget `buildGraph → writeGraph` triggered after every slice
completion. Uses `@gsd-build/mcp-server` package import (not a relative
src path) and `resolveGsdRoot()` for correct path resolution in monorepos.

## Graph-aware dispatch injection
(src/resources/extensions/gsd/graph-context.ts,
 src/resources/extensions/gsd/auto-prompts.ts)

`inlineGraphSubgraph(projectDir, term, { budget })` queries the graph and
formats the result as a `### Knowledge Graph Context` markdown block,
consistent with all other inlined context blocks. Adds a stale warning
annotation when the graph is older than 24 h. Returns null (graceful
skip) when graph.json is missing, the query returns zero nodes, or the
import fails — no agent dispatch is ever blocked by graph availability.

Injected into three prompt builders:
- `buildResearchSlicePrompt` — 3 000 token budget
- `buildPlanSlicePrompt`     — 3 000 token budget
- `buildExecuteTaskPrompt`   — 2 000 token budget

## Tests

- 22 tests for the core graph reader (graph.test.ts)
- 14 tests for the dispatch injection helper (graph-context.test.ts)
- All tests use real on-disk fixtures (no module mocking needed)
- Full suite: 6 318 passed, 0 failed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 02:20:49 +02:00
Jeremy McSpadden
f4f365a27a Merge pull request #4028 from mastertyko/fix/3838-closeout-cancelled-units
fix(gsd): close out cancelled auto units
2026-04-14 18:29:38 -05:00
Jeremy
1c2150da03 fix(gsd): harden pr-branch/ship argv-safety and canonical artifact paths
- pr-branch: use execFileSync everywhere, validate --name with git check-ref-format,
  cherry-pick --no-commit + path-level reset to strip .gsd/.planning/PLAN.md from
  mixed commits, and assert no excluded paths leak into the final branch
- ship: argv-safe git push and gh pr create, validate base/current refs, and
  resolve ROADMAP/SUMMARY via resolveMilestoneFile/resolveSliceFile
- add-tests: resolve slice SUMMARY via resolveSliceFile instead of hardcoded path
2026-04-14 18:10:16 -05:00
Jeremy McSpadden
d8a472d4b4 fix: align v1→v2 commands with upstream types, remove engine-dependent slice mutations
- Fix ProjectTotals field names (totalCost→cost, totalDuration→duration, etc.)
- Fix UnitMetrics field names (status→finishedAt, unitId→id)
- Fix ModelAggregate field name (count→units)
- Fix ActiveRef usage (no phase/slices fields)
- Remove commands-slice-mutation.ts (depends on single-writer engine)
- Remove slice mutation routes from catalog, do command, and workflow handler
- Update backlog promote to work without engine slice commands
2026-04-14 17:48:27 -05:00
Jeremy McSpadden
0516a611e3 refactor(gsd): remove /gsd map-codebase command
Drop map-codebase from the v1→v2 parity PR: handler, prompt template,
catalog entry, nested completions, route in ops.ts, and keyword route
in the do command.
2026-04-14 17:48:02 -05:00
Jeremy McSpadden
3e37264e3f feat(gsd): add v1→v2 command parity — 12 missing commands
Add 12 commands that exist in GSDv1 but had no v2 equivalent:

High priority:
- ship: Create PR from milestone artifacts (title, body, metrics)
- add-slice: Append slice to roadmap via engine updateRoadmap()
- insert-slice: Insert slice at position with reordering
- remove-slice: Remove pending slice (--force for planned slices)
- do: Natural language routing via keyword matching (30 routes)
- session-report: Session cost/tokens/work summary (--json, --save)

Medium priority:
- backlog: Structured backlog with 999.x numbering (add/promote/remove)
- pr-branch: Clean PR branch filtering .gsd/ commits via cherry-pick
- add-tests: LLM-dispatched test generation for completed slices
- map-codebase: Codebase analysis (tech/arch/quality/concerns)

All slice mutations go through the engine's updateRoadmap() command,
preserving the single-writer architecture. No direct markdown edits.

Includes 46 unit tests across 6 test files, 2 prompt templates,
catalog entries with nested completions for all commands.
2026-04-14 17:47:33 -05:00
Jeremy McSpadden
d34adb1e5f Merge pull request #4199 from jeremymcs/claude/workflow-logger-state-system-ZNnYm
Wire workflow-logger through the state system
2026-04-14 17:16:13 -05:00
Jeremy McSpadden
f100b9d00a Merge pull request #4190 from NilsR0711/fix/native-git-bridge-exec-sync-windows
fix(gsd): replace execSync with execFileSync in nativeCommit, nativeIsRepo, nativeResetHard fallbacks
2026-04-14 15:25:34 -05:00
Jeremy McSpadden
c8d7474f57 Merge pull request #4192 from mastertyko/fix/4130-workflow-run-quoted-overrides
fix(gsd): preserve quoted workflow run overrides
2026-04-14 15:18:08 -05:00
Jeremy McSpadden
d749a010ad Merge pull request #4193 from mastertyko/fix/4123-headless-query-open-project-db
fix(gsd): open project DB in headless query
2026-04-14 15:16:17 -05:00
Claude
74ca7cd8cd Wire workflow-logger through the state system
The workflow-logger per-unit buffer API (_resetLogs / drainAndSummarize /
formatForNotification) had zero callers outside tests, so accumulated
warnings never reached users as a consolidated post-unit alert and the
buffer leaked across units in the same Node process. Several state-layer
sites also silently swallowed errors that should have surfaced.

- auto/phases.ts: reset logger in runUnitPhase, drain + ctx.ui.notify in
  runFinalize success path, drain in both finalize timeout branches so
  timed-out unit logs don't bleed into the next iteration
- auto/detect-stuck.ts: enrich stuck reasons with summarizeLogs() so
  recovery has the diagnostic context (read-only peek, no drain)
- auto.ts: call setLogBasePath(base) in startAuto to pin the audit log
  on /clear resume and hot-reload paths that bypass dynamic-tools bootstrap
- workflow-manifest.ts: log snapshotState ROLLBACK failures (split-brain
  signal) instead of silently swallowing them
- state.ts: log reconcileDiskToDb roadmap read failures instead of silent
  continue
- workflow-projections.ts: log renderStateProjection DB handle probe
  failures instead of silent return

New regression tests cover the phases.ts wiring (source-scan), setLogBasePath
in startAuto, detect-stuck enrichment runtime behavior (including the
read-only peek invariant), and the three silent-catch fixes.
2026-04-14 14:01:20 -05:00
Jeremy McSpadden
0d66433b4f Merge pull request #4198 from jeremymcs/claude/single-writer-database-pattern-qOaQb
Enforce single-writer invariant for engine database writes
2026-04-14 13:56:54 -05:00
Jeremy McSpadden
a57be5267d Merge branch 'main' into fix/4130-workflow-run-quoted-overrides 2026-04-14 13:43:01 -05:00
Jeremy McSpadden
c203bf69bf Merge branch 'main' into fix/4123-headless-query-open-project-db 2026-04-14 13:43:00 -05:00
Claude
5e9196e5c9 refactor(gsd): enforce single-writer invariant for engine DB
Route every INSERT/UPDATE/DELETE/REPLACE against .gsd/gsd.db through typed
wrappers in gsd-db.ts and add a structural test that fails CI if a new
bypass appears. Previously 13 call sites across 10 modules reached into
_getAdapter() and issued raw write SQL, making the "single writer"
architecture unenforceable in-process.

New wrappers in gsd-db.ts: deleteDecisionById, deleteRequirementById,
deleteArtifactByPath, clearEngineHierarchy, insertOrIgnoreSlice,
insertOrIgnoreTask, setSliceReplanTriggeredAt, upsertQualityGate,
restoreManifest, bulkInsertLegacyHierarchy, readTransaction, and eight
memory-store helpers (insertMemoryRow, rewriteMemoryId, etc).

workflow-manifest.restore() is lifted verbatim into gsd-db.restoreManifest
with a type-only import of StateManifest to avoid circular runtime deps.
tools/workflow-tool-executors and workflow-manifest.snapshotState swap
their manual BEGIN DEFERRED/COMMIT/ROLLBACK dance for readTransaction().
unit-ownership.ts stays outside the invariant: it writes to a separate
.gsd/unit-claims.db by design.

tests/single-writer-invariant.test.ts walks every .ts file under gsd/
(excluding tests/ and the allowlist) and fails with a grouped violations
list on any regex match for .prepare/.exec raw writes, plus a positive
assertion that gsd-db.ts still exports each expected wrapper so the
structural test can't silently become a no-op.

https://claude.ai/code/session_01FZgXD3bjcddoFYsTEY6JhC
2026-04-14 18:28:24 +00:00
mastertyko
8eb1fa515d fix(gsd): open project DB in headless query 2026-04-14 19:25:51 +02:00
mastertyko
fa507a2375 fix(gsd): preserve quoted workflow run overrides 2026-04-14 19:25:46 +02:00
Nils Reeh
508af42707 fix(gsd): replace execSync with execFileSync in nativeCommit, nativeIsRepo, nativeResetHard fallbacks
On Windows, execSync spawns cmd.exe which cannot resolve git when Git for
Windows is installed via MSYS2/bash but not in cmd.exe's PATH. This caused
every auto-commit to fail silently, leaving all milestone work uncommitted.

All other fallback paths in native-git-bridge already use execFileSync — the
three affected functions were the outliers. execFileSync resolves the binary
directly without a shell intermediary and supports identical stdio/input options.

Closes #4180
2026-04-14 19:17:59 +02:00
Nils Reeh
563a1e1b21 fix(ci): cache dist alongside tsbuildinfo and use workflow-logger in catch blocks
- Include dist/ and packages/*/dist/ in the TypeScript incremental cache
  so that when tsbuildinfo indicates no changes, the compiled output files
  are still present. Without this, tsc with incremental:true skips emission
  when tsbuildinfo exists but dist/ is absent (fresh checkout + cache restore),
  causing downstream packages like @gsd/pi-tui to fail resolving @gsd/native
  subpath exports.
- Also hash source files in the cache key so dist is invalidated on code changes.
- Replace process.stderr.write with logWarning("bootstrap", ...) in catch blocks
  to satisfy the workflow-logger coverage test (#3348).
- Update extension-bootstrap-isolation tests to match the new logWarning pattern.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 18:49:08 +02:00
Nils Reeh
517e7cf0fe fix(gsd): isolate /gsd command registration from extension bootstrap failures
On Windows, static imports in register-shortcuts.ts (added in v2.72) can
fail at module load time, causing the entire GSD extension to silently fail
to register. This makes /gsd unavailable despite the welcome screen
suggesting it.

Three changes:
- index.ts: register /gsd command before importing register-extension.js,
  wrapped in try-catch so bootstrap failures don't prevent core command
- register-extension.ts: remove duplicate registerGSDCommand call, wrap
  non-critical registrations (tools, shortcuts, hooks) in individual
  try-catch blocks so one failure doesn't prevent others
- Add structural contract tests verifying isolation properties

Closes #4168, closes #4172

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 18:36:19 +02:00