Portolan

A frontier agent, the Cartographer, surveys a brownfield codebase into a living nautical Chart, and you read it as an atlas. Every fact carries an anchor and a trust label, or it does not ship.

chart · sound · trust · sail

The trust ladder

Portolan never pretends a guess is knowledge. Every entry carries exactly one label:

LabelMeansIn the atlas
measuredtaken from the source, line-anchored; soundings confirmeddeepest water, solid lanes
charteddeclared by manifests, BOMs, packagingmid band
reporteda claim from docs or reportspale band
doubtfulevidence present, could not be validatedfaint dashed lane
unsurveyednot determined; left blank on purposeblank water, no ink

Staleness is rendered too: sources changed since the last survey ⇒ the island wears a pending correction hatch until an expedition heals it. Hovering an island raises its atlas plate: counters, behavior truth, newest notice, derived role, everything from embedded bytes only.

What ships

MCP survey tools

Fifteen stdio tools your agent calls: sweeps, symbols, manifests, soundings (sound.edge/sound.anchor), the Chart store, the Harbor queue, the trust.report verification summary, and chart.export — the whole Chart as one self-describing JSON document. Deterministic where it must be.

Verification as the spine

One call — trust.report — re-sounds every anchor on the Chart deterministically, then lays out trust labels, staleness, and receipts, naming any refuted anchor. Portolan charts itself: its own receipt holds 49 entries, 48 measured, 116/116 anchors confirmed, Pointer current.

Versioned formats

The Chart's data model ships as five named, versioned formats — chart entries, the trust vocabulary, receipts, and the adjacency graph export as JSON Schemas, plus the Pointer block as a versioned text format (all at 0.1.0, semver from there). A consumer validates an export with the schemas alone: docs/formats.md is the contract, no source reading required.

The Pointer — the front door

Every surveyed province's AGENTS.md carries a small versioned block that routes each incoming agent session to the harbor: one bootstrap command, the survey mandate. Rendered from one template, kept current by every expedition's close-out, and verified — current / stale / missing — by trust.report at the moment of use. File as pointer, MCP as truth.

Harbor & night watch

A deterministic proposal queue — repairs, gaps, new land, and flares (out-of-charter needs filed by expeditions) — plus a bounded night watch that launches repairs through any external launcher. Every expedition records its charter (promised scope) in the ship's log; overreach is computed from receipts and shown, never silent. No daemon, ever.

Byproduct exports

The Chart Room and Fleet Review are generated on demand, byte-deterministic, zero dependencies. Exports, never the storage.

Skill = method

The Cartographer's whole expedition method is a loadable skill: five passes, assert→sound→write, honest unsurveyed waters, Sailing Directions to close.

Local-first, read-only

Writes stay under the target's .portolan/; the target's source is never touched. Network access and installation sit behind one explicit per-session approval.

Sea-tried

An acceptance gate runs the whole loop against the real Apache Bigtop corpus and refuses stand-ins; the Governor's own reading is the final word.

Demo province: apache-bigtop

An 18-repo Apache stack assembled by gradle+BOM, surveyed by one headless expedition fleet and now wearing its hover plates and honesty ledgers.

Open this province's Chart Room ▸ …and the two-province fleet page ▸

Province factsBigtop master repo + 19 BOM components (2 retired) · 93 chart entries · hubs: bigtop-utils ×14, hadoop ×11 · 4 dangers: version skew, undeclared solr↔zookeeper, retired vessels, copy-paste recipes
Expedition fleet30+ headless expeditions (opencode + glm-5.3) took the province to 22/22 vessels with observed behavior and 22 charted API lights; 39 of 93 chart entries are measured from source. Every write receipted in the ship's log.
Honest zerosWhat no expedition observed is still labeled unsurveyed — the lamps say so, in red, on every island.
Self-healing proofNight watch launched real repair expeditions (history: by: night-watch); a live clobber incident (2-entry partial write) exposed a store gap — fixed as a shrink guard; the chart was restored from byproduct snapshots.

Quickstart

# survey a target with your agent (one phrase, it installs Portolan itself):
survey <target> with Portolan

# no agent at hand? one command installs skill + MCP + the Pointer:
bunx --package @fcon-tech/portolan portolan install --target .

# render one province's atlas — map + graph, find & filters, hover plates:
bun core/src/chartroom/cli.ts render --target /path/to/province

# assemble several provinces into one fleet page:
bun core/src/chartroom/cli.ts review --target /prov/a --target /prov/b

# the harbor, headless:
bun core/src/harbor/cli.ts propose --target <t> --format chat   # the queue
bun core/src/harbor/cli.ts run    --target <t> --fingerprint <fp> \
    --launcher adapters/opencode/expedition-launcher            # launch one by hand
bun core/src/harbor/cli.ts watch  --target <t> [same flags]     # the bounded night policy

# the whole Chart as one machine-readable document (no MCP needed):
bun core/src/bin/portolan.ts export --target /path/to/province   # validates against docs/formats.md schemas

# serve the fifteen MCP tools to your harness:
bun core/src/server/main.ts --target /path/to/province

Requirements: Bun, ripgrep, universal-ctags. Full contract: docs/MANIFEST.md · format schemas: docs/formats.md · specs live in openspec/specs/ (validated), history in openspec/changes/archive/.