@event4u/agent-config 3.1.1 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/.agent-src/commands/agent-status.md +1 -1
  2. package/.agent-src/commands/analytics/prune.md +78 -0
  3. package/.agent-src/commands/analytics/show.md +107 -0
  4. package/.agent-src/commands/analytics.md +64 -0
  5. package/.agent-src/commands/knowledge/forget.md +104 -0
  6. package/.agent-src/commands/knowledge/ingest.md +122 -0
  7. package/.agent-src/commands/knowledge/list.md +102 -0
  8. package/.agent-src/commands/knowledge.md +75 -0
  9. package/.agent-src/scripts/update_roadmap_progress.py +1 -1
  10. package/.agent-src/skills/compress-memory/SKILL.md +1 -1
  11. package/.agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  12. package/.claude-plugin/marketplace.json +8 -1
  13. package/AGENTS.md +5 -4
  14. package/CHANGELOG.md +54 -222
  15. package/README.md +12 -2
  16. package/dist/discovery/deprecation-report.md +1 -1
  17. package/dist/discovery/discovery-manifest.json +164 -10
  18. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  19. package/dist/discovery/discovery-manifest.summary.md +3 -3
  20. package/dist/discovery/orphan-report.md +1 -1
  21. package/dist/discovery/packs.json +12 -5
  22. package/dist/discovery/trust-report.md +2 -2
  23. package/dist/discovery/workspaces.json +11 -4
  24. package/dist/mcp/mcp-cloudflare-catalogue.json +2 -0
  25. package/dist/mcp/registry-manifest.json +5 -3
  26. package/docs/architecture.md +1 -1
  27. package/docs/archive/CHANGELOG-pre-3.2.0.md +268 -0
  28. package/docs/benchmarks.md +4 -4
  29. package/docs/catalog.md +9 -2
  30. package/docs/contracts/CHANGELOG-conventions.md +20 -1
  31. package/docs/contracts/adr-mcp-runtime.md +1 -1
  32. package/docs/contracts/at-rest-encryption.md +146 -0
  33. package/docs/contracts/benchmark-corpus-spec.md +3 -3
  34. package/docs/contracts/benchmark-report-schema.md +5 -5
  35. package/docs/contracts/caveman-telemetry.md +4 -4
  36. package/docs/contracts/compression-default-kill-criterion.md +5 -5
  37. package/docs/contracts/cost-enforcement.md +1 -1
  38. package/docs/contracts/daily-workspace.md +137 -0
  39. package/docs/contracts/explain-modes.md +146 -0
  40. package/docs/contracts/host-agent-protocol.md +88 -0
  41. package/docs/contracts/local-analytics.md +148 -0
  42. package/docs/contracts/local-knowledge-ingestion.md +96 -0
  43. package/docs/contracts/mcp-beta-criteria.md +1 -1
  44. package/docs/contracts/mcp-cloud-scope.md +4 -4
  45. package/docs/contracts/mcp-registry-manifest.schema.json +1 -1
  46. package/docs/contracts/mcp-tool-inventory.md +1 -1
  47. package/docs/contracts/mcp-tool-stub-envelope.md +1 -1
  48. package/docs/contracts/measurement-baseline.md +6 -6
  49. package/docs/contracts/role-experience.md +121 -0
  50. package/docs/contracts/workspace-documents.md +140 -0
  51. package/docs/decisions/ADR-022-daily-workspace-decomposition.md +140 -0
  52. package/docs/decisions/ADR-023-host-agent-protocol.md +129 -0
  53. package/docs/decisions/ADR-024-workspace-v0-feature-floor.md +126 -0
  54. package/docs/decisions/ADR-025-workspace-chrome.md +119 -0
  55. package/docs/decisions/ADR-026-explain-mode-translation.md +117 -0
  56. package/docs/decisions/ADR-027-changelog-machine-vs-manual.md +129 -0
  57. package/docs/decisions/ADR-028-root-layout.md +147 -0
  58. package/docs/decisions/ADR-029-multi-workspace-deferred.md +122 -0
  59. package/docs/decisions/INDEX.md +8 -0
  60. package/docs/deploy/small-team-recipe.md +148 -0
  61. package/docs/deploy/team-deployment-posture.md +91 -0
  62. package/docs/getting-started-by-role.md +27 -0
  63. package/docs/getting-started.md +1 -1
  64. package/docs/guides/local-analytics.md +125 -0
  65. package/docs/guides/local-knowledge.md +127 -0
  66. package/docs/mcp-server.md +1 -1
  67. package/docs/parity/bench-ruflo.json +3 -3
  68. package/docs/parity/ruflo.md +1 -1
  69. package/docs/setup/mcp-client-config.md +1 -1
  70. package/docs/setup/mcp-cloud-endpoints.md +1 -1
  71. package/docs/setup/mcp-cloud-setup.md +2 -2
  72. package/docs/setup/mcp-r2-bootstrap.md +1 -1
  73. package/package.json +4 -2
  74. package/scripts/__pycache__/validate_frontmatter.cpython-312.pyc +0 -0
  75. package/scripts/_lib/__pycache__/__init__.cpython-312.pyc +0 -0
  76. package/scripts/_lib/__pycache__/agent_src.cpython-312.pyc +0 -0
  77. package/scripts/_lib/bench_caveman.py +2 -2
  78. package/scripts/_lib/bench_caveman_report.py +1 -1
  79. package/scripts/_lib/bench_cost.py +2 -2
  80. package/scripts/_lib/bench_report.py +2 -2
  81. package/scripts/_lib/changelog_eras.py +330 -0
  82. package/scripts/audit_mcp_tools.py +1 -1
  83. package/scripts/bench_baseline_ready.py +3 -3
  84. package/scripts/bench_compress_memory.py +4 -4
  85. package/scripts/bench_drift_check.py +2 -2
  86. package/scripts/bench_per_tool.py +2 -2
  87. package/scripts/bench_run.py +4 -4
  88. package/scripts/build_mcp_registry_manifest.py +2 -2
  89. package/scripts/mcp_server/__init__.py +1 -1
  90. package/scripts/mcp_server/catalog.py +1 -1
  91. package/scripts/mcp_server/consumer_tool_catalog.json +1 -1
  92. package/scripts/mcp_server/tools.py +1 -1
  93. package/scripts/memory_lookup.py +78 -1
  94. package/scripts/pack_mcp_content.py +6 -6
  95. package/scripts/release.py +93 -3
  96. package/scripts/skill_trigger_eval.py +2 -2
@@ -0,0 +1,96 @@
1
+ ---
2
+ stability: beta
3
+ keep-beta-until: 2026-08-24
4
+ ---
5
+
6
+ # Local knowledge ingestion contract
7
+
8
+ **Purpose.** Freeze the input shape, bounds, storage target, and redaction defaults for the single-user, local-only knowledge surface (`/knowledge:ingest`, `/knowledge:list`, `/knowledge:forget`) **before** any implementation lands. Closes the "Copy/Paste AI" complaint from feedback A without touching OAuth, multi-tenancy, or Hard-Floor connector territory.
9
+
10
+ Last refreshed: 2026-05-24. Phase 2 of the employee-product workstream.
11
+
12
+ ## What this doc is **not**
13
+
14
+ - Not the connector contract for GitHub / Jira / Confluence — those sit behind OAuth and stay cancelled in `road-to-internal-ai-os-deployment.md` Phase 5.
15
+ - Not a remote-fetch surface — every input must resolve to a local path on the same machine the agent runs on.
16
+ - Not a memory replacement — ingested content lives **inside** the existing memory layer under a dedicated namespace, never as a parallel store.
17
+
18
+ ## Input shapes
19
+
20
+ The ingestion command accepts exactly these input shapes; anything else is rejected at the input validator with a structured error and no partial write.
21
+
22
+ | Input | Resolution rule | Example |
23
+ |---|---|---|
24
+ | `file://<absolute-path>` | Single file. Path must be absolute and inside the user's home or the project root (no `/etc`, `/var`, `~root/`, `..` escapes). | `file:///Users/maintainer/clients/acme/brief.pdf` |
25
+ | Local folder path | Recursive walk; symlinks not followed; hidden directories skipped (`.git`, `.venv`, `node_modules`). | `/Users/maintainer/clients/acme/` |
26
+ | `.zip` archive | Unpacked to a temp dir inside `$TMPDIR/agent-knowledge-<uuid>`, walked, then the temp dir is removed before the command returns. | `/Users/maintainer/clients/acme.zip` |
27
+
28
+ **Remote URLs are rejected** — `http://`, `https://`, `s3://`, `gs://`, `azure://`. The error message names `/knowledge:ingest` as local-only by design.
29
+
30
+ ## Supported MIME types
31
+
32
+ The ingestion module routes each file through the existing `markitdown` adapter when the MIME type is not native markdown.
33
+
34
+ | MIME | Adapter | Notes |
35
+ |---|---|---|
36
+ | `text/markdown` | passthrough | UTF-8 only; other encodings rejected |
37
+ | `text/plain` | passthrough | UTF-8 only |
38
+ | `application/pdf` | `markitdown` | OCR if scanned; OCR confidence < 0.7 surfaces as `low_confidence` tag |
39
+ | `application/vnd.openxmlformats-officedocument.wordprocessingml.document` (`.docx`) | `markitdown` | |
40
+ | `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` (`.xlsx`) | `markitdown` | One sheet per chunk |
41
+ | `application/epub+zip` (`.epub`) | `markitdown` | Chapter per chunk |
42
+ | `image/png`, `image/jpeg` | `markitdown` OCR | OCR confidence stored same as PDF |
43
+
44
+ Unsupported MIME → file skipped with a counted `skipped: <mime>` entry in the command summary. No partial-content writes.
45
+
46
+ ## Bounds (non-negotiable, enforced at command entry)
47
+
48
+ | Bound | Limit | Rationale |
49
+ |---|---|---|
50
+ | Total ingest size | ≤ 100 MB per `/knowledge:ingest` call | Keeps a single ingestion bounded; multi-ingest is fine |
51
+ | Document count | ≤ 1000 per call | Avoids unbounded walks on a misconfigured folder |
52
+ | Per-file size | ≤ 20 MB | One outlier file cannot blow the budget |
53
+ | Total memory footprint | ≤ 500 MB across all ingests | LRU eviction at the namespace level when crossed |
54
+ | Path traversal depth | ≤ 10 directories | Cheap guard against pathological folder trees |
55
+
56
+ Crossing any bound is a **hard reject** at command entry — not a warning. The command returns a structured error with the bound name and the observed value.
57
+
58
+ ## Storage target
59
+
60
+ Ingested content lives inside the existing memory namespace as a dedicated prefix:
61
+
62
+ ```
63
+ memory/
64
+ └── knowledge/
65
+ ├── <ingest-id>/ # uuid7 per ingest call
66
+ │ ├── manifest.json # source path, count, timestamps, redactions
67
+ │ └── chunks/<n>.md # one markdown chunk per logical unit
68
+ ```
69
+
70
+ - `<ingest-id>` is a uuid7 so timestamps are recoverable from the id; never user-controlled.
71
+ - `manifest.json` is the audit row — used by `/knowledge:list` and by the LRU eviction loop.
72
+ - Chunks are markdown only after the adapter has run; the original binary is never stored.
73
+
74
+ The MCP tool `memory_retrieve` (existing surface in `agent-memory`) **must** tag retrieved entries from this namespace with `source: knowledge`. The host model decides what to do with user-supplied vs maintainer-curated entries; this contract only requires the tag.
75
+
76
+ ## Redaction defaults
77
+
78
+ Redaction runs **before** the chunk write, never after.
79
+
80
+ - **PII allowlist** — only the following identifier classes survive the ingest: project names, document titles, headings, technical terminology. Everything else that pattern-matches a PII regex set (e-mail addresses, phone numbers, IBAN, credit-card-shaped strings, SSN-shaped strings) is replaced with class placeholders (`[EMAIL]`, `[PHONE]`, `[IBAN]`, `[CC]`, `[SSN]`).
81
+ - **Secrets never stored** — anything matching the existing `gitleaks` ruleset (or equivalent) is replaced with `[SECRET]` and the manifest's `secrets_redacted` counter is incremented. A chunk with ≥ 1 secret redaction is tagged `contains_redactions: true`.
82
+ - **The user can opt out per-call** with `--no-redact`, but the manifest captures the flag so the audit trail names exactly which ingests bypassed redaction. The default is always redact.
83
+
84
+ ## Eviction policy
85
+
86
+ LRU at the namespace level. When the 500 MB cap is crossed, oldest ingests (by `manifest.last_touched`) are dropped whole — never per-chunk. `last_touched` updates on every `memory_retrieve` hit against an entry in the namespace. The user can pin an ingest with `/knowledge:list --pin <ingest-id>`; pinned ingests are never evicted.
87
+
88
+ ## Command surface (deferred to impl PR)
89
+
90
+ `/knowledge:ingest <path>`, `/knowledge:list`, `/knowledge:forget <prefix>` are defined elsewhere — this contract pins their **inputs, bounds, storage, and redaction**. The Python module that implements the file walk + MIME routing + chunk writing lives at `packages/core/installer/python/knowledge_ingest.py`, ≤ 600 LOC (bumped from the pre-impl ≤ 400 budget once five PII classes, five secret patterns, LRU eviction, manifest persistence, pin/unpin and the multi-verb CLI were all in one file — splitting would have added an import seam without changing the surface), per Phase 2 Step 2.
91
+
92
+ ## Open questions (Phase 2 council pass, optional)
93
+
94
+ - Chunk size — fixed (e.g. 2 KB markdown) vs adaptive per document? Default: 2 KB until the recruit sessions or eval surface a reason to change.
95
+ - OCR confidence threshold — 0.7 is a guess; first three sessions inform the right number.
96
+ - Pinning UX — `--pin` flag vs a separate `/knowledge:pin` command. Default in this contract: a flag on `/knowledge:list`.
@@ -7,7 +7,7 @@ mcp_scope: lite
7
7
 
8
8
  > **Status:** Active · governs the `experimental → beta` promotion for
9
9
  > the MCP surface (`scripts/mcp_server/` local stdio kernel + the
10
- > hosted `workers/mcp/` bridge). Owned by Phase 3 of the
10
+ > hosted `internal/workers/mcp/` bridge). Owned by Phase 3 of the
11
11
  > `road-to-surface-discipline` roadmap (see `agents/roadmaps/`).
12
12
  > Companion contract:
13
13
  > [`mcp-phase-1-scope.md`](mcp-phase-1-scope.md) (local) ·
@@ -5,7 +5,7 @@ mcp_scope: lite
5
5
 
6
6
  # MCP Server — Cloud Scope (A0-cloud Hard Contract)
7
7
 
8
- > **Status:** Active · covers `workers/mcp/` (TypeScript Cloudflare
8
+ > **Status:** Active · covers `internal/workers/mcp/` (TypeScript Cloudflare
9
9
  > Worker bridge), MVP-1 surface. Extends — does **not** supersede —
10
10
  > [`mcp-phase-1-scope.md`](mcp-phase-1-scope.md), which retains
11
11
  > exclusive ownership of `scripts/mcp_server/` (local stdio).
@@ -15,7 +15,7 @@ mcp_scope: lite
15
15
  ## Purpose
16
16
 
17
17
  Locks the **execution-safety boundary** for the hosted MCP Worker. Any
18
- code under `workers/mcp/` must satisfy this contract verbatim. The
18
+ code under `internal/workers/mcp/` must satisfy this contract verbatim. The
19
19
  local stdio kernel and the hosted Worker are two distinct surfaces; a
20
20
  deviation in one is **not** authorized by a precedent in the other.
21
21
 
@@ -46,7 +46,7 @@ prose-only.
46
46
  - **What it never does:** execute Python scripts, shell out, spawn
47
47
  runtimes, touch consumer FS, write to R2, mutate consumer state,
48
48
  call upstream LLM APIs, or read `.agent-src.uncompressed/`.
49
- - **Owner code path:** `workers/mcp/` (TypeScript, Cloudflare Worker).
49
+ - **Owner code path:** `internal/workers/mcp/` (TypeScript, Cloudflare Worker).
50
50
  This contract is the normative spec.
51
51
  - **Auth model:** `public` (default) or `bearer-auth` (operator opt-in)
52
52
  per `## Auth surface`. HMAC and CF Access are declared but deferred.
@@ -194,7 +194,7 @@ runtime mode switch.
194
194
  returns HTTP `401` with a JSON-RPC error envelope (code `-32001`,
195
195
  message `"Unauthorized"`) and the RFC 6750
196
196
  `WWW-Authenticate: Bearer realm="agent-config-mcp"` header.
197
- Implementation: `workers/mcp/src/index.ts` § auth gate (the
197
+ Implementation: `internal/workers/mcp/src/index.ts` § auth gate (the
198
198
  `if (requiredToken) { … }` block).
199
199
  - **Liveness carve-out:** the `GET /` liveness probe is
200
200
  unauthenticated by design — health checks and `curl` smoke tests
@@ -52,7 +52,7 @@
52
52
  "tools_count": {
53
53
  "type": "integer",
54
54
  "minimum": 0,
55
- "description": "Sourced from workers/mcp/content.json#/tool_catalog/tools. Hard-sourced — no fallback. R3 (discovery roadmap) is a hard prerequisite per the AI-Council external review."
55
+ "description": "Sourced from internal/workers/mcp/content.json#/tool_catalog/tools. Hard-sourced — no fallback. R3 (discovery roadmap) is a hard prerequisite per the AI-Council external review."
56
56
  },
57
57
  "install_hint_stdio": { "type": "string", "minLength": 1 }
58
58
  }
@@ -47,7 +47,7 @@ keep-beta-until: 2026-08-14
47
47
  ## Glossary
48
48
 
49
49
  - **Side-effect** — `ro` (read-only) · `fs-write` (filesystem write) · `shell` (spawns processes).
50
- - **Transports** — `stdio` (`scripts/mcp_server/`) · `worker` (`workers/mcp/`). A tool may live on both.
50
+ - **Transports** — `stdio` (`scripts/mcp_server/`) · `worker` (`internal/workers/mcp/`). A tool may live on both.
51
51
  - **Stub** — catalog-listed for discovery; returns the `not_implemented` envelope from
52
52
  [`mcp-tool-stub-envelope.md`](mcp-tool-stub-envelope.md) until promoted.
53
53
 
@@ -20,7 +20,7 @@ a 500.
20
20
  ## Source of truth
21
21
 
22
22
  `scripts/mcp_server/consumer_tool_catalog.json` (schema_version 1).
23
- Both the stdio server and the Cloud Worker bundle (`workers/mcp/`,
23
+ Both the stdio server and the Cloud Worker bundle (`internal/workers/mcp/`,
24
24
  packed by `scripts/pack_mcp_content.py`) read from this file. The
25
25
  manifest returned by `tools/list` is byte-identical apart from
26
26
  per-tool `implemented_on` metadata.
@@ -24,7 +24,7 @@ Four axes, all numeric, all reproducible from the same input:
24
24
 
25
25
  Schemas: [`benchmark-report-schema.md`](benchmark-report-schema.md) ·
26
26
  [`benchmark-corpus-spec.md`](benchmark-corpus-spec.md). Reports land at
27
- `bench/reports/<utc-stamp>-<corpus>[-projection].{json,md}` —
27
+ `internal/bench/reports/<utc-stamp>-<corpus>[-projection].{json,md}` —
28
28
  timestamped, never overwritten, content-addressed by run.
29
29
 
30
30
  ## Corpora — frozen for the soak window
@@ -67,10 +67,10 @@ NO ANECDOTE, NO INDIVIDUAL REPORT, NO ROADMAP-SIDE OVERRIDE.
67
67
  [`scripts/bench_baseline_ready.py`](../../scripts/bench_baseline_ready.py)
68
68
  returns exit 0 iff both:
69
69
 
70
- 1. **Wall-clock soak:** `today − bench/baseline-start.txt ≥ --min-days` (default 60)
71
- 2. **Report density:** `bench/reports/*-<corpus>.json` count ≥ `--min-reports` (default 30)
70
+ 1. **Wall-clock soak:** `today − internal/bench/baseline-start.txt ≥ --min-days` (default 60)
71
+ 2. **Report density:** `internal/bench/reports/*-<corpus>.json` count ≥ `--min-reports` (default 30)
72
72
 
73
- Soak start anchored at [`bench/baseline-start.txt`](../../bench/baseline-start.txt)
73
+ Soak start anchored at [`internal/bench/baseline-start.txt`](../../bench/baseline-start.txt)
74
74
  = **2026-05-16**. Earliest possible flip: **2026-07-15**, contingent
75
75
  on the 30-report floor.
76
76
 
@@ -86,11 +86,11 @@ On baseline closure, the step-4 closeout writes the numeric verdict to
86
86
  [`docs/parity/bench.json`](../parity/bench.json) — frozen snapshot with
87
87
  the 30+ reports averaged, drift verdict, and the compression-default
88
88
  decision per the kill-criterion table. That file is the artefact every
89
- P2 roadmap reads — not the live `bench/reports/` directory.
89
+ P2 roadmap reads — not the live `internal/bench/reports/` directory.
90
90
 
91
91
  ## Carve-outs
92
92
 
93
- - **Pricing freshness:** [`bench/pricing.yaml`](../../bench/pricing.yaml) rows must carry `sourced_on: YYYY-MM-DD`. Stale prices = stale numbers = no trust (ruflo "measured-vs-claimed" pattern).
93
+ - **Pricing freshness:** [`internal/bench/pricing.yaml`](../../bench/pricing.yaml) rows must carry `sourced_on: YYYY-MM-DD`. Stale prices = stale numbers = no trust (ruflo "measured-vs-claimed" pattern).
94
94
  - **Subjective grading excluded:** quality scoring is mechanical via `quality_assertion`. No vibes.
95
95
  - **Cursor / Cline / Windsurf:** rules-only surfaces, no SKILL.md projection. `bench:projection` reports them as `not_applicable` — the gap is acknowledged, not silently dropped.
96
96
 
@@ -0,0 +1,121 @@
1
+ ---
2
+ stability: beta
3
+ keep-beta-until: 2026-08-24
4
+ ---
5
+
6
+ # Role-experience contract
7
+
8
+ **Purpose.** Freeze the on-disk shape of a `role-experience` — the artefact that turns a non-developer persona (galabau owner, content creator, consultant, …) into a first-class entry point with three first tasks, a named prompt library, and a curated skill shortlist. Pins the interface **before** the launcher in Phase 4 reads it, so the launcher and the role authors can move independently.
9
+
10
+ Last refreshed: 2026-05-24. Phase 3 of the employee-product workstream.
11
+
12
+ ## What a role experience is
13
+
14
+ A folder at `agents/roles/<role>/` that contains:
15
+
16
+ - One **identity index** (`index.md`) — one-paragraph persona, three concrete first tasks, recommended pack list, install-path hint.
17
+ - A **prompt library** (`prompts/<name>.md`) — 5–10 named prompts, each a single markdown file with structured frontmatter and a parameterised body the launcher can fill.
18
+ - A **skill shortlist** (`skills.yml`) — the existing skills the launcher should surface for this role, in priority order. Cites existing skills only; never duplicates them.
19
+
20
+ A role experience is **not**:
21
+
22
+ - A new skill — the shortlist references existing skills under `packages/<pack>/.agent-src.uncompressed/skills/`. The role experience curates; it does not implement.
23
+ - A documentation page — `docs/getting-started-by-role.md` is the prose surface and links **to** the role experience, never duplicates it.
24
+ - A persona file under `personas/` — personas are review voices the AI Council uses; role experiences are end-user entry points.
25
+
26
+ ## Folder shape
27
+
28
+ ```
29
+ agents/roles/<role>/
30
+ ├── index.md # identity + three first tasks + recommended packs
31
+ ├── skills.yml # skill shortlist (priority-ordered)
32
+ └── prompts/
33
+ ├── <name-1>.md
34
+ ├── <name-2>.md
35
+ └── … # 5–10 prompts
36
+ ```
37
+
38
+ `<role>` is a kebab-case identifier; it doubles as the launcher key and the URL slug. Reserved words: `default`, `_template`, `_archive`.
39
+
40
+ ## `index.md` frontmatter (required)
41
+
42
+ ```yaml
43
+ ---
44
+ role: <kebab-case-id>
45
+ display_name: "Galabau owner"
46
+ tagline: "One-sentence description visible in the launcher rail."
47
+ recommended_packs: [core, founder-strategy] # cites existing packs only
48
+ install_path_hint: "MCP recommended (Claude Desktop) · CLI when …"
49
+ recruit_session_ref: "agents/recruit-sessions/01-galabau-owner.md" # nullable until session lands
50
+ status: stable | beta | draft
51
+ ---
52
+ ```
53
+
54
+ The body of `index.md` then lists, in this order:
55
+
56
+ 1. **Persona paragraph** (≤ 80 words) — who this role is for, in the role's own language.
57
+ 2. **Three first tasks** — each a single sentence + the prompt name (`prompts/<name>.md`) that bootstraps it.
58
+ 3. **Recommended pack list** — referenced from frontmatter, expanded with one-line rationale per pack.
59
+
60
+ ## Prompt frontmatter (required)
61
+
62
+ Each `prompts/<name>.md` carries:
63
+
64
+ ```yaml
65
+ ---
66
+ name: <kebab-case-id> # unique within the role's prompts/ folder
67
+ intent: "One sentence: what the user gets out of this prompt."
68
+ inputs:
69
+ - name: customer_brief
70
+ required: true
71
+ shape: "free-text paragraph"
72
+ - name: tone
73
+ required: false
74
+ shape: "one of [neutral, warm, urgent]"
75
+ output_shape: "Markdown — H2 sections, ≤ 600 words, structured offer."
76
+ skill_hint: refine-prompt # which skill the host should foreground; cites existing skill
77
+ ---
78
+ ```
79
+
80
+ The body is the parameterised prompt itself, with `{{input_name}}` placeholders the launcher fills before sending to the host model. Bodies stay ≤ 200 lines; prompts longer than that get split.
81
+
82
+ ## `skills.yml` shape
83
+
84
+ ```yaml
85
+ # Priority-ordered. The launcher surfaces the first 5 in its default view; the rest go behind "more".
86
+ skills:
87
+ - id: refine-prompt
88
+ why: "Tightens fuzzy customer briefs before any drafting."
89
+ - id: voice-and-tone-design
90
+ why: "Locks the role's voice so emails read consistent across customers."
91
+ - id: doc-coauthoring
92
+ why: "Section-by-section drafting flow for longer offers."
93
+ ```
94
+
95
+ Every `id` must resolve to an existing skill under `packages/<pack>/.agent-src.uncompressed/skills/<id>/SKILL.md` — verified by the lint pass in Phase 3 Step 6.
96
+
97
+ ## Versioning + status
98
+
99
+ - `status: draft` — scaffold only, no recruit-session evidence yet. Launcher hides drafts in the default view.
100
+ - `status: beta` — scaffold + at least one recruit session backs the first-task choice. Launcher surfaces with a `beta` badge.
101
+ - `status: stable` — at least two recruit sessions concurred on the role's first tasks and the friction-inventory landed at ≤ 3 P0 items.
102
+
103
+ Status promotion is a maintainer decision, captured in the `recruit_session_ref` frontmatter trail. Demotion (stable → beta) happens when a follow-up recruit session contradicts the existing first-task choice.
104
+
105
+ ## Lint pass (deferred to Phase 3 Step 6)
106
+
107
+ The lint pass (`task lint-role-experiences`, wired into `task ci`) asserts:
108
+
109
+ 1. Every `agents/roles/<role>/index.md` has all required frontmatter keys + at least 3 first tasks.
110
+ 2. Every `prompts/<name>.md` has the four required frontmatter keys (`name`, `intent`, `inputs`, `output_shape`) plus `skill_hint`.
111
+ 3. Every `skills.yml#skills[].id` resolves to an existing skill.
112
+ 4. Every `recommended_packs[]` entry resolves to an existing pack manifest.
113
+ 5. Status promotion never happens without a non-null `recruit_session_ref`.
114
+
115
+ Lint pass code lives at `scripts/lint_role_experiences.py`, ≤ 200 LOC. Until the lint pass ships, the scaffolds in Phase 3 Steps 2–4 are hand-validated against this contract.
116
+
117
+ ## Open questions (Phase 3 optional council pass)
118
+
119
+ - Per-role default model — should `index.md` carry a `default_model` frontmatter key the launcher honours, or stay at the host's global default? Default in this contract: stay at host default; per-role override is a future ADR.
120
+ - Prompt input typing — should `inputs[].shape` be free-text or constrained to a small enum (`text`, `enum`, `file-path`, `url`)? Default: free-text; constraint enum is a future tightening.
121
+ - Multi-language prompt bodies — German vs English by role? Default: prompt bodies follow the language policy of the package (English); the host translates at runtime per `language-and-tone`.
@@ -0,0 +1,140 @@
1
+ # Workspace Documents Contract
2
+
3
+ > **Status** · v0 / design · 2026-05-24. Phase 5 of the
4
+ > employee-product workstream.
5
+ > Builds on the [`daily-workspace`](daily-workspace.md) surface and
6
+ > the host-agent protocol from
7
+ > [`ADR-023`](../decisions/ADR-023-host-agent-protocol.md). Documents
8
+ > are the **output shape** of selected launcher prompts.
9
+
10
+ ## When a launcher prompt produces a document
11
+
12
+ A launcher prompt is **document-shaped** when its frontmatter sets
13
+ `output_shape: document`. Otherwise the prompt is **chat-shaped**
14
+ (default) — the host reply lands in the session JSONL log only.
15
+
16
+ ```yaml
17
+ # agents/roles/galabau/prompts/angebot-erstellen.md
18
+ ---
19
+ title: Angebot erstellen
20
+ output_shape: document
21
+ document_type: offer
22
+ slug: from_title
23
+ ---
24
+ ```
25
+
26
+ Recognised `document_type` values (v0): `offer`, `mail-draft`,
27
+ `memo`, `brief`, `video-script`. Unknown types are rejected at
28
+ launcher-load time with a banner; the prompt falls back to
29
+ chat-shaped.
30
+
31
+ ## Storage layout
32
+
33
+ ```
34
+ ~/.event4u/agent-config/workspace/documents/
35
+ ├── offer/
36
+ │ ├── kundeX-angebot-2026-05-24.md ← body
37
+ │ └── kundeX-angebot-2026-05-24.history.jsonl ← per-save revision log
38
+ ├── mail-draft/
39
+ ├── memo/
40
+ ├── brief/
41
+ └── video-script/
42
+ ```
43
+
44
+ Slug rules: kebab-case ASCII; deduped by appending `-2`, `-3`, …;
45
+ filename never contains PII. Slug default = `slugify(title) + "-" + iso-date`.
46
+
47
+ ## Document frontmatter
48
+
49
+ ```markdown
50
+ ---
51
+ type: offer
52
+ title: Angebot Kunde X
53
+ created_at: 2026-05-24T12:08:00Z
54
+ last_edited_at: 2026-05-24T12:14:00Z
55
+ source_prompt: agents/roles/galabau/prompts/angebot-erstellen.md
56
+ source_session: 20260524T120800Z-a1b2c3d4
57
+ role: galabau
58
+ tags: [kunde-x, gartenbau, 2026-q2]
59
+ schema: workspace-document/v0
60
+ ---
61
+
62
+ [document body — Markdown, host-generated, user-edited]
63
+ ```
64
+
65
+ `source_prompt` + `source_session` form the provenance pair: every
66
+ document points back to the prompt that produced it and the session
67
+ that ran it. The session JSONL stays in the session store; only the
68
+ **reference** lives here.
69
+
70
+ ## Revision log
71
+
72
+ Path: `<slug>.history.jsonl`. Append-only. One entry per save.
73
+
74
+ ```json
75
+ {
76
+ "ts": "2026-05-24T12:14:00Z",
77
+ "actor": "user",
78
+ "kind": "save",
79
+ "delta": { "added": 12, "removed": 4 },
80
+ "body_sha256": "ab12…"
81
+ }
82
+ ```
83
+
84
+ Actor `host` marks the initial-creation save (from the host agent's
85
+ reply). Actor `user` marks every subsequent edit. No body in the
86
+ log — only the SHA. The body lives in the `.md` file; rollback walks
87
+ the SHA chain and reconstructs from a tracked-base + delta is
88
+ **deferred** to v1 (v0 keeps only the latest body).
89
+
90
+ ## Export
91
+
92
+ | Format | How | Notes |
93
+ |---|---|---|
94
+ | Markdown | identity copy of `<slug>.md` | always available |
95
+ | PDF | `markitdown` reverse path (preferred), `pandoc` fallback | requires `pandoc` on PATH for fallback |
96
+ | DOCX | `pandoc <slug>.md -o <slug>.docx` | requires `pandoc` on PATH |
97
+
98
+ Export target: user picks a folder via the OS picker. No autosave to
99
+ cloud, no upload, no remote backend. Export failures surface as a
100
+ banner; partial files are not left behind.
101
+
102
+ ## Workspace integration
103
+
104
+ - Phase 4 right-rail "Recent documents" list shows ≤ 20 most-recent
105
+ entries scoped to the current role; click → opens the body in the
106
+ user's default Markdown editor.
107
+ - The workspace **centre pane** for a document-shaped session shows
108
+ the document body live (read-only) plus a "Edit" button that
109
+ hands off to the OS default `.md` editor.
110
+ - Closing the workspace does not lock the document file — it stays
111
+ user-editable.
112
+
113
+ ## Failure modes
114
+
115
+ - Host CLI returns a non-document reply for a document-shaped prompt
116
+ → workspace stores the raw text under `<slug>.md` with a
117
+ `quarantine: true` frontmatter flag; UI shows a one-line banner.
118
+ - Disk full → red banner, no silent body loss.
119
+ - Frontmatter parse failure → revision log still appends a
120
+ `kind: save_failed` record; user's working file is preserved
121
+ alongside as `<slug>.broken.md`.
122
+
123
+ ## Coverage requirements (Phase 5 Step 6)
124
+
125
+ - Golden tests on the export rendering: 3 fixture documents × 3
126
+ export formats (Markdown / PDF / DOCX). Fixtures under
127
+ `tests/golden/workspace-documents/`.
128
+ - Schema-validation tests on the frontmatter contract using
129
+ `tests/fixtures/workspace-documents/valid/` and `invalid/`.
130
+ - ≥ 80 % branch on save + history-append paths.
131
+
132
+ ## Cross-references
133
+
134
+ - [`daily-workspace`](daily-workspace.md) — workspace shell that
135
+ hosts the document view.
136
+ - [`host-agent-protocol`](host-agent-protocol.md) — how the document
137
+ body is produced.
138
+ - [`local-knowledge-ingestion`](local-knowledge-ingestion.md) —
139
+ sources cited inside documents.
140
+ - ADRs: [`023`](../decisions/ADR-023-host-agent-protocol.md), [`024`](../decisions/ADR-024-workspace-v0-feature-floor.md), [`025`](../decisions/ADR-025-workspace-chrome.md).
@@ -0,0 +1,140 @@
1
+ ---
2
+ adr: 022
3
+ status: accepted
4
+ date: 2026-05-24
5
+ decision: daily-workspace-decomposition
6
+ supersedes: —
7
+ superseded_by: —
8
+ phase: v3.x · employee-product-and-external-proof Phase 4
9
+ type: forward-looking
10
+ ---
11
+
12
+ # ADR-022 — Daily workspace — decomposition
13
+
14
+ ## Status
15
+
16
+ **Accepted** · 2026-05-24. Phase 4 Step 1 of
17
+ [`road-to-employee-product-and-external-proof.md`](../../agents/roadmaps/road-to-employee-product-and-external-proof.md).
18
+ Records the council's verdict on the original "workspace shape"
19
+ question — that the question was malformed — and replaces a single
20
+ chrome decision with three sequenced sub-decisions.
21
+
22
+ The numeric reservation note in
23
+ [`ADR-021`](ADR-021-deployment-shape.md) (ADRs 022–025 held for the
24
+ internal-AI-OS-deployment roadmap) is retired: that roadmap is
25
+ archived ([`agents/roadmaps/archive/road-to-internal-ai-os-deployment.md`](../../agents/roadmaps/archive/road-to-internal-ai-os-deployment.md))
26
+ and the active strategy after release `3.1.1` is the
27
+ employee-product / external-proof roadmap. ADR-022 claims the
28
+ number under the new strategy.
29
+
30
+ Companion artefacts:
31
+
32
+ - Roadmap: [`agents/roadmaps/road-to-employee-product-and-external-proof.md`](../../agents/roadmaps/road-to-employee-product-and-external-proof.md)
33
+ - Council question: [`agents/decisions/open-questions/daily-workspace-shape.md`](../../agents/decisions/open-questions/daily-workspace-shape.md)
34
+ - Council verdict: `agents/runtime/council/responses/daily-workspace-shape.json` (gitignored)
35
+ - Predecessor ADRs: [`ADR-014`](ADR-014-gui-framework-choice.md) (installer chrome), [`ADR-016`](ADR-016-installer-architecture.md) (installer architecture), [`ADR-020`](ADR-020-global-only-consumer-scope.md) (consumer scope).
36
+
37
+ ## Context
38
+
39
+ Phase 4 of the post-`3.1.1` roadmap proposes a persistent daily
40
+ workspace — left rail (role + task launcher), centre pane (active
41
+ conversation with the host agent), right rail (knowledge sources +
42
+ explain-trace) — as the missing daily-use surface for non-developer
43
+ roles (galabau owner, content creator, consultant).
44
+
45
+ The original Step 1 framed the decision as a four-way chrome pick:
46
+ extend the GUI installer · separate Electron/Tauri app · browser tab
47
+ · TUI-first. The council was asked to choose one.
48
+
49
+ ## What the council said
50
+
51
+ Both council members (claude-sonnet-4-5, gpt-4o) **rejected the
52
+ question as malformed** after a two-round debate. The convergent
53
+ verdict, in their own words:
54
+
55
+ > *"The ADR masquerades as a UI choice when it is actually three
56
+ > entangled, unsequenced decisions: (1) the protocol boundary to
57
+ > host agents, (2) the v0 feature scope that validates 'non-developers
58
+ > prefer this', (3) the chrome that wraps that scope."*
59
+ > — Anthropic
60
+
61
+ > *"Without a stable, documented protocol between the workspace and
62
+ > host agents, the ADR's proposition lacks substance and could be
63
+ > shelved until a reliable, documented, and tested protocol is
64
+ > defined."* — OpenAI
65
+
66
+ The load-bearing critique is that the workspace contract requires
67
+ two capabilities the host agents (Claude Code, Augment, Cursor,
68
+ Cline, Windsurf) have not been confirmed to expose:
69
+
70
+ 1. A stable RPC / IPC surface for **launching a conversation with a
71
+ pre-filled prompt + pre-selected skill** (not just CLI flags that
72
+ drift per Hyrum's Law).
73
+ 2. Structured **explain-trace emission** (not "parse stdout and hope").
74
+
75
+ Until both are proven for at least one host agent, no chrome option
76
+ can be implemented — each inherits the same fatal coupling risk.
77
+
78
+ ## Decision
79
+
80
+ Split Phase 4 Step 1 into three sequential sub-decisions, each its
81
+ own ADR:
82
+
83
+ 1. **ADR-023 — Host-agent protocol contract** *(blocking)*. Inventory
84
+ the surface each named host agent exposes today, name the
85
+ fallback for missing surfaces, write `docs/contracts/host-agent-protocol.md`.
86
+ Status today: **drafted, not started**.
87
+ 2. **ADR-024 — Workspace v0 feature floor** *(depends on ADR-023)*.
88
+ Define the minimum viable shell that recruit-session participants
89
+ can evaluate. Pare back from "left rail + centre pane + right rail"
90
+ to whatever the protocol from ADR-023 can actually drive end-to-end.
91
+ 3. **ADR-025 — Workspace chrome** *(depends on ADR-024)*. The original
92
+ four-way pick (installer-extension · Electron/Tauri · browser tab ·
93
+ TUI), narrowed by what ADR-024 needs and what ADR-023 makes
94
+ feasible.
95
+
96
+ The roadmap is updated accordingly: Phase 4 grows two new gating
97
+ steps (ADR-023 + ADR-024) ahead of the chrome decision. The
98
+ "≤ 6 weeks for one engineer" budget assumption from the original
99
+ roadmap is preserved as a working figure — both council members
100
+ flagged it as ambitious. ADR-024 will tighten it.
101
+
102
+ ## Consequences
103
+
104
+ **Positive**
105
+
106
+ - The blocking risk (host-agent protocol feasibility) is surfaced
107
+ as its own ADR with its own go/no-go gate, not buried under a
108
+ chrome debate.
109
+ - Phase 4 cannot accidentally ship a chrome built on an unproven
110
+ integration substrate.
111
+ - Recruit sessions (Phase 1) get a clearer signal of *what* to
112
+ validate: "does the v0 feature floor solve the daily-use gap?"
113
+ rather than "do you prefer this UI?"
114
+
115
+ **Negative**
116
+
117
+ - Phase 4 ships two additional ADRs before any code lands. Adds
118
+ governance overhead; the autonomous-execution rule narrows the
119
+ ask-tax but doesn't remove it.
120
+ - The chrome decision (ADR-025) is deferred at least one council
121
+ round behind ADR-023 + ADR-024.
122
+
123
+ **Reversal cost** — low. If ADR-023 proves the protocol is trivially
124
+ stable, ADR-024 can collapse to a one-line "we re-adopt the
125
+ original v1 scope" decision and ADR-025 proceeds against the
126
+ original four-way pick.
127
+
128
+ ## Open questions (next-ADR-deferred)
129
+
130
+ - Whether the host-agent protocol investigation should be
131
+ council-gated again or treated as a research artefact (ADR-023
132
+ will say).
133
+ - Whether "host agent" remains plural or narrows to one supported
134
+ host for v0 (ADR-024 will say).
135
+
136
+ ## Cross-references
137
+
138
+ - Council question file: [`agents/decisions/open-questions/daily-workspace-shape.md`](../../agents/decisions/open-questions/daily-workspace-shape.md)
139
+ - Role identity scaffolds (Phase 3 output): [`agents/roles/`](../../agents/roles/)
140
+ - Knowledge-ingestion contract (Phase 2 input): [`docs/contracts/local-knowledge-ingestion.md`](../contracts/local-knowledge-ingestion.md)