mirror of
https://github.com/proxysoul/Empryo.git
synced 2026-11-07 06:25:57 -10:00
chore: governance, build hardening, mintlify sweep
- governance: CODEOWNERS, GOVERNANCE.md, PRIVACY.md, FUNDING.yml, PR template - CONTRIBUTING.md: in-scope/out-of-scope contribution policy - SECURITY.md: drop stale supported-versions table - scripts/build.ts: minify + sourcemap:none + abs-path scrub + sentinel guard under NODE_ENV=production - mintlify: rename-refactor sample, broken paths, theme list (36), casing, license name Co-Authored-By: SoulForge <[email protected]>
This commit is contained in:
20 files changed
+391
-28
No files matched your search
@@ -0,0 +1,30 @@
|
||||
# SoulForge code owners.
|
||||
#
|
||||
# Architecture and core IP paths require maintainer review on every PR.
|
||||
# Other paths (providers, components, docs) accept community contributions
|
||||
# with regular review. See CONTRIBUTING.md for the full governance policy.
|
||||
|
||||
# Default — every file requires maintainer review unless overridden below.
|
||||
* @proxysoul
|
||||
|
||||
# Architecture / core IP — locked. Discuss in an issue before any PR.
|
||||
/src/core/intelligence/ @proxysoul
|
||||
/src/core/agents/ @proxysoul
|
||||
/src/core/context/manager.ts @proxysoul
|
||||
/src/core/prompts/ @proxysoul
|
||||
/src/core/memory/recall.ts @proxysoul
|
||||
/src/core/compaction/ @proxysoul
|
||||
/src/hearth/ @proxysoul
|
||||
|
||||
# Build / publish — sensitive to source-map / identifier leaks.
|
||||
/scripts/build.ts @proxysoul
|
||||
/scripts/bundle.sh @proxysoul
|
||||
/.github/workflows/ @proxysoul
|
||||
/package.json @proxysoul
|
||||
|
||||
# License / governance docs.
|
||||
/LICENSE @proxysoul
|
||||
/COMMERCIAL_LICENSE.md @proxysoul
|
||||
/GOVERNANCE.md @proxysoul
|
||||
/CONTRIBUTING.md @proxysoul
|
||||
/CODEOWNERS @proxysoul
|
||||
@@ -0,0 +1,5 @@
|
||||
# GitHub Sponsors button + alternative funding links.
|
||||
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/displaying-a-sponsor-button-in-your-repository
|
||||
|
||||
github: [proxysoul]
|
||||
custom: ["https://paypal.me/waeru"]
|
||||
@@ -0,0 +1,31 @@
|
||||
<!--
|
||||
Read CONTRIBUTING.md before opening this PR.
|
||||
|
||||
Out-of-scope PRs are closed without review. Out of scope means:
|
||||
- src/core/intelligence/, src/core/agents/, src/core/context/manager.ts
|
||||
- src/core/prompts/, src/core/memory/recall.ts, src/core/compaction/
|
||||
- src/hearth/ server internals
|
||||
- New tools, new agents, new commands
|
||||
|
||||
For architecture proposals: open a Discussion, not a PR.
|
||||
-->
|
||||
|
||||
## What
|
||||
|
||||
<!-- One sentence: what does this change? -->
|
||||
|
||||
## Why
|
||||
|
||||
<!-- One paragraph: what problem does it solve, what was the prior behavior? -->
|
||||
|
||||
## Scope check
|
||||
|
||||
- [ ] I read `CONTRIBUTING.md` and this PR is in the **In scope** table.
|
||||
- [ ] This PR does not touch any path in the **Out of scope** list.
|
||||
- [ ] One feature or fix per PR (no drive-by refactors).
|
||||
- [ ] `bun run lint:fix && bun run format && bun run typecheck` passes.
|
||||
- [ ] If behavior changed, a test was added or updated.
|
||||
|
||||
## Verification
|
||||
|
||||
<!-- How did you verify this works? Steps, commands, or screenshots. -->
|
||||
+42
-1
@@ -158,7 +158,48 @@ src/
|
||||
└── ... # other hooks
|
||||
```
|
||||
|
||||
## Rules
|
||||
## Contribution scope
|
||||
|
||||
SoulForge is open source under BUSL-1.1 with **strict architectural governance**. The maintainer (proxysoul) owns product direction. To respect everyone's time, the scope of acceptable contributions is explicit and enforced.
|
||||
|
||||
**Read this section before writing code.** PRs outside scope will be closed without review. This is not personal — it's how the project stays coherent with one maintainer.
|
||||
|
||||
### In scope — open a PR directly
|
||||
|
||||
| Area | Path |
|
||||
|---|---|
|
||||
| Bug fixes | anywhere |
|
||||
| LLM providers | `src/core/llm/providers/*.ts` |
|
||||
| UI polish, themes, keybindings, accessibility | `src/components/`, `src/hooks/`, `src/stores/` |
|
||||
| Tool fixes (perf, edge cases, error messages — no behavior changes) | `src/core/tools/` (excluding new tools) |
|
||||
| Documentation | `mintlify-docs/`, `README.md`, recipes |
|
||||
| Tests | `tests/` |
|
||||
| Build, CI, packaging | `scripts/`, `.github/workflows/` |
|
||||
|
||||
### Out of scope — PRs will be closed unread
|
||||
|
||||
These paths define product direction. **Do not open PRs against them.** They are protected by `CODEOWNERS` and maintainer review is mandatory; drive-by changes are closed without discussion.
|
||||
|
||||
- `src/core/intelligence/` — repo map, ranking, indexing, backend router
|
||||
- `src/core/agents/` — agent loop, dispatch, bus, subagent orchestration
|
||||
- `src/core/context/manager.ts` — context assembly
|
||||
- `src/core/prompts/` — system prompts, family detection, mode overlays
|
||||
- `src/core/memory/recall.ts` — memory recall scoring
|
||||
- `src/core/compaction/` — compaction strategies, working state extraction
|
||||
- `src/hearth/` server internals — pairing protocol, permission engine
|
||||
- New tools, new agents, new commands
|
||||
|
||||
If you have an idea touching these paths, **open a Discussion**, not an issue or PR. The maintainer will respond `yes`, `no`, or `let's design it together` before any code is written. This is the only path forward for architecture proposals — it protects your time more than it protects the project.
|
||||
|
||||
The Discussions board is the right place for: "what if SoulForge did X", "I'd like to add Y", "have you considered Z architecture". Issues are for bugs and concrete feature requests in the in-scope areas above.
|
||||
|
||||
### Why this is strict
|
||||
|
||||
Single maintainer. No co-maintainers, no committee. Every architecture PR is hours of design review the maintainer cannot afford to spend on speculative direction. The scope above is the contract: anything in-scope gets a fair review, anything out-of-scope is a closed-without-review fast path so contributors don't waste time waiting.
|
||||
|
||||
Same governance model as SQLite, Postgres, FreeBSD, Linux subsystems, aider. Open code, controlled direction.
|
||||
|
||||
## Code rules
|
||||
|
||||
These are non-negotiable. PRs that break them will be asked to fix before merge.
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# Governance
|
||||
|
||||
SoulForge is a single-maintainer open-source project. This document explains how decisions get made.
|
||||
|
||||
## Maintainer
|
||||
|
||||
@proxysoul owns:
|
||||
|
||||
- Product direction and roadmap
|
||||
- Architecture decisions (agent design, intelligence layer, prompts, context strategy)
|
||||
- Release cadence and version numbers
|
||||
- Final say on every merged PR
|
||||
- License interpretation and commercial license issuance
|
||||
|
||||
## Decision-making
|
||||
|
||||
| Type of change | How it lands |
|
||||
|---|---|
|
||||
| Bug fix | Open a PR; maintainer reviews and merges |
|
||||
| Provider adapter | Open a PR; maintainer reviews and merges |
|
||||
| UI / theme / docs | Open a PR; maintainer reviews and merges |
|
||||
| Tool improvement (no architecture change) | Open a PR; maintainer reviews and merges |
|
||||
| New feature touching only "open" paths | Open an issue first to align; PR after |
|
||||
| Architecture change | Open an issue **first**. Maintainer responds yes / no / "let's discuss". Skip this and the PR gets closed. |
|
||||
| Public API / SDK change | Open an issue first; semver-stable contracts are not changed casually |
|
||||
| Build / publish pipeline | Open an issue first; sensitive to source-map and identifier leaks |
|
||||
|
||||
The "open an issue first" rule exists to save your time. The maintainer would rather say "no, here's why" in 5 minutes than have you spend a weekend on a PR that won't land.
|
||||
|
||||
## Why strict architectural governance
|
||||
|
||||
SoulForge's value is in how the pieces fit together — agent loop, intelligence, context, prompts, memory. The maintainer needs to keep that vision coherent across many releases. Open-source contributions to architecture would fragment that vision and slow the project down.
|
||||
|
||||
This is the same model used by SQLite, Postgres, FreeBSD subsystems, the Linux kernel, aider, and most successful single-maintainer open-source projects.
|
||||
|
||||
CODEOWNERS enforces this on GitHub: PRs touching IP-sensitive paths require maintainer review and cannot self-merge.
|
||||
|
||||
## What "open source" means here
|
||||
|
||||
- **Visibility:** every line of source is on GitHub. You can read, audit, and learn from it.
|
||||
- **Forkability:** you can fork the repo and patch it for yourself. BUSL-1.1 limits commercial redistribution for 4 years; converts to Apache 2.0 on March 15, 2030.
|
||||
- **Contribution:** PRs welcome in the areas listed in [CONTRIBUTING.md](CONTRIBUTING.md). Architecture is single-maintainer.
|
||||
- **Privacy:** SoulForge runs entirely on your machine. Your code is sent only to the LLM providers you choose. There is no SoulForge backend. See [PRIVACY.md](PRIVACY.md).
|
||||
|
||||
## License gates
|
||||
|
||||
| License | Use case |
|
||||
|---|---|
|
||||
| BUSL-1.1 (default) | Personal use, internal company use, non-redistribution. Free forever. |
|
||||
| [Commercial license](COMMERCIAL_LICENSE.md) | Repackaging or reselling SoulForge as a commercial product or service during the BUSL period. Email proxysoul to inquire. |
|
||||
| Apache 2.0 (auto-conversion) | All uses, after March 15, 2030. |
|
||||
|
||||
## Communication
|
||||
|
||||
- **Bug reports / feature requests:** [GitHub issues](https://github.com/proxysoul/soulforge/issues)
|
||||
- **Security disclosures:** see [SECURITY.md](SECURITY.md)
|
||||
- **Commercial license inquiries:** open a GitHub issue or contact via the email listed in COMMERCIAL_LICENSE.md
|
||||
- **Discussion:** [GitHub Discussions](https://github.com/proxysoul/soulforge/discussions) (when enabled)
|
||||
|
||||
## Forking
|
||||
|
||||
You're free to fork. If your fork ships under a different name and respects BUSL-1.1, that's fine. If you want to maintain a permanent fork, that's also fine — but understand that upstream changes won't merge automatically and you take on the maintenance burden yourself.
|
||||
|
||||
If you're forking because a PR was rejected: this governance model means architecture rejections are intentional, not arbitrary. A fork that re-applies rejected architecture changes is welcome to exist; it's just not what SoulForge is.
|
||||
|
||||
## Future
|
||||
|
||||
This is a single-maintainer project today. If at some point a sustainable funding model materializes (sponsorships, commercial licenses, acquisition), governance may evolve — additional maintainers, a steering committee, or a non-profit foundation. Any such change will be announced clearly in advance.
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
# Privacy
|
||||
|
||||
SoulForge is a **local-first** AI coding tool. This document describes exactly what data flows where, so you can verify the privacy model directly against the source.
|
||||
|
||||
## TL;DR
|
||||
|
||||
- SoulForge runs entirely on your machine.
|
||||
- There is no SoulForge backend. No telemetry. No analytics. No usage tracking.
|
||||
- Code from your project is sent **only** to the LLM providers you choose to enable.
|
||||
- API keys live in `~/.soulforge/secrets.json` (file mode `0600`) or your OS keychain.
|
||||
- Sessions, repo map, and memory are SQLite databases under `~/.soulforge/` and `<project>/.soulforge/`.
|
||||
|
||||
## What gets sent over the network
|
||||
|
||||
Three categories, all on actions you initiate:
|
||||
|
||||
### 1. LLM provider API calls
|
||||
|
||||
Every chat turn, tool call result, and dispatched subagent talks to the LLM provider you've selected. The request payload contains:
|
||||
|
||||
- The system prompt (varies by mode — see [`src/core/prompts/`](src/core/prompts/))
|
||||
- The conversation history for the current session
|
||||
- The current Soul Map / repo map injection (file list, exported symbol names)
|
||||
- File contents you asked the agent to read
|
||||
- Tool definitions and tool call results
|
||||
|
||||
This is the **same as every other AI coding tool**. Cursor, Claude Code, Aider, Continue all do this. The provider you pick (Anthropic, OpenAI, Google, etc.) is the destination.
|
||||
|
||||
You can verify the exact payload at runtime — set `BUN_DEBUG=1` and look at the network requests, or read [`src/core/agents/forge.ts`](src/core/agents/forge.ts) and the provider adapters in [`src/core/llm/providers/`](src/core/llm/providers/).
|
||||
|
||||
### 2. Web search (opt-in, with approval prompt)
|
||||
|
||||
When the agent decides to search the web (`web_search` tool), SoulForge prompts you for approval before each search. The search query goes to the configured search backend (Brave, DuckDuckGo, or Tavily) — never to SoulForge servers (there are none).
|
||||
|
||||
Disable: set `webSearch: false` in `~/.soulforge/config.json` or run with `--no-web-search`.
|
||||
|
||||
### 3. Page fetches (opt-in, with approval prompt)
|
||||
|
||||
When the agent decides to fetch a URL (`fetch_page` tool), it prompts you. The fetch goes to the URL you approve, optionally through Jina Reader for HTML cleanup.
|
||||
|
||||
## What does NOT leave your machine
|
||||
|
||||
- Your file system contents, except files the agent explicitly reads and includes in an LLM request you initiated.
|
||||
- Repo map, memory database, sessions — all in SQLite under `~/.soulforge/`.
|
||||
- API keys — stored locally in `~/.soulforge/secrets.json` (mode `0600`) or in your OS keychain when available.
|
||||
- Bug reports, error traces, performance metrics — none of this is collected. SoulForge has no telemetry.
|
||||
- Your usage patterns — when you type, what you ask, which models you use. Nobody is watching.
|
||||
|
||||
## What's in `~/.soulforge/`
|
||||
|
||||
```
|
||||
~/.soulforge/
|
||||
├── secrets.json # API keys, mode 0600 (you only)
|
||||
├── config.json # global config
|
||||
├── memory.db # global persistent memory (SQLite)
|
||||
├── sessions/ # session JSONL files (per project)
|
||||
├── lsp-servers/ # auto-installed LSP servers
|
||||
└── installs/ # auto-installed tooling (nvim, etc.)
|
||||
```
|
||||
|
||||
Per-project data lives in `<your-project>/.soulforge/`:
|
||||
|
||||
```
|
||||
<project>/.soulforge/
|
||||
├── config.json # project-specific config
|
||||
├── memory.db # project-scoped memory
|
||||
└── repomap.db # SQLite repo map (FTS5, PageRank scores)
|
||||
```
|
||||
|
||||
## Sensitive file blocking
|
||||
|
||||
By default, SoulForge refuses to read files matching these patterns (the agent gets an empty result, even if it asks):
|
||||
|
||||
- `.env`, `.env.*`
|
||||
- `*.pem`, `*.key`, `id_rsa*`, `id_dsa*`, `id_ecdsa*`, `id_ed25519*`
|
||||
- `credentials`, `credentials.json`
|
||||
- `.npmrc`, `.netrc`, `.pgpass`
|
||||
- Anything matching the user's `/privacy add` patterns
|
||||
|
||||
The list is in [`src/core/security/forbidden.ts`](src/core/security/forbidden.ts). Add your own patterns with `/privacy add <glob>` in the TUI or via the `forbidden` field in `~/.soulforge/config.json`.
|
||||
|
||||
## Hearth (remote control)
|
||||
|
||||
The optional Hearth daemon exposes SoulForge to a paired Telegram or Discord bot you set up on your own account. When enabled:
|
||||
|
||||
- Messages you send from your phone go through Telegram's / Discord's servers (their privacy policies apply).
|
||||
- The Hearth daemon runs locally on your machine.
|
||||
- Your code never leaves your host.
|
||||
|
||||
Disable: don't pair Hearth, or run `/hearth unpair`.
|
||||
|
||||
## License-key validation (future)
|
||||
|
||||
The codebase has scaffolding for a future "Pro" tier with license-key validation. **Today, no license check happens.** When/if a Pro tier ships:
|
||||
|
||||
- Validation will be a single HTTP call to a license server on startup.
|
||||
- The check will not transmit any project content — only the license key.
|
||||
- The Pro features will run locally; no cloud execution.
|
||||
|
||||
## Verifying the privacy story
|
||||
|
||||
You don't have to take this document's word for it. SoulForge is open source. Audit paths:
|
||||
|
||||
1. Read [`src/core/llm/`](src/core/llm/) for every outbound network call.
|
||||
2. Read [`src/core/agents/forge.ts`](src/core/agents/forge.ts) for what gets sent to LLMs.
|
||||
3. Read [`src/core/security/forbidden.ts`](src/core/security/forbidden.ts) for sensitive-file blocking.
|
||||
4. Run with `BUN_DEBUG=1` to see every HTTP request live.
|
||||
5. Use any local network monitor (Little Snitch, Wireshark) to confirm.
|
||||
|
||||
If you find an unintended data flow, please report via [SECURITY.md](SECURITY.md).
|
||||
|
||||
## Data deletion
|
||||
|
||||
Everything SoulForge stores is in `~/.soulforge/` and `<project>/.soulforge/`. Delete those directories and SoulForge has nothing on you.
|
||||
@@ -42,10 +42,3 @@ Use `/privacy` to add or remove forbidden file patterns:
|
||||
- **Project scope** — patterns in `.soulforge/forbidden` apply to current project
|
||||
- **Global scope** — patterns in `~/.soulforge/forbidden` apply everywhere
|
||||
- Built-in patterns cover `.env`, `.pem`, `credentials`, `private_key`, `id_rsa`, `.npmrc`, `.netrc`, `shadow`, `passwd`, and more
|
||||
|
||||
## Supported Versions
|
||||
|
||||
| Version | Supported |
|
||||
|---------|-----------|
|
||||
| 3.x | Yes |
|
||||
| < 3.0 | No |
|
||||
@@ -23,7 +23,7 @@ Configure which model each one uses in [the task router](/recipes/task-router).
|
||||
|
||||
## What the agents share
|
||||
|
||||
When Forge dispatches multiple sub-agents in parallel, they coordinate through the AgentBus:
|
||||
When Forge dispatches multiple sub-agents in parallel, they coordinate through a shared bus:
|
||||
|
||||
- **File cache** — first reader caches; others reuse.
|
||||
- **Tool cache** — read-only tool results shared across agents and dispatches.
|
||||
|
||||
@@ -15,7 +15,7 @@ You don't configure this. It picks the best available backend for every operatio
|
||||
| Operation | Examples |
|
||||
|-----------|----------|
|
||||
| **Go to definition** | "where is `parseConfig` defined?" |
|
||||
| **Find references** | "who calls `AgentBus`?" |
|
||||
| **Find references** | "who calls `parseConfig`?" |
|
||||
| **Rename** | "rename `useChat` to `useConversation` everywhere" |
|
||||
| **Type info** | "what's the return type of `fetchUser`?" |
|
||||
| **Diagnostics** | "any errors in this file?" |
|
||||
|
||||
@@ -13,9 +13,9 @@ The agent never wastes a turn grepping for "where does auth live" — it already
|
||||
The map appears in every system prompt, looking like this:
|
||||
|
||||
```
|
||||
src/core/agents/agent-bus.ts (→12)
|
||||
+AgentBus Shared coordination bus for parallel subagent communication
|
||||
+SharedCache
|
||||
src/services/auth/session.ts (→12)
|
||||
+SessionManager Tracks active sessions, refresh tokens, expiry
|
||||
+SessionStore
|
||||
```
|
||||
|
||||
- `+` — exported symbol
|
||||
|
||||
@@ -66,7 +66,7 @@ Privacy patterns (`/privacy add`) block sensitive files from the agent entirely.
|
||||
|
||||
## Can I use it for work?
|
||||
|
||||
Yes. Use it anywhere, anytime, for free — personal projects, startups, enterprise, client work, whatever. The [BSL 1.1 license](https://github.com/proxysoul/soulforge/blob/main/LICENSE) only kicks in if you want to *redistribute SoulForge as a commercial product* (repackage it, resell it, host it as a paid service). Converts to Apache 2.0 on March 15, 2030.
|
||||
Yes. Use it anywhere, anytime, for free — personal projects, startups, enterprise, client work, whatever. The [Business Source License 1.1](https://github.com/proxysoul/soulforge/blob/main/LICENSE) only kicks in if you want to *redistribute SoulForge as a commercial product* (repackage it, resell it, host it as a paid service). Converts to Apache 2.0 on March 15, 2030.
|
||||
|
||||
## What languages does code intelligence cover?
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ That's it. macOS and Linux. Neovim and a Nerd Font are auto-installed on first l
|
||||
<Tabs>
|
||||
<Tab title="Prebuilt binary">
|
||||
```bash
|
||||
# download from https://github.com/ProxySoul/soulforge/releases/latest
|
||||
# download from https://github.com/proxysoul/soulforge/releases/latest
|
||||
tar xzf soulforge-*.tar.gz && cd soulforge-*/ && ./install.sh
|
||||
```
|
||||
</Tab>
|
||||
@@ -32,7 +32,7 @@ That's it. macOS and Linux. Neovim and a Nerd Font are auto-installed on first l
|
||||
</Tab>
|
||||
<Tab title="Source">
|
||||
```bash
|
||||
git clone https://github.com/ProxySoul/soulforge.git
|
||||
git clone https://github.com/proxysoul/soulforge.git
|
||||
cd soulforge && bun install && bun run dev
|
||||
```
|
||||
</Tab>
|
||||
@@ -83,7 +83,7 @@ You need at least one LLM provider key. Pick one path:
|
||||
|
||||
Keys are stored in your OS keychain (macOS Keychain, Linux secret-tool). You can also `export ANTHROPIC_API_KEY=...` in your shell profile.
|
||||
|
||||
[See all 20+ providers →](/providers)
|
||||
[See all 20+ providers →](/providers/overview)
|
||||
|
||||
## Launch
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ Most AI coding tools treat your codebase as text. They grep, they paste, they ma
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="The first AST editor for AI" icon="scalpel" href="/tools/ast-edit">
|
||||
Symbol-addressed TypeScript and JavaScript edits via ts-morph. Born from my own 2022 Master's thesis on programmatic JS to TS conversion. Changing a return type costs a handful of tokens.
|
||||
Symbol-addressed TypeScript and JavaScript edits via ts-morph. Roots in a 2022 Master's thesis on programmatic JS to TS conversion. Changing a return type costs a handful of tokens.
|
||||
</Card>
|
||||
<Card title="Full LSP, your way" icon="brain" href="/tools/lsp">
|
||||
Workspace rename, definitions, references, call and type hierarchy, diagnostics, code actions, format. Mason installer for 576+ servers from the TUI.
|
||||
@@ -65,7 +65,7 @@ Neovim is optional. A Nerd Font is optional. SoulForge prompts to install either
|
||||
## Plain-English prompts, real tool calls
|
||||
|
||||
```
|
||||
> rename AgentBus to CoordinationBus
|
||||
> rename UserService to AccountService
|
||||
> move parseConfig from utils.ts to config/parser.ts
|
||||
> change fetchUser to return Promise<User>
|
||||
> run tests, fix lint, commit
|
||||
|
||||
@@ -23,7 +23,7 @@ icon: "rocket"
|
||||
<Step title="Make a change">
|
||||
Describe the change in plain English.
|
||||
```
|
||||
> rename AgentBus to CoordinationBus across the project
|
||||
> rename UserService to AccountService across the project
|
||||
```
|
||||
Watch the agent run `rename_symbol` — one tool call updates every file.
|
||||
</Step>
|
||||
|
||||
@@ -9,7 +9,7 @@ icon: "pen"
|
||||
Just ask:
|
||||
|
||||
```
|
||||
> rename AgentBus to CoordinationBus
|
||||
> rename UserService to AccountService
|
||||
```
|
||||
|
||||
The agent runs `rename_symbol` — one LSP-backed call updates every file and verifies there are no dangling references.
|
||||
@@ -27,7 +27,7 @@ Moves the symbol, updates every import across the project, fixes re-exports. Ful
|
||||
## Rename a file
|
||||
|
||||
```
|
||||
> rename src/old-name.ts to src/components/new-name.ts
|
||||
> rename src/old-name.ts to src/utils/new-name.ts
|
||||
```
|
||||
|
||||
Moves the file, updates every importer.
|
||||
|
||||
@@ -85,4 +85,4 @@ Each tab has its own independent checkpoint history. Git tags are namespaced by
|
||||
|
||||
## Steering
|
||||
|
||||
Steering messages (sent while the agent is working via `Ctrl+V` or the message queue) do not create new checkpoints. They fold into the current running checkpoint.
|
||||
Steering messages (typed into the input while the agent is working) do not create new checkpoints. They fold into the current running checkpoint.
|
||||
@@ -115,7 +115,7 @@ Both backends support: definitions, references, hover, diagnostics, rename, code
|
||||
|
||||
### Mason auto-install
|
||||
|
||||
On first editor launch, SoulForge detects project languages and installs appropriate LSP servers via Mason. Servers are stored in `~/.local/share/soulforge/mason/bin/` and discovered automatically.
|
||||
On first editor launch, SoulForge detects project languages and installs appropriate LSP servers via Mason. Servers are stored in `~/.soulforge/lsp-servers/` and discovered automatically.
|
||||
|
||||
## Vim hints
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "Themes"
|
||||
description: "24 builtin themes, custom themes with hot reload — pick your flavor or add yours."
|
||||
description: "36 builtin themes, custom themes with hot reload — pick your flavor or add yours."
|
||||
icon: "palette"
|
||||
---
|
||||
|
||||
@@ -34,6 +34,18 @@ Press `/theme` or `Ctrl+K` → search "theme" to open the theme picker. Themes p
|
||||
| `proxysoul-main` | proxySoul — deep purple with hot pink |
|
||||
| `proxysoul-coffee` | proxySoul Coffee — warm amber & burnt orange |
|
||||
| `proxysoul-water` | proxySoul Water — ocean blue & teal |
|
||||
| `cyberdream` | Cyberdream |
|
||||
| `oxocarbon` | Oxocarbon |
|
||||
| `sonokai` | Sonokai |
|
||||
| `moonfly` | Moonfly |
|
||||
| `melange` | Melange |
|
||||
| `solarized-osaka` | Solarized Osaka |
|
||||
| `bamboo` | Bamboo |
|
||||
| `nordic` | Nordic |
|
||||
| `synthwave` | Synthwave |
|
||||
| `iceberg` | Iceberg |
|
||||
| `ember` | Ember |
|
||||
| `vesper` | Vesper |
|
||||
|
||||
### Light
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ Open `/lsp status`. If your language server isn't attached:
|
||||
/lsp install
|
||||
```
|
||||
|
||||
Picks from the Mason registry and installs into `~/.local/share/soulforge/mason/`. Restart SoulForge after installing.
|
||||
Picks from the Mason registry and installs into `~/.soulforge/lsp-servers/`. Restart SoulForge after installing.
|
||||
|
||||
## Neovim not found
|
||||
|
||||
|
||||
+71
-2
@@ -109,6 +109,24 @@ const reactCompilerPlugin: BunPlugin = {
|
||||
},
|
||||
};
|
||||
|
||||
// ── Strip absolute filesystem paths from the bundle ────────────────────
|
||||
// Bun's bundler may inline absolute paths (cwd, $HOME) into the bundle as
|
||||
// __dirname / __filename strings or comment markers. Replace them so the
|
||||
// dev machine's filesystem doesn't ship with the binary.
|
||||
const stripAbsPathsPlugin: BunPlugin = {
|
||||
name: "strip-abs-paths",
|
||||
setup(build) {
|
||||
const cwd = process.cwd();
|
||||
const home = process.env.HOME ?? "";
|
||||
build.onLoad({ filter: /\.(ts|tsx|js|jsx)$/ }, async ({ path, loader }) => {
|
||||
let src = await Bun.file(path).text();
|
||||
if (cwd && src.includes(cwd)) src = src.split(cwd).join("");
|
||||
if (home && src.includes(home)) src = src.split(home).join("~");
|
||||
return { contents: src, loader };
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// ── Parse args ───────────────────────────────────────────────────────
|
||||
const isCompile = process.argv.includes("--compile");
|
||||
|
||||
@@ -220,12 +238,25 @@ if (isCompile) {
|
||||
const finalPath = outfile ? resolve(outfile) : defaultBinary;
|
||||
console.log(`✓ Compiled binary with React Compiler in ${elapsed}ms → ${finalPath}`);
|
||||
} else {
|
||||
// Production hardening: when NODE_ENV=production or --prod is passed, the
|
||||
// npm `dist/` build is minified, sourcemap-free, identifier-mangled.
|
||||
// This is what protects the published binary from `strings`-based source
|
||||
// recovery and casual reverse-engineering.
|
||||
const isProd = process.env.NODE_ENV === "production" || process.argv.includes("--prod");
|
||||
const minify = isProd ? { whitespace: true, identifiers: true, syntax: true } : false;
|
||||
|
||||
const result = await Bun.build({
|
||||
entrypoints: ["src/boot.tsx"],
|
||||
outdir: "dist",
|
||||
target: "bun",
|
||||
naming: "[dir]/index.[ext]",
|
||||
plugins: [reactCompilerPlugin, devtoolsStubPlugin],
|
||||
plugins: [
|
||||
stripAbsPathsPlugin,
|
||||
reactCompilerPlugin,
|
||||
devtoolsStubPlugin,
|
||||
],
|
||||
minify,
|
||||
sourcemap: "none",
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
@@ -244,6 +275,8 @@ if (isCompile) {
|
||||
target: "bun",
|
||||
naming: "[name].[ext]",
|
||||
plugins: [reactCompilerPlugin],
|
||||
minify,
|
||||
sourcemap: "none",
|
||||
});
|
||||
|
||||
if (!workerResult.success) {
|
||||
@@ -285,9 +318,45 @@ if (isCompile) {
|
||||
);
|
||||
chmodSync("dist/bin.sh", 0o755);
|
||||
|
||||
// Production guards: assert no inline sourcemaps and no source-form sentinel
|
||||
// class declarations leak into the bundle. Bun preserves export NAMES even
|
||||
// with identifier mangling — the *class body* is what we protect.
|
||||
if (isProd) {
|
||||
const bundle = await Bun.file("dist/index.js").text();
|
||||
const sentinels = [
|
||||
/\bclass\s+ContextManager\b/,
|
||||
/\bclass\s+AgentBus\b/,
|
||||
/\bclass\s+RepoMap\b/,
|
||||
/\bclass\s+WorkspaceCoordinator\b/,
|
||||
/\bfunction\s+createForgeAgent\b/,
|
||||
];
|
||||
const leaks = sentinels.filter((re) => re.test(bundle)).map((re) => re.source);
|
||||
if (leaks.length > 0) {
|
||||
console.error(`✗ unmangled class/function declarations leaked: ${leaks.join(", ")}`);
|
||||
process.exit(1);
|
||||
}
|
||||
if (bundle.includes("sourceMappingURL=data:")) {
|
||||
console.error("✗ inline sourcemap detected in bundle");
|
||||
process.exit(1);
|
||||
}
|
||||
// Post-build path scrub. The onLoad strip-paths plugin only sees our
|
||||
// source; pre-bundled CJS deps inline absolute __dirname/__filename paths
|
||||
// that survive into dist/index.js. Replace them.
|
||||
const cwd = process.cwd();
|
||||
const home = process.env.HOME ?? "";
|
||||
let raw = bundle;
|
||||
for (const needle of [cwd, home].filter(Boolean)) {
|
||||
if (raw.includes(needle)) raw = raw.split(needle).join("");
|
||||
}
|
||||
if (raw !== bundle) {
|
||||
await Bun.write("dist/index.js", raw);
|
||||
}
|
||||
console.log("✓ verified: sentinels absent, no inline sourcemap, paths stripped");
|
||||
}
|
||||
|
||||
const elapsed = (performance.now() - start).toFixed(0);
|
||||
const count = result.outputs.length + workerResult.outputs.length;
|
||||
console.log(
|
||||
`✓ Built ${count} artifact${count === 1 ? "" : "s"} with React Compiler in ${elapsed}ms`,
|
||||
`✓ Built ${count} artifact${count === 1 ? "" : "s"} with React Compiler in ${elapsed}ms (minified=${!!minify})`,
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user