@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.
- package/.agent-src/commands/agent-status.md +1 -1
- package/.agent-src/commands/analytics/prune.md +78 -0
- package/.agent-src/commands/analytics/show.md +107 -0
- package/.agent-src/commands/analytics.md +64 -0
- package/.agent-src/commands/knowledge/forget.md +104 -0
- package/.agent-src/commands/knowledge/ingest.md +122 -0
- package/.agent-src/commands/knowledge/list.md +102 -0
- package/.agent-src/commands/knowledge.md +75 -0
- package/.agent-src/scripts/update_roadmap_progress.py +1 -1
- package/.agent-src/skills/compress-memory/SKILL.md +1 -1
- package/.agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/.claude-plugin/marketplace.json +8 -1
- package/AGENTS.md +5 -4
- package/CHANGELOG.md +54 -222
- package/README.md +12 -2
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +164 -10
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +12 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +11 -4
- package/dist/mcp/mcp-cloudflare-catalogue.json +2 -0
- package/dist/mcp/registry-manifest.json +5 -3
- package/docs/architecture.md +1 -1
- package/docs/archive/CHANGELOG-pre-3.2.0.md +268 -0
- package/docs/benchmarks.md +4 -4
- package/docs/catalog.md +9 -2
- package/docs/contracts/CHANGELOG-conventions.md +20 -1
- package/docs/contracts/adr-mcp-runtime.md +1 -1
- package/docs/contracts/at-rest-encryption.md +146 -0
- package/docs/contracts/benchmark-corpus-spec.md +3 -3
- package/docs/contracts/benchmark-report-schema.md +5 -5
- package/docs/contracts/caveman-telemetry.md +4 -4
- package/docs/contracts/compression-default-kill-criterion.md +5 -5
- package/docs/contracts/cost-enforcement.md +1 -1
- package/docs/contracts/daily-workspace.md +137 -0
- package/docs/contracts/explain-modes.md +146 -0
- package/docs/contracts/host-agent-protocol.md +88 -0
- package/docs/contracts/local-analytics.md +148 -0
- package/docs/contracts/local-knowledge-ingestion.md +96 -0
- package/docs/contracts/mcp-beta-criteria.md +1 -1
- package/docs/contracts/mcp-cloud-scope.md +4 -4
- package/docs/contracts/mcp-registry-manifest.schema.json +1 -1
- package/docs/contracts/mcp-tool-inventory.md +1 -1
- package/docs/contracts/mcp-tool-stub-envelope.md +1 -1
- package/docs/contracts/measurement-baseline.md +6 -6
- package/docs/contracts/role-experience.md +121 -0
- package/docs/contracts/workspace-documents.md +140 -0
- package/docs/decisions/ADR-022-daily-workspace-decomposition.md +140 -0
- package/docs/decisions/ADR-023-host-agent-protocol.md +129 -0
- package/docs/decisions/ADR-024-workspace-v0-feature-floor.md +126 -0
- package/docs/decisions/ADR-025-workspace-chrome.md +119 -0
- package/docs/decisions/ADR-026-explain-mode-translation.md +117 -0
- package/docs/decisions/ADR-027-changelog-machine-vs-manual.md +129 -0
- package/docs/decisions/ADR-028-root-layout.md +147 -0
- package/docs/decisions/ADR-029-multi-workspace-deferred.md +122 -0
- package/docs/decisions/INDEX.md +8 -0
- package/docs/deploy/small-team-recipe.md +148 -0
- package/docs/deploy/team-deployment-posture.md +91 -0
- package/docs/getting-started-by-role.md +27 -0
- package/docs/getting-started.md +1 -1
- package/docs/guides/local-analytics.md +125 -0
- package/docs/guides/local-knowledge.md +127 -0
- package/docs/mcp-server.md +1 -1
- package/docs/parity/bench-ruflo.json +3 -3
- package/docs/parity/ruflo.md +1 -1
- package/docs/setup/mcp-client-config.md +1 -1
- package/docs/setup/mcp-cloud-endpoints.md +1 -1
- package/docs/setup/mcp-cloud-setup.md +2 -2
- package/docs/setup/mcp-r2-bootstrap.md +1 -1
- package/package.json +4 -2
- package/scripts/__pycache__/validate_frontmatter.cpython-312.pyc +0 -0
- package/scripts/_lib/__pycache__/__init__.cpython-312.pyc +0 -0
- package/scripts/_lib/__pycache__/agent_src.cpython-312.pyc +0 -0
- package/scripts/_lib/bench_caveman.py +2 -2
- package/scripts/_lib/bench_caveman_report.py +1 -1
- package/scripts/_lib/bench_cost.py +2 -2
- package/scripts/_lib/bench_report.py +2 -2
- package/scripts/_lib/changelog_eras.py +330 -0
- package/scripts/audit_mcp_tools.py +1 -1
- package/scripts/bench_baseline_ready.py +3 -3
- package/scripts/bench_compress_memory.py +4 -4
- package/scripts/bench_drift_check.py +2 -2
- package/scripts/bench_per_tool.py +2 -2
- package/scripts/bench_run.py +4 -4
- package/scripts/build_mcp_registry_manifest.py +2 -2
- package/scripts/mcp_server/__init__.py +1 -1
- package/scripts/mcp_server/catalog.py +1 -1
- package/scripts/mcp_server/consumer_tool_catalog.json +1 -1
- package/scripts/mcp_server/tools.py +1 -1
- package/scripts/memory_lookup.py +78 -1
- package/scripts/pack_mcp_content.py +6 -6
- package/scripts/release.py +93 -3
- 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.
|
|
42
|
+
agent_config_version: "3.1.1"
|
|
43
43
|
|
|
44
44
|
# --- Project identity ---
|
|
45
45
|
project:
|