@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
@@ -66,7 +66,7 @@ Extract from latest record:
66
66
  - `by_model[]` — per-tier (haiku / sonnet / opus) input / output / cache split
67
67
  - `budget.tier` — `under` / `50` / `75` / `90` / `100` (from `node scripts/cost/budget.mjs check`)
68
68
 
69
- Pricing source: [`bench/pricing.yaml`](../../bench/pricing.yaml). Reader
69
+ Pricing source: [`internal/bench/pricing.yaml`](../../bench/pricing.yaml). Reader
70
70
  implementation: [`scripts/cost/track.mjs`](../../scripts/cost/track.mjs).
71
71
 
72
72
  ### 3b. Read caveman delta + per-conversation cost lens
@@ -0,0 +1,78 @@
1
+ ---
2
+ name: analytics:prune
3
+ tier: 2
4
+ cluster: analytics
5
+ sub: prune
6
+ description: Drop events older than the 90-day retention window from the local analytics log. Atomic and idempotent.
7
+ skills: [file-editor]
8
+ disable-model-invocation: true
9
+ suggestion:
10
+ eligible: true
11
+ trigger_description: "prune the analytics log, drop old events, clean up events.jsonl"
12
+ trigger_context: "user wants to manually advance the rolling retention window"
13
+ workspaces:
14
+ - agent-config-maintainer
15
+ packs:
16
+ - meta
17
+ lifecycle: active
18
+ trust:
19
+ level: core
20
+ confidence: high
21
+ human_review_required: false
22
+ install:
23
+ default: true
24
+ removable: false
25
+ ---
26
+
27
+ # /analytics prune
28
+
29
+ Drops every record in `events.jsonl` whose timestamp is older than the
30
+ 90-day retention window. Atomic: writes to `events.jsonl.tmp` first,
31
+ then renames over the original. A lock file prevents two prune passes
32
+ from racing.
33
+
34
+ ## Prerequisites
35
+
36
+ - Python 3.10+ on the host.
37
+ - `~/.event4u/agent-config/workspace/analytics/events.jsonl` exists.
38
+
39
+ ## Steps
40
+
41
+ ### 1. Run the implementation
42
+
43
+ ```bash
44
+ python3 packages/core/installer/python/workspace_analytics.py prune
45
+ ```
46
+
47
+ No flags. The 90-day window is fixed by contract.
48
+
49
+ ### 2. Surface the result
50
+
51
+ ```
52
+ > pruned 47 event(s)
53
+ ```
54
+
55
+ If the file is missing or already empty, print `pruned 0 event(s)` and
56
+ exit 0 — pruning is idempotent.
57
+
58
+ ### 3. If another prune pass is running
59
+
60
+ The implementation acquires `retention.lock` with `O_EXCL`. If the lock
61
+ is held, the call returns 0 dropped (silent no-op). Re-run after the
62
+ other pass finishes.
63
+
64
+ ## Safety
65
+
66
+ - **Atomic file replace.** The new JSONL is written to `events.jsonl.tmp`
67
+ and atomically renamed with `replace`; no readers see a half-written
68
+ file.
69
+ - **Lock-file mutex.** `retention.lock` is created with `O_EXCL` and
70
+ unlinked in a `finally` block — even on crash, the next run can
71
+ reclaim it after the lock owner is gone.
72
+ - Never reads the network, never POSTs.
73
+
74
+ ## See also
75
+
76
+ - [`/analytics show`](show.md) — render the (post-prune) report.
77
+ - [`local-analytics`](../../../docs/contracts/local-analytics.md)
78
+ § Storage — atomicity guarantees and lock semantics.
@@ -0,0 +1,107 @@
1
+ ---
2
+ name: analytics:show
3
+ tier: 2
4
+ cluster: analytics
5
+ sub: show
6
+ description: Render top prompts, launcher → completion rate per role, average session length, and knowledge-source usage from the local analytics log.
7
+ skills: [file-editor]
8
+ disable-model-invocation: true
9
+ suggestion:
10
+ eligible: true
11
+ trigger_description: "show analytics, top prompts last 30 days, which role launched what, completion rate per role"
12
+ trigger_context: "user wants a human-readable report from the local workspace event log"
13
+ workspaces:
14
+ - agent-config-maintainer
15
+ packs:
16
+ - meta
17
+ lifecycle: active
18
+ trust:
19
+ level: core
20
+ confidence: high
21
+ human_review_required: false
22
+ install:
23
+ default: true
24
+ removable: false
25
+ ---
26
+
27
+ # /analytics show
28
+
29
+ Renders the local event log as a report. Never reads remote data, never
30
+ POSTs. Defaults to a 30-day window and markdown output.
31
+
32
+ ## Prerequisites
33
+
34
+ - Python 3.10+ on the host.
35
+ - `~/.event4u/agent-config/workspace/analytics/events.jsonl` exists or
36
+ is empty (empty is a normal result, not an error).
37
+
38
+ ## Steps
39
+
40
+ ### 1. Parse the argument
41
+
42
+ ```
43
+ /analytics show [--window 24h|7d|30d] [--event <name>] [--role <slug>]
44
+ [--format markdown|csv|json]
45
+ ```
46
+
47
+ - `--window` defaults to `30d`.
48
+ - `--format` defaults to `markdown`.
49
+ - `--event` and `--role` are optional filters.
50
+
51
+ ### 2. Run the implementation
52
+
53
+ ```bash
54
+ python3 packages/core/installer/python/workspace_analytics.py \
55
+ show [--window=...] [--event=...] [--role=...] [--format=...]
56
+ ```
57
+
58
+ ### 3. Surface the result
59
+
60
+ **Markdown** view (default):
61
+
62
+ ```
63
+ # Workspace analytics — last 30d
64
+
65
+ ## Top prompts
66
+
67
+ - `tradesperson` · `estimate` — 12
68
+ - `content-creator` · `script-video` — 7
69
+
70
+ ## Launcher → completion rate per role
71
+
72
+ - `tradesperson` — 83% (12 launched · 10 completed)
73
+
74
+ **Average session length:** 3m 41s
75
+ **Knowledge sources clicked:** 14
76
+ ```
77
+
78
+ **CSV** view — one row per event: `ts,event,role,task,host_tier,duration_ms`.
79
+ Pipe into `awk`/`csvkit` for ad-hoc queries.
80
+
81
+ **JSON** view — full event array; useful for `jq` filters or chart
82
+ pipelines.
83
+
84
+ ### 4. Empty log
85
+
86
+ Print the markdown shell with `_No events recorded in this window._`
87
+ and offer the next step:
88
+
89
+ ```
90
+ > 1. open the workspace tab to start recording events
91
+ > 2. /analytics prune — drop stale records older than 90 days
92
+ ```
93
+
94
+ ## Safety
95
+
96
+ - Read-only. Never writes to the JSONL, never opens the network.
97
+ - The opt-out check (env + settings) short-circuits before the file is
98
+ opened — see [`local-analytics`](../../../docs/contracts/local-analytics.md)
99
+ § Opt-out.
100
+
101
+ ## See also
102
+
103
+ - [`/analytics prune`](prune.md) — drop events older than 90 days.
104
+ - [`local-analytics`](../../../docs/contracts/local-analytics.md) — full
105
+ schema and retention contract.
106
+ - [`local-analytics walkthrough`](../../../docs/guides/local-analytics.md)
107
+ — the 3-minute read for end-users.
@@ -0,0 +1,64 @@
1
+ ---
2
+ name: analytics
3
+ tier: 2
4
+ description: Analytics orchestrator — routes to show, prune. Local-only workspace event log under `~/.event4u/agent-config/workspace/analytics/`.
5
+ cluster: analytics
6
+ type: orchestrator
7
+ disable-model-invocation: true
8
+ suggestion:
9
+ eligible: true
10
+ trigger_description: "show my workspace analytics, top prompts last week, which role launched what, prune the analytics log"
11
+ trigger_context: "user wants to read or maintain the local-only workspace event log"
12
+ workspaces:
13
+ - agent-config-maintainer
14
+ packs:
15
+ - meta
16
+ lifecycle: active
17
+ trust:
18
+ level: core
19
+ confidence: high
20
+ human_review_required: false
21
+ install:
22
+ default: true
23
+ removable: false
24
+ ---
25
+
26
+ # /analytics
27
+
28
+ Top-level orchestrator for the `/analytics` family — the **local
29
+ workspace analytics** cluster. Local-only, never POSTs, opt-out via
30
+ env or `.agent-settings.yml`.
31
+
32
+ Anchors: [`local-analytics`](../docs/contracts/local-analytics.md)
33
+ contract — schema, retention, opt-out, event vocabulary.
34
+
35
+ ## Sub-commands
36
+
37
+ | Sub-command | Routes to | Purpose |
38
+ |---|---|---|
39
+ | `/analytics show` | `commands/analytics/show.md` | Render top prompts, launcher → completion, session length, knowledge usage |
40
+ | `/analytics prune` | `commands/analytics/prune.md` | Drop events older than the 90-day retention window |
41
+
42
+ ## Dispatch
43
+
44
+ 1. Parse the user's argument: `/analytics <sub-command> [args]`.
45
+ 2. Look up the sub-command in the table above.
46
+ 3. Load the body of the routed file and follow its `## Steps` section
47
+ verbatim with the remaining args.
48
+ 4. If the sub-command is unknown or missing, print the table above and ask:
49
+
50
+ > 1. show — render the analytics report (markdown · csv · json)
51
+ > 2. prune — drop events older than 90 days
52
+
53
+ ## Rules
54
+
55
+ - **Local-only.** This cluster never POSTs. It is disjoint from the
56
+ 3.1.0 telemetry SDK Worker (which is undeployed by design).
57
+ - **Opt-out wins.** If `AGENT_CONFIG_NO_LOCAL_ANALYTICS=1` or
58
+ `.agent-settings.yml → analytics.local: off`, every sub-command
59
+ becomes a no-op before any file is opened.
60
+ - **Closed event vocabulary.** Emitters reject unknown event names —
61
+ see [`local-analytics`](../docs/contracts/local-analytics.md)
62
+ § Event vocabulary.
63
+ - **Do NOT commit, push, or open a PR** unless the user explicitly asks.
64
+ - **Do NOT chain sub-commands.** One `/analytics <sub>` per turn.
@@ -0,0 +1,104 @@
1
+ ---
2
+ name: knowledge:forget
3
+ tier: 2
4
+ cluster: knowledge
5
+ sub: forget
6
+ description: Drop a knowledge ingest from `agents/memory/knowledge/` by id prefix. Atomic, no partial state. Pinning protects from LRU eviction, not from explicit forget — pinned ingests are dropped the same.
7
+ skills: [file-editor]
8
+ disable-model-invocation: true
9
+ suggestion:
10
+ eligible: true
11
+ trigger_description: "forget this ingest, drop the acme knowledge, remove the customer folder from agent memory"
12
+ trigger_context: "user wants to purge a specific knowledge ingest"
13
+ workspaces:
14
+ - agent-config-maintainer
15
+ packs:
16
+ - meta
17
+ lifecycle: active
18
+ trust:
19
+ level: core
20
+ confidence: high
21
+ human_review_required: false
22
+ install:
23
+ default: true
24
+ removable: false
25
+ ---
26
+
27
+ # /knowledge forget
28
+
29
+ Removes one ingest from `agents/memory/knowledge/`. The id prefix
30
+ must resolve to exactly one ingest — otherwise the command refuses
31
+ and asks for a longer prefix.
32
+
33
+ ## Prerequisites
34
+
35
+ - An ingest matching the prefix exists. Run `/knowledge list` first
36
+ to find it.
37
+ - The id prefix is **8 characters or more** in practice — uuid7 ids
38
+ are unique on the first 8 hex chars within a single namespace,
39
+ and the dispatcher rejects ambiguous prefixes.
40
+
41
+ ## Steps
42
+
43
+ ### 1. Parse the argument
44
+
45
+ ```
46
+ /knowledge forget <ingest-id-prefix>
47
+ ```
48
+
49
+ If the prefix is missing → print the usage line above and stop. Do
50
+ **not** guess — there is no safe default.
51
+
52
+ ### 2. Run the implementation
53
+
54
+ ```bash
55
+ python3 packages/core/installer/python/knowledge_ingest.py \
56
+ forget <ingest-id-prefix>
57
+ ```
58
+
59
+ The module:
60
+
61
+ - Resolves the prefix; rejects if zero or multiple matches.
62
+ - Removes the entire `agents/memory/knowledge/<ingest-id>/` directory
63
+ in one `shutil.rmtree` — chunks, manifest, everything.
64
+ - Returns the full ingest-id that was removed.
65
+
66
+ ### 3. Surface the result
67
+
68
+ ```
69
+ > ✅ forgot 01a2b3c4-5d6e-7890-abcd-ef1234567890
70
+ > source: /Users/maintainer/clients/acme
71
+ > documents: 12, chunks: 47, bytes recovered: 318012
72
+ ```
73
+
74
+ If the prefix matched zero ingests, surface a structured error:
75
+
76
+ ```
77
+ > ❌ no ingest matches prefix: <prefix>
78
+ > run /knowledge list to see what's there
79
+ ```
80
+
81
+ If the prefix matched multiple ingests:
82
+
83
+ ```
84
+ > ❌ ambiguous prefix: <prefix> — matches <n> ingests
85
+ > use a longer prefix (first 8 hex chars is usually enough)
86
+ ```
87
+
88
+ ## Safety
89
+
90
+ - **Destructive — no undo.** The chunked content is gone after this
91
+ command returns. The Python module does not move-to-trash; it
92
+ removes the directory.
93
+ - The command **never** removes the parent `agents/memory/knowledge/`
94
+ directory itself — only the matching `<ingest-id>/` subdirectory.
95
+ - The command **never** writes outside `agents/memory/knowledge/`.
96
+ - Pinning is irrelevant here — pinning protects from LRU eviction,
97
+ not from explicit user-driven forget.
98
+
99
+ ## See also
100
+
101
+ - [`/knowledge ingest`](ingest.md) — add a new ingest.
102
+ - [`/knowledge list`](list.md) — find an id prefix.
103
+ - [`local-knowledge-ingestion`](../../../docs/contracts/local-knowledge-ingestion.md)
104
+ § Storage — directory layout.
@@ -0,0 +1,122 @@
1
+ ---
2
+ name: knowledge:ingest
3
+ tier: 2
4
+ cluster: knowledge
5
+ sub: ingest
6
+ description: Walk a local path (folder, .zip, single file), redact PII + secrets, chunk to 2 KB markdown, and persist into the agent memory namespace under `knowledge/<ingest-id>/`.
7
+ skills: [file-editor]
8
+ disable-model-invocation: true
9
+ suggestion:
10
+ eligible: true
11
+ trigger_description: "ingest this folder, add these PDFs to the agent, point the agent at my customer files, /knowledge:ingest <path>"
12
+ trigger_context: "user wants the agent to know about a local folder or document without OAuth connectors"
13
+ workspaces:
14
+ - agent-config-maintainer
15
+ packs:
16
+ - meta
17
+ lifecycle: active
18
+ trust:
19
+ level: core
20
+ confidence: high
21
+ human_review_required: false
22
+ install:
23
+ default: true
24
+ removable: false
25
+ ---
26
+
27
+ # /knowledge ingest
28
+
29
+ Indexes a local path into the agent's memory namespace. Local-only,
30
+ single-user, bounded. Implements the
31
+ [`local-knowledge-ingestion`](../../../docs/contracts/local-knowledge-ingestion.md)
32
+ contract.
33
+
34
+ ## Prerequisites
35
+
36
+ - Python 3.10+ available on the host.
37
+ - Path is local — absolute or relative to the project root. Remote
38
+ schemes are rejected.
39
+ - `markitdown` is on `PATH` (or `--markitdown=<bin>` supplied) **if**
40
+ the corpus contains binary formats (PDF, DOCX, XLSX, EPUB, PPTX,
41
+ images). Pure markdown / text corpora work without it.
42
+
43
+ ## Steps
44
+
45
+ ### 1. Parse the argument
46
+
47
+ The user invokes `/knowledge ingest <path> [--no-redact]
48
+ [--markitdown=<bin>]`. The path is the first positional argument.
49
+
50
+ If `<path>` is missing → print the usage line above and stop.
51
+
52
+ ### 2. Pre-flight checks
53
+
54
+ Run before any file is touched:
55
+
56
+ - Reject `http://`, `https://`, `s3://`, `gs://`, `azure://`.
57
+ - Resolve the path; reject if it does not exist.
58
+ - If the path is a `.zip`, the implementation unpacks into `$TMPDIR`
59
+ and cleans up after the call returns — no manual handling needed.
60
+
61
+ ### 3. Run the implementation
62
+
63
+ ```bash
64
+ python3 packages/core/installer/python/knowledge_ingest.py \
65
+ ingest <path> [--no-redact] [--markitdown=<bin>]
66
+ ```
67
+
68
+ The module enforces:
69
+
70
+ - ≤ 1000 documents per call
71
+ - ≤ 20 MB per file
72
+ - ≤ 500 MB total namespace footprint (LRU eviction by `last_touched`)
73
+ - ≤ 10 directories deep
74
+
75
+ Crossing any bound is a **hard reject** with a structured error
76
+ naming the bound and the observed value. No partial writes.
77
+
78
+ ### 4. Surface the result
79
+
80
+ The module prints a JSON manifest. Summarize in chat:
81
+
82
+ ```
83
+ > ✅ ingested <ingest-id-short> from <source>
84
+ > documents: <n>, chunks: <m>, bytes_stored: <b>
85
+ > PII redacted: EMAIL=<x>, PHONE=<y>, IBAN=<z>, CC=<a>, SSN=<b>
86
+ > secrets redacted: <s>
87
+ > skipped: <count> unsupported MIME
88
+ ```
89
+
90
+ If `redacted: false` (user passed `--no-redact`), surface a
91
+ **non-omittable warning** that the corpus may contain PII or secrets
92
+ in plaintext.
93
+
94
+ ### 5. Hand off
95
+
96
+ Show the user how to retrieve:
97
+
98
+ ```
99
+ > Next steps:
100
+ > 1. /knowledge list — see all ingests + sizes
101
+ > 2. /knowledge list --pin <id> — pin so it survives LRU eviction
102
+ > 3. /knowledge forget <id> — drop this ingest atomically
103
+ ```
104
+
105
+ ## Safety
106
+
107
+ - The command **never** fetches the network. Remote-URL rejection is
108
+ the first input check, before any path resolution.
109
+ - The command **never** writes outside `agents/memory/knowledge/`.
110
+ - Redaction defaults to ON. `--no-redact` is a deliberate maintainer
111
+ opt-out, not a UX default.
112
+ - LRU eviction is by **ingest**, never by chunk — partial ingests
113
+ cannot exist in the namespace.
114
+
115
+ ## See also
116
+
117
+ - [`local-knowledge-ingestion`](../../../docs/contracts/local-knowledge-ingestion.md)
118
+ — contract (input shapes, bounds, storage, redaction).
119
+ - [`/knowledge list`](list.md) — what's been ingested, pinning.
120
+ - [`/knowledge forget`](forget.md) — drop an ingest atomically.
121
+ - [`markitdown`](../../skills/markitdown/SKILL.md) — peer-side adapter
122
+ for PDF / DOCX / XLSX / images.
@@ -0,0 +1,102 @@
1
+ ---
2
+ name: knowledge:list
3
+ tier: 2
4
+ cluster: knowledge
5
+ sub: list
6
+ description: List existing knowledge ingests in `agents/memory/knowledge/` (table or JSON); pin / unpin by id prefix to control LRU eviction.
7
+ skills: [file-editor]
8
+ disable-model-invocation: true
9
+ suggestion:
10
+ eligible: true
11
+ trigger_description: "what knowledge has the agent ingested, list ingested folders, show knowledge memory, pin this ingest"
12
+ trigger_context: "user wants to inspect or curate the local knowledge namespace"
13
+ workspaces:
14
+ - agent-config-maintainer
15
+ packs:
16
+ - meta
17
+ lifecycle: active
18
+ trust:
19
+ level: core
20
+ confidence: high
21
+ human_review_required: false
22
+ install:
23
+ default: true
24
+ removable: false
25
+ ---
26
+
27
+ # /knowledge list
28
+
29
+ Shows everything currently held under `agents/memory/knowledge/`,
30
+ sorted by `created_at` ascending. Read-only by default; `--pin` and
31
+ `--unpin` mutate the `pinned` flag on a single ingest by id prefix.
32
+
33
+ ## Prerequisites
34
+
35
+ - Python 3.10+ on the host.
36
+ - `agents/memory/knowledge/` exists or is empty — the command treats
37
+ "empty" as a normal result, not an error.
38
+
39
+ ## Steps
40
+
41
+ ### 1. Parse the argument
42
+
43
+ ```
44
+ /knowledge list [--format=table|json] [--pin <id-prefix>]
45
+ [--unpin <id-prefix>]
46
+ ```
47
+
48
+ - `--format` defaults to `table` (ASCII; human-readable).
49
+ - `--pin` and `--unpin` are mutually exclusive in spirit; the CLI
50
+ accepts only one per call.
51
+
52
+ ### 2. Run the implementation
53
+
54
+ ```bash
55
+ python3 packages/core/installer/python/knowledge_ingest.py \
56
+ list [--format=...] [--pin <id-prefix>] [--unpin <id-prefix>]
57
+ ```
58
+
59
+ ### 3. Surface the result
60
+
61
+ **Table view** columns:
62
+
63
+ ```
64
+ ID DOCS CHUNKS BYTES PINNED REDACTED CREATED SOURCE
65
+ 01a2b3c4 12 47 318012 no yes 2026-05-25T08:14:02 /Users/maintainer/clients/acme
66
+ ```
67
+
68
+ **JSON view** — full manifest array, one object per ingest. Useful for
69
+ piping into `jq` or `/memory load` flows.
70
+
71
+ **Pin / unpin** — one-line confirmation:
72
+
73
+ ```
74
+ > ✅ pinned 01a2b3c4
75
+ > ✅ unpinned 01a2b3c4
76
+ ```
77
+
78
+ Pinning protects an ingest from LRU eviction when the 500 MB
79
+ namespace cap is crossed.
80
+
81
+ ### 4. Empty namespace
82
+
83
+ Print `(no ingests)` and offer the next step:
84
+
85
+ ```
86
+ > 1. /knowledge ingest <path> — point at a local folder, .zip, or file
87
+ ```
88
+
89
+ ## Safety
90
+
91
+ - Read-only by default; only `--pin` / `--unpin` mutate state, and
92
+ both edit a single flag on a single manifest file.
93
+ - The id prefix must be **unambiguous** — if it matches more than one
94
+ ingest, the command rejects with a structured error and asks for a
95
+ longer prefix.
96
+
97
+ ## See also
98
+
99
+ - [`/knowledge ingest`](ingest.md) — add a new ingest.
100
+ - [`/knowledge forget`](forget.md) — drop an ingest atomically.
101
+ - [`local-knowledge-ingestion`](../../../docs/contracts/local-knowledge-ingestion.md)
102
+ § Bounds — when LRU fires.
@@ -0,0 +1,75 @@
1
+ ---
2
+ name: knowledge
3
+ tier: 2
4
+ description: Knowledge orchestrator — routes to ingest, list, forget. Local-only file ingestion into the agent memory namespace.
5
+ cluster: knowledge
6
+ type: orchestrator
7
+ disable-model-invocation: true
8
+ suggestion:
9
+ eligible: true
10
+ trigger_description: "ingest local folder, add my customer files, point the agent at this folder, list ingested knowledge, forget that ingest"
11
+ trigger_context: "user wants to feed local files (folder, .zip, single doc) to the agent without OAuth connectors"
12
+ workspaces:
13
+ - agent-config-maintainer
14
+ packs:
15
+ - meta
16
+ lifecycle: active
17
+ trust:
18
+ level: core
19
+ confidence: high
20
+ human_review_required: false
21
+ install:
22
+ default: true
23
+ removable: false
24
+ ---
25
+
26
+ # /knowledge
27
+
28
+ Top-level orchestrator for the `/knowledge` family — the **local
29
+ knowledge ingestion** cluster. Single-user, single-machine, no OAuth,
30
+ no remote fetches. Feeds local files (folder · `.zip` · single PDF /
31
+ DOCX / XLSX / MD / TXT / image) into the existing memory namespace
32
+ under the `knowledge/` prefix.
33
+
34
+ Anchors: [`local-knowledge-ingestion`](../docs/contracts/local-knowledge-ingestion.md)
35
+ contract — input shapes, bounds, redaction defaults, storage layout.
36
+
37
+ ## Sub-commands
38
+
39
+ | Sub-command | Routes to | Purpose |
40
+ |---|---|---|
41
+ | `/knowledge ingest` | `commands/knowledge/ingest.md` | Walk a local path, redact, chunk, persist to `agents/memory/knowledge/<ingest-id>/` |
42
+ | `/knowledge list` | `commands/knowledge/list.md` | List existing ingests (table or JSON); pin / unpin by id prefix |
43
+ | `/knowledge forget` | `commands/knowledge/forget.md` | Drop a single ingest by id prefix (atomic, no partial state) |
44
+
45
+ Sub-command names match the locked contract in
46
+ [`docs/contracts/command-clusters.md`](../docs/contracts/command-clusters.md).
47
+
48
+ ## Dispatch
49
+
50
+ 1. Parse the user's argument: `/knowledge <sub-command> [args]`.
51
+ 2. Look up the sub-command in the table above.
52
+ 3. Load the body of the routed file and follow its `## Steps` section
53
+ verbatim with the remaining args.
54
+ 4. If the sub-command is unknown or missing, print the table above and ask:
55
+
56
+ > 1. ingest — point at a local folder, `.zip`, or file
57
+ > 2. list — show what's already ingested (`--pin` / `--unpin` to flag)
58
+ > 3. forget — drop an ingest by id prefix
59
+
60
+ ## Rules
61
+
62
+ - **Local-only.** Remote URLs (`http://`, `https://`, `s3://`, `gs://`,
63
+ `azure://`) are rejected at the input validator. Never fetch the
64
+ network from this cluster.
65
+ - **Bounds are non-negotiable** — see the contract. ≤ 1000 docs, ≤ 20 MB
66
+ per file, ≤ 500 MB namespace (LRU eviction at the namespace level).
67
+ - **Redaction defaults to ON.** Five PII classes (email, phone, IBAN,
68
+ credit card, SSN-shape) and five secret patterns (AWS, GitHub PAT,
69
+ OpenAI key, private-key blocks, generic high-entropy `api_key=...`
70
+ assignments) are replaced before storage. `--no-redact` exists for
71
+ trusted maintainer corpora; it never becomes the default.
72
+ - **Do NOT commit, push, or open a PR** unless the user explicitly asks.
73
+ - **Do NOT chain sub-commands.** One `/knowledge <sub>` per turn.
74
+ - If the user invokes `/knowledge` with no argument, **show the menu** —
75
+ do not guess which sub-command they meant.
@@ -65,7 +65,7 @@ PHASE_RE = re.compile(
65
65
  TITLE_RE = re.compile(r"^#\s+(?:Roadmap:\s*)?(.+?)\s*$", re.MULTILINE)
66
66
  EXCLUDE_NAMES = {"template.md", "README.md", "progress.md", "roadmaps-progress.md"}
67
67
  EXCLUDE_PREFIXES = ("open-questions",)
68
- EXCLUDE_DIRS = {"archive", "skipped"}
68
+ EXCLUDE_DIRS = {"archive", "skipped", "stubs"}
69
69
 
70
70
  # Frontmatter — minimal YAML block at the top of a roadmap. Used to hide
71
71
  # drafts (`status: draft`) from the dashboard. Anything else (no
@@ -23,7 +23,7 @@ install:
23
23
 
24
24
  # compress-memory
25
25
 
26
- > **Experimental.** Output-side caveman dialect did not meet kill-criterion in [`bench/reports/caveman-v1.md`](../../../bench/reports/caveman-v1.md) (`vs_terse` median −9.27 %). Input-side memory compression is orthogonal use case: savings target always-loaded memory budget, not reply stream. Treat ship-criterion as **per-target measurement**, not v1 verdict.
26
+ > **Experimental.** Output-side caveman dialect did not meet kill-criterion in [`internal/bench/reports/caveman-v1.md`](../../../bench/reports/caveman-v1.md) (`vs_terse` median −9.27 %). Input-side memory compression is orthogonal use case: savings target always-loaded memory budget, not reply stream. Treat ship-criterion as **per-target measurement**, not v1 verdict.
27
27
 
28
28
  ## When to use
29
29
 
@@ -39,7 +39,7 @@ schema_version: 1
39
39
  # CI guard: a release bump of `package.json` must update this value
40
40
  # in lockstep — see scripts/check_template_pin_drift.py (road-to-
41
41
  # portable-runtime-and-update-check P3.3).
42
- agent_config_version: "3.0.0"
42
+ agent_config_version: "3.1.1"
43
43
 
44
44
  # --- Project identity ---
45
45
  project: