docs: add MAGICFORM_CUSTOMIZATIONS.md sync index
Indexes the fork's customizations by subsystem and points each at the files it owns and the most recent forward-port commit. Future syncs replay each entry against new upstream layout instead of spelunking the diff. Per-subsystem isolation also means upstream changes typically only conflict on one or two entries at a time, not the entire customization surface. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9a0b281734
commit
763e5690c6
1 changed files with 138 additions and 0 deletions
138
MAGICFORM_CUSTOMIZATIONS.md
Normal file
138
MAGICFORM_CUSTOMIZATIONS.md
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
# MagicForm Customizations
|
||||||
|
|
||||||
|
This file is the index of customizations the `magicform` fork carries on top
|
||||||
|
of `sipeed/picoclaw` upstream. Read this first when:
|
||||||
|
- Doing an upstream sync (start by replaying each customization against the
|
||||||
|
new layout if upstream has changed the surrounding code)
|
||||||
|
- Reviewing a PR that touches any of the listed files
|
||||||
|
- Onboarding a new engineer to the fork
|
||||||
|
|
||||||
|
The single source of truth for *what changed* is the git log
|
||||||
|
(`git log upstream/main..main`). This file tells you *why* and *where*.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Goals of the fork
|
||||||
|
|
||||||
|
1. **Multi-tenant isolation.** A single `picoclaw` process serves many
|
||||||
|
tenants. Each tenant has its own filesystem workspace, config, sessions,
|
||||||
|
provider credentials, and tool/skill allowlist. Inbound messages carry
|
||||||
|
tenant hints in `bus.InboundContext.Raw`; the agent loop validates them
|
||||||
|
against a security boundary and applies them per-turn.
|
||||||
|
2. **Defense-in-depth on workspace boundary.** Every path-manipulating tool
|
||||||
|
(`fs`, `exec`, skill installer) honours `agents.defaults.workspace_root`
|
||||||
|
as a containment root. Tenants cannot read or write outside it.
|
||||||
|
3. **MagicForm webhook channel.** A webhook-driven channel
|
||||||
|
(`pkg/channels/magicform`) accepts inbound messages from MagicForm and
|
||||||
|
posts agent responses back via callback URL. Lives alongside upstream's
|
||||||
|
stock channels.
|
||||||
|
4. **Bounded resource use.** Search APIs and write tools have explicit byte
|
||||||
|
limits to keep a hostile or buggy upstream from exhausting memory/disk.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Subsystem map (read top-down when syncing)
|
||||||
|
|
||||||
|
Each entry: subsystem → files touched → most recent commit on `main`.
|
||||||
|
When upstream restructures a subsystem, only the matching entry needs to be
|
||||||
|
forward-ported.
|
||||||
|
|
||||||
|
### 1. MagicForm webhook channel
|
||||||
|
- **Owns:** `pkg/channels/magicform/{magicform.go,init.go}`
|
||||||
|
- **Registers in:** `pkg/gateway/gateway.go` (blank import)
|
||||||
|
- **Config plumbing:** `MagicFormSettings` in `pkg/config/config.go`,
|
||||||
|
`ChannelMagicForm` constant + `channelSettingsFactory` entry in
|
||||||
|
`pkg/config/config_channel.go`, validation case in
|
||||||
|
`pkg/channels/manager.go::getChannelConfigAndEnabled`.
|
||||||
|
- **Protocol:** HTTP POST to `/hooks/magicform` with bearer token; outbound
|
||||||
|
is HTTP POST callback to a per-request URL with JSON payload.
|
||||||
|
- **Tenancy hints:** the webhook handler stuffs `workspace_override`,
|
||||||
|
`config_dir`, `allowed_tools`, `allowed_skills` (and `callback_url`,
|
||||||
|
`stack_id`, `conversation_id`) into `bus.InboundContext.Raw`; the agent
|
||||||
|
loop reads them in `agent_tenant.go`.
|
||||||
|
|
||||||
|
### 2. Multi-tenancy in the agent loop
|
||||||
|
- **Owns:** `pkg/agent/agent_tenant.go` (entirely fork-owned, isolated for
|
||||||
|
sync friendliness) and a small wire-up block in
|
||||||
|
`pkg/agent/agent_message.go::processMessage`.
|
||||||
|
- **Surface on processOptions:** `WorkspaceOverride`, `ConfigDir`,
|
||||||
|
`AllowedTools`, `AllowedSkills` (defined in `pkg/agent/agent.go`).
|
||||||
|
- **Status: Phase 1.** Hints are validated and plumbed onto
|
||||||
|
`processOptions`. Phase 2 (effSessions, effContextBuilder, effProvider,
|
||||||
|
effModel threaded through `pipeline_llm.go`, `turn_state.go`,
|
||||||
|
`context_manager.go`) is a separate PR.
|
||||||
|
- **Security boundary:** validation uses
|
||||||
|
`pathutil.ResolveWorkspacePath(agents.defaults.workspace_root, hint)`;
|
||||||
|
fails closed when `workspace_root` is unset.
|
||||||
|
|
||||||
|
### 3. Workspace path security utility
|
||||||
|
- **Owns:** `pkg/pathutil/{resolve.go,resolve_test.go}` (fork-owned).
|
||||||
|
- Used by: `agent_tenant.go`, `pkg/config/config.go::mergeAgentDefaults`,
|
||||||
|
`cmd/picoclaw/internal/agent/helpers.go::validateWorkspacePaths`,
|
||||||
|
channels that accept tenant paths.
|
||||||
|
|
||||||
|
### 4. CLI overrides and workspace config overlay
|
||||||
|
- **Owns:** `cmd/picoclaw/internal/agent/{helpers.go,helpers_test.go}` —
|
||||||
|
validates `--workspace` / `--config-dir` flags, loads
|
||||||
|
`<config-dir>/config.json` and merges over the base config via
|
||||||
|
`Config.MergeWorkspaceConfig`.
|
||||||
|
- **Owns:** `pkg/config/config.go::MergeWorkspaceConfig` and
|
||||||
|
`mergeAgentDefaults` (fork additions; not in upstream).
|
||||||
|
|
||||||
|
### 5. Tool hardening (filesystem)
|
||||||
|
- **Owns:** customizations in `pkg/tools/fs/filesystem.go::sandboxFs.WriteFile`:
|
||||||
|
- `MaxWriteFileSize` cap (20 MB) before opening any file.
|
||||||
|
- `crypto/rand` temp suffixes instead of `time.Now().UnixNano()`.
|
||||||
|
- Last forward-ported: commit `cd1720f4` (after upstream `4c133dc2`
|
||||||
|
reorganized `pkg/tools/`).
|
||||||
|
|
||||||
|
### 6. Tool hardening (web search)
|
||||||
|
- **Owns:** customizations in `pkg/tools/integration/web.go`:
|
||||||
|
- `searchMaxResponseSize` constant (2 MB) used by every search provider's
|
||||||
|
`io.ReadAll(io.LimitReader(...))`.
|
||||||
|
- Last forward-ported: commit `94d28c1b`.
|
||||||
|
|
||||||
|
### 7. Output-channel plumbing for tenancy callbacks
|
||||||
|
- **Owns:** `pkg/bus/types.go` additions on `OutboundMessage`: `Type`,
|
||||||
|
`Metrics`, `Progress`, `Escalation`. Plus types `ResponseMetrics`,
|
||||||
|
`OutboundProgress`, `OutboundEscalation`, `TokenUsage`.
|
||||||
|
- The MagicForm channel `Send` reads these to compose its callback payload.
|
||||||
|
Other channels ignore them.
|
||||||
|
|
||||||
|
### 8. Exec tool: filterEnv
|
||||||
|
- **Owns:** `filterEnv` field in `ExecTool` and `ExecConfig`. Strips
|
||||||
|
non-`PICOCLAW_*`-prefixed env vars before child processes.
|
||||||
|
- Files: `pkg/tools/shell.go`, `pkg/config/config.go::ExecConfig`.
|
||||||
|
|
||||||
|
### 9. Channel base hook
|
||||||
|
- **Owns:** `BaseChannel.Bus()` accessor in `pkg/channels/base.go`. Used
|
||||||
|
by the magicform channel to publish directly with a non-default SessionKey.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Sync playbook
|
||||||
|
|
||||||
|
When pulling a new upstream:
|
||||||
|
|
||||||
|
1. `git fetch upstream && git fetch origin`
|
||||||
|
2. Branch: `git checkout -b sync/upstream-YYYY-MM-DD origin/main`
|
||||||
|
3. `git merge upstream/main` and resolve conflicts.
|
||||||
|
4. For each subsystem above, replay any commits whose files now no longer
|
||||||
|
exist (modify/delete conflicts) onto upstream's new locations.
|
||||||
|
5. `go build ./... && go test ./...`
|
||||||
|
6. Open a PR against `main`. Each forward-port should be its own commit
|
||||||
|
prefixed `forward-port:` so the merge commit and customization commits
|
||||||
|
are visually distinct in `git log`.
|
||||||
|
7. Update this index if the file map shifts.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What is *not* customized any more
|
||||||
|
|
||||||
|
- **Launcher (`cmd/picoclaw-launcher/`)**: dropped during the
|
||||||
|
2026-05-07 sync. Half its dependencies were deleted upstream and
|
||||||
|
MagicForm doesn't use the launcher's HTTP API. Upstream's
|
||||||
|
`web/backend/` is the replacement if a web admin is ever needed.
|
||||||
|
- **Deprecated `AgentDefaults.Model`**: dropped during the 2026-05-07
|
||||||
|
sync. Use `model_name`. Workspace overlays that still set the old
|
||||||
|
`"model"` JSON key will be silently ignored — migrate them.
|
||||||
Loading…
Add table
Reference in a new issue