Skip to content

Commit 309f7c2

Browse files
feat(workspace-hub): add side-load entry packets
1 parent 7591ded commit 309f7c2

21 files changed

Lines changed: 599 additions & 80 deletions

docs/07-context-cache-and-retrieval.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,17 @@ Typical contents:
220220
- its preferred runtime mode
221221
- its main preview or entry point
222222

223+
### `entry.md`
224+
225+
Repo-scoped routing packet.
226+
227+
Typical contents:
228+
229+
- the default open order for repo work
230+
- key commands and runtime mode
231+
- the small set of canonical docs to open next
232+
- the constraints that should keep the session repo-scoped unless broader context is truly required
233+
223234
### `overview.md`
224235

225236
`L1` summary.

docs/20-ai-context-side-load.md

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,13 @@ V1 generates only these paths:
4343
cache/context/
4444
├── workspace/
4545
│ ├── abstract.md
46+
│ ├── entry.md
4647
│ ├── overview.md
4748
│ └── sources.json
4849
└── repos/
4950
└── workspace-hub/
5051
├── abstract.md
52+
├── entry.md
5153
├── overview.md
5254
└── sources.json
5355
```
@@ -78,9 +80,9 @@ Use this when starting a fresh chat that needs repo-aware handover context.
7880

7981
Recommended sequence:
8082

81-
1. treat tracked docs as canonical and start with the relevant handover or README surface
83+
1. treat tracked docs as canonical and start with the relevant side-load entry packet
8284
2. refresh the side-load cache if the session is broad, new, or likely to re-read workspace context repeatedly
83-
3. let the chat use generated `abstract.md` and `overview.md` as the fast entry layer
85+
3. let the chat use generated `entry.md`, `abstract.md`, and `overview.md` as the fast entry layer
8486
4. fall back to tracked docs, manifests, and repo files for any real decision or ambiguity
8587
5. regenerate or ignore the cache if Workspace Hub reports the side-load state as `stale` or `missing`
8688

@@ -95,7 +97,7 @@ Then start the chat with a handover instruction such as:
9597

9698
> Read `docs/HANDOVER.md` first for the current workspace state. Use generated side-load files under `cache/context/` only as a compact entry layer, and treat tracked docs and repo files as canonical.
9799
98-
For repo-specific work, point the chat at the relevant repo README or handover note as well as the repo side-load cache when it exists.
100+
For repo-specific work, point the chat at the repo `entry.md` first, then the repo README or handover note only when the side-load packet is insufficient.
99101

100102
## Source set
101103

@@ -127,6 +129,18 @@ It should stay small enough for quick relevance decisions and answer:
127129
- the main runtime or entrypoint
128130
- the main constraint or warning
129131

132+
### `entry.md`
133+
134+
Use this as the default repo-scoped routing packet.
135+
136+
It should stay compact enough to answer:
137+
138+
- what to open first
139+
- repo type and runtime mode
140+
- the main commands
141+
- the primary canonical docs
142+
- the main constraints that should prevent broad workspace loading
143+
130144
### `overview.md`
131145

132146
Use this as the `L1` planning summary.
@@ -188,7 +202,7 @@ The details panel should show:
188202
- `fresh` when all declared inputs still exist, `mtimeMs` values still match, and required outputs exist
189203
- `stale` when an input changed or disappeared, or a required output file is missing
190204

191-
The Hub can open the generated `abstract.md`, `overview.md`, and `sources.json` files directly through the existing generic open-path route.
205+
The Hub can open the generated `entry.md`, `abstract.md`, `overview.md`, and `sources.json` files directly through the existing generic open-path route.
192206

193207
## Practical rule
194208

docs/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
- Added a tracked [docs/plans/readme-docs-closeout.md](plans/readme-docs-closeout.md) plan for future reference, and aligned small Workspace Hub/operator copy surfaces with the same mapped-host wording in `repos/workspace-hub`, `tools/scripts/doctor-workspace.sh`, and `tools/scripts/setup-workspace-profile.sh`.
99
- Extended `repos/workspace-hub` backlog follow-through with better repo-list prioritization for pinned and recent work, clearer Python-aware dependency readiness, intake-result surfacing in repo details, capability search and inspection, explicit mapped-host routing status, and richer runtime troubleshooting guidance.
1010
- Advanced Workspace memory graph support from file-open-only toward Phase 2 by surfacing derived-edge counts, node-type breakdown, and an in-app graph report preview for the selected target, while clarifying intentional MCP profile usage in the Workspace Hub settings panel.
11+
- Added generated `entry.md` side-load packets for workspace and repo context caches, updated manifest support for `entryDocs`, and aligned the side-load docs so Hub operators have one default routing document before they open deeper generated summaries.
12+
- Split Workspace Hub indexed search into `thin` and `deep` modes so the default path stays fast and side-load-aware while deeper searches can still opt into repo-local docs, logs, and artifact content when that extra cost is justified.
1113

1214
## 2026-04-10
1315

docs/HANDOVER.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,3 +866,33 @@ Verification after this slice:
866866
Pickup note:
867867

868868
- The managed browser wrappers are now robust even when the host process exposes an unusable home directory; any remaining Playwright-specific failure inside a separate tool host is no longer caused by the workspace wrapper.
869+
870+
### Implementation update (2026-04-11, side-load entry packet and thin/deep search)
871+
872+
Current local workspace changes after `7591ded` focus on the side-load entry path and indexed search behavior.
873+
874+
Completed in the current local slice:
875+
876+
1. Added `entry.md` as the default side-load routing packet.
877+
- `tools/scripts/generate-context-cache.sh` now emits `entry.md` for both workspace and repo targets alongside `abstract.md`, `overview.md`, and `sources.json`.
878+
- `docs/07-context-cache-and-retrieval.md` and `docs/20-ai-context-side-load.md` now treat `entry.md` as the first compact read for repo-scoped work.
879+
- Repo manifests now support optional `entryDocs` so a repo can declare the small set of canonical files operators should open before scanning broadly.
880+
881+
2. Added `thin` versus `deep` indexed search modes in `workspace-hub`.
882+
- `thin` is now the default indexed search path and stays focused on repo metadata plus side-load summaries.
883+
- `deep` is explicit and expands search into README content, logs, docs, failure reports, and artifacts where those sources exist.
884+
- Search document caching is now keyed by mode instead of assuming one global index shape.
885+
886+
3. Updated Hub UI copy and repo details to match the new side-load flow.
887+
- Repo Discovery now exposes the indexed-search mode selector.
888+
- Repo details can open the generated repo `entry.md` packet directly.
889+
- Discovery and manifest docs now explain `entryDocs` plus thin/deep search behavior.
890+
891+
Verification status for this local slice:
892+
893+
- tests were updated for `entry.md` generation, side-load hydration, and thin/deep search behavior
894+
- final runtime verification for this exact local slice should still be re-run before the next commit or push
895+
896+
Pickup note:
897+
898+
- if this slice lands, update `docs/CHANGELOG.md`, `docs/README.md`, and any relevant `workspace-hub` docs summary so the public side-load contract reflects `entry.md` and the new indexed-search modes

docs/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ Read these in order:
4949
- `17-mcp-install-and-health-check.md` defines the workspace-owned Codex MCP install, verify, and downgrade path.
5050
- `18-mcp-server-catalog.md` defines the small approved MCP server catalog for v1.
5151
- `19-mcp-authoring-rules.md` defines the quality bar for adding future tracked MCP examples.
52-
- `20-ai-context-side-load.md` defines the concrete v1 side-load generator, provenance contract, and Workspace Hub freshness semantics for generated `cache/context/` summaries.
52+
- `20-ai-context-side-load.md` defines the concrete v1 side-load generator, `entry.md` routing packet, provenance contract, and Workspace Hub freshness semantics for generated `cache/context/` summaries plus the thin-versus-deep search split.
5353
- `HANDOVER.md` summarizes the current state of the workspace, current implementation batches, and the latest acceptance evidence.
5454
- `CHANGELOG.md` records notable workspace-level changes.
5555

@@ -79,7 +79,7 @@ Useful maintenance scripts:
7979
- `tools/scripts/install-mcp-profile.sh` generates and optionally applies the managed Codex Workspace MCP block for a named profile.
8080
- `tools/scripts/check-mcp-health.sh` verifies the managed MCP block, expected active servers, tracked examples, and wrapper-based browser runtime assumptions.
8181
- `tools/scripts/init-agent-job-bundle.sh` previews or creates a local cache/context bundle for longer-running agent jobs under `cache/context/agents/jobs/`.
82-
- `tools/scripts/generate-context-cache.sh` previews or writes workspace and repo side-load summaries under `cache/context/workspace/` and `cache/context/repos/`.
82+
- `tools/scripts/generate-context-cache.sh` previews or writes workspace and repo side-load summaries under `cache/context/workspace/` and `cache/context/repos/`, including the generated `entry.md` packet that now acts as the default Hub handoff surface.
8383
- `tools/scripts/release-readiness.sh` runs the stable release gate: workspace doctors, `workspace-hub` test/lint/build, skill-sync dry run, and placeholder-surface checks.
8484
- `tools/scripts/run-with-workspace-env.sh` runs a command with the shared workspace environment, including the shared Playwright browser cache path.
8585
- `tools/scripts/setup-workspace-profile.sh` provides a guided, non-destructive profile check for `core`, `hub`, `mixed-stack`, `wordpress`, `agent-enhanced`, `workflow-state`, `spec-driven`, and `ui-previews`.

repos/workspace-hub/README.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ Workspace Hub is a local control plane for people who manage many standalone rep
4141
- applies tracked repo-local agent presets for Codex baseline, OMX-ready, OpenCode, or an all-in-one setup directly from the details panel
4242
- exports the shared workspace Playwright browser cache to repo install and runtime commands by default, so Playwright-based smoke runs can reuse one Chromium download
4343
- streams live runtime, install, cover, and activity updates from the local API
44-
- indexes repo metadata, manifests, recent logs, failure reports, and local agent-job artifacts for server-side search
45-
- reads generated repo side-load summaries on repo-detail hydration so operators can inspect context-cache freshness and open the generated summary files without paying for that metadata on every base summary refresh
44+
- indexes repo metadata, manifests, side-load summaries, recent logs, failure reports, and local agent-job artifacts for server-side search, with a fast default `thin` mode plus an opt-in `deep` mode for heavier repo content
45+
- reads generated repo side-load summaries on repo-detail hydration so operators can inspect context-cache freshness and open the generated `entry.md`, `abstract.md`, `overview.md`, and provenance files without paying for that metadata on every base summary refresh
4646
- exposes a dedicated Workspace memory surface for MemPalace service state, target selection, in-app retrieval search, target-scoped graph builds, and safe wrapper actions
4747
- builds target-scoped MemPalace graph artifacts from normalized sidecars and nearby markdown instead of introducing a second ingestion engine
4848
- stores lightweight per-repo metadata and recent activity locally
@@ -201,7 +201,8 @@ pnpm dev:api
201201
pnpm dev:web --host 127.0.0.1 --port 4174
202202
curl -s http://127.0.0.1:4101/api/workspace/summary/base | jq '{repoCount: (.repos | length), capabilityCount: (.capabilities | length), firstRepo: (.repos[0] | {relativePath, detailLevel})}'
203203
curl -s http://127.0.0.1:4101/api/capabilities | jq '{generatedAt, stats}'
204-
curl -s "http://127.0.0.1:4101/api/search?q=memory" | jq '{total: (.results | length), categories: (.results | map(.category))}'
204+
curl -s "http://127.0.0.1:4101/api/search?q=memory&mode=thin" | jq '{mode, total: (.results | length), categories: (.results | map(.category))}'
205+
curl -s "http://127.0.0.1:4101/api/search?q=memory&mode=deep" | jq '{mode, total: (.results | length), categories: (.results | map(.category))}'
205206
curl -s -X POST http://127.0.0.1:4101/api/services/context -H 'Content-Type: application/json' -d '{"serviceId":"mempalace","targetKind":"workspace-docs"}' | jq '{targetLabel, graph: .graph | {lastBuiltAt, nodeCount, edgeCount}}'
206207
curl -s -X POST http://127.0.0.1:4101/api/services/command -H 'Content-Type: application/json' -d '{"serviceId":"mempalace","commandId":"search","searchQuery":"workspace memory"}' | jq '{command, ok}'
207208
curl -s -X POST http://127.0.0.1:4101/api/services/command -H 'Content-Type: application/json' -d '{"serviceId":"mempalace","commandId":"build-graph"}' | jq '{command, ok}'
@@ -238,6 +239,8 @@ Default local endpoints:
238239
- observability: `http://127.0.0.1:4101/api/workspace/observability`
239240
- events: `http://127.0.0.1:4101/api/events`
240241
- search: `http://127.0.0.1:4101/api/search?q=preview`
242+
- search (thin): `http://127.0.0.1:4101/api/search?q=preview&mode=thin`
243+
- search (deep): `http://127.0.0.1:4101/api/search?q=preview&mode=deep`
241244
- capabilities: `http://127.0.0.1:4101/api/capabilities`
242245

243246
Summary endpoints:
@@ -249,6 +252,8 @@ Summary endpoints:
249252
The UI now prefers base summary for frequent refreshes and hydrates full diagnostics when needed.
250253
The capability panel now also reads a dedicated read-only capability snapshot so operators can inspect installed, enabled, and reference-only counts without inferring them from the broader workspace summary.
251254
Repo details now also read optional side-load metadata for the selected repo only, so the `Context cache` block can show `missing`, `fresh`, or `stale` generated summary state without slowing the discovery-first list path.
255+
The `Context cache` block now treats generated `entry.md` as the default operator handoff packet and can still open the deeper side-load files when needed.
256+
Indexed search now defaults to `thin` mode so repo discovery, manifest signals, and side-load summaries remain cheap to query, with `deep` mode available when you explicitly want heavier repo-local content included.
252257
Observability now includes cache hit or miss counters, diagnostics cache behavior, eager repo-details request timing, and summary request reasons to support tuning.
253258
`/api/workspace/observability` now exposes a versioned schema (`observabilityVersion: 2`) with grouped sections (`discovery`, `diagnostics`, `repoDetails`, `summary`); current top-level counters remain as compatibility aliases for existing consumers.
254259

@@ -407,3 +412,5 @@ Current layout note:
407412
Add deeper per-capability state such as post-install command health or last update output if operators need more than the current read-only snapshot and action feedback.
408413
- Batch 3: Repo intake polish.
409414
Tighten intake output so new repos get clearer runtime notes, explicit optional ability dependency guidance when relevant, and better first-run defaults.
415+
Each generated side-load bundle now includes an `entry.md` routing packet alongside the deeper summaries and provenance files.
416+
The repo-details panel opens that packet first, and indexed search uses the lighter side-load material by default unless you explicitly switch to `deep` mode.

repos/workspace-hub/docs/discovery.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Repo Discovery currently supports:
2121
- `External repos`
2222
- repo-type filters such as `vite`, `wordpress`, or `static`
2323

24-
Search matches repo metadata plus archive file names and paths.
24+
Search defaults to thin indexed metadata plus repo side-load summaries. Deep mode is explicit and expands into debug-only docs, logs, and local artifacts when those sources are available.
2525

2626
## Dashboard layout
2727

repos/workspace-hub/docs/manifest.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ Workspace Hub currently supports these optional fields:
5757
- `healthcheckUrl`
5858
- `servbayPath`
5959
- `servbaySubdomain`
60+
- `entryDocs`
6061
- `tags`
6162
- `notes`
6263

@@ -88,8 +89,9 @@ When Workspace Hub writes a manifest, it uses this order for known fields:
8889
12. `healthcheckUrl`
8990
13. `servbayPath`
9091
14. `servbaySubdomain`
91-
15. `tags`
92-
16. `notes`
92+
15. `entryDocs`
93+
16. `tags`
94+
17. `notes`
9395

9496
Unknown preserved keys are appended after the known keys.
9597

@@ -108,6 +110,10 @@ Unknown preserved keys are appended after the known keys.
108110
"previewCommand": "pnpm preview",
109111
"previewUrl": "http://127.0.0.1:4100",
110112
"healthcheckUrl": "http://127.0.0.1:4101/api/health",
113+
"entryDocs": [
114+
"repos/workspace-hub/README.md",
115+
"repos/workspace-hub/docs/INSTRUCTIONS.md"
116+
],
111117
"tags": ["hub", "workspace", "tooling"],
112118
"notes": "Local-first dashboard for managing mixed-stack repo workspaces."
113119
}
@@ -127,6 +133,7 @@ Unknown preserved keys are appended after the known keys.
127133
- Prefer `direct` for Vite, Three.js, and similar frontend repos unless a repo explicitly needs something else.
128134
- Prefer `external` for WordPress repos already managed by Local or another app.
129135
- Use `servbayPath` or `servbaySubdomain` only when mapped-host routing is stable and tested (field names are stable JSON keys).
136+
- Use `entryDocs` for the small set of canonical files the operator should open before scanning the repo broadly.
130137
- Keep manifests explicit and readable; do not turn them into a dump of every inferred value unless the repo benefits from that clarity.
131138
- Keep local-only values in `project.local.json` when they should not ship with the repo.
132139
- If the repo needs a workspace ability for operator workflows, mention the install command in repo docs instead of trying to encode that dependency implicitly in the manifest.

repos/workspace-hub/server/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,10 @@ app.get(
434434
try {
435435
const query =
436436
typeof request.query.q === 'string' ? request.query.q.trim() : ''
437+
const mode =
438+
request.query.mode === 'deep' || request.query.mode === 'thin'
439+
? request.query.mode
440+
: 'thin'
437441

438442
if (!query) {
439443
response.status(400).json({ message: 'A search query is required.' })
@@ -445,6 +449,9 @@ app.get(
445449
apiPort,
446450
getInstallSnapshots(),
447451
getRuntimeSnapshots(),
452+
mode === 'deep'
453+
? undefined
454+
: { includeDiagnostics: false, repoProjection: 'list' },
448455
)
449456

450457
response.json(
@@ -453,6 +460,7 @@ app.get(
453460
summary.repos,
454461
summary.coreServices,
455462
summary.capabilities,
463+
mode,
456464
),
457465
)
458466
} catch (error) {

repos/workspace-hub/server/repo-manifest.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type {
1010
export type RepoManifestInput = {
1111
buildCommand?: unknown
1212
devCommand?: unknown
13+
entryDocs?: unknown
1314
externalUrl?: unknown
1415
healthcheckUrl?: unknown
1516
installCommand?: unknown
@@ -51,6 +52,7 @@ const orderedManifestKeys = [
5152
'healthcheckUrl',
5253
'servbayPath',
5354
'servbaySubdomain',
55+
'entryDocs',
5456
'tags',
5557
'notes',
5658
] as const
@@ -78,6 +80,17 @@ function normalizeTags(value: unknown) {
7880
.filter(Boolean)
7981
}
8082

83+
function normalizeEntryDocs(value: unknown) {
84+
if (!Array.isArray(value)) {
85+
return []
86+
}
87+
88+
return value
89+
.filter((entry): entry is string => typeof entry === 'string')
90+
.map((entry) => entry.trim())
91+
.filter(Boolean)
92+
}
93+
8194
async function readExistingManifest(manifestPath: string) {
8295
try {
8396
return JSON.parse(await readFile(manifestPath, 'utf8')) as Record<string, unknown>
@@ -129,11 +142,13 @@ export function normalizeManifestInput(input: RepoManifestInput) {
129142
}
130143

131144
const normalizedTags = normalizeTags(input.tags)
145+
const normalizedEntryDocs = normalizeEntryDocs(input.entryDocs)
132146
const notes = normalizeOptionalString(input.notes)
133147

134148
return {
135149
buildCommand: normalizeOptionalString(input.buildCommand),
136150
devCommand: normalizeOptionalString(input.devCommand),
151+
entryDocs: normalizedEntryDocs.length ? normalizedEntryDocs : undefined,
137152
externalUrl: normalizeOptionalString(input.externalUrl),
138153
healthcheckUrl: normalizeOptionalString(input.healthcheckUrl),
139154
installCommand: normalizeOptionalString(input.installCommand),

0 commit comments

Comments
 (0)