Add server-data-ops delete agent (Context Intelligence session-data deletion) - #108
Draft
Diego Colombo (colombod) wants to merge 39 commits into
Draft
Add server-data-ops delete agent (Context Intelligence session-data deletion)#108Diego Colombo (colombod) wants to merge 39 commits into
Diego Colombo (colombod) wants to merge 39 commits into
Conversation
…hin module)
Build the server-data-ops tool the same way as the query tool: the logic
lives in the shared context_intelligence library, and the module is a thin
wrap over it.
Library (context_intelligence/client.py), on both CIClient and AsyncCIClient:
- session_summary(session_id) -> GET /sessions/{id}/summary (the preview facts)
- delete_session(session_id) -> DELETE /sessions/{id} (the result counts)
Same request build and CIClientError translation as cypher()/fetch_blob();
no workspace, no apply, no retry -- matches the server. A 404 (unknown
session) and 409 (still receiving data, or id ambiguous across workspaces)
keep their status code so the tool can explain them.
Module (modules/tool-server-data-ops/), sibling of the query tool: mount()
builds one shared ToolConfigResolver and mounts two thin tools. Each resolves
which server to talk to with the query tool's own resolve_query_connection
(reused unchanged: own sources config or the hook's destinations, works with
no hook, source= selection, fail-loud on ambiguity, list_sources to discover),
then calls the library. The module never reaches the server directly -- the
only path is through the library's client.
Proven: module tests 54 passed; repo suite 773 passed; ruff + pyright clean.
Part of context-intelligence session data delete (bundle, B1).
🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)
Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
Lean server-data-ops agent + companion skill driving the three approved delete scenarios (delete current session; find by theme/topic then delete; delete another user's session with an ownership warning). The agent reaches the server only through tool-server-data-ops; preview then explicit confirmation before any delete; the narrative overview is built from the root session's prompts and delegated to graph-analyst. Proven in a Digital Twin: the branch agent + branch tool + branch skill resolve via Gitea url_rewrite and a live session_summary call returned real seeded facts. Part of context-intelligence session data delete (bundle, B3). 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
The analysis and navigation behaviors each independently list the same three agents (graph-analyst, session-navigator, server-data-ops). The analysis behavior no longer imports the navigation behavior; each lists the agents itself, so they are two independent, equal copies. This registers the new server-data-ops agent so a user reaches it the same way as the others, and ships with no foundation change; the convergence eases the later transition. Descriptions updated to match. Part of context-intelligence session data delete (bundle, B4). 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…body A Digital Twin evaluation caught two real bugs, both from the agent not loading its own skill and improvising from its body: - All-servers completeness: a session can live on more than one server. The agent now checks every configured server, surfaces each one the session is on, deletes from each chosen server and verifies, and never reports the deletion complete while another server still holds it. (Previously it deleted from one of two servers and told the user 'done' -- a false success for a delete feature.) - Flow 1 folder-exclusion offer and Flow 2 root-prompt narrative (via graph-analyst) are now hard rules in the agent body, not skill-only steps the agent could skip. The three rules now live in the agent body so they hold even if the skill is not loaded; the skill keeps the detailed step order and now matches. Preview, the explicit confirmation gate, and the ownership warning are unchanged. Part of context-intelligence session data delete (bundle, B3). 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
Server now exposes GET /whoami, returning {"contributor_id": <github-id>}
(null when auth is disabled). This wires it through so the delete
workflow can resolve "who am I" and compare against a session's
created_by for ownership warnings.
- context_intelligence/client.py: add whoami() to CIClient (sync,
_http_get_strict) and AsyncCIClient (async, inline httpx GET), right
beside session_summary()/delete_session(), using the identical
request-build + CIClientError translation pattern. No retry, status
codes preserved.
- modules/tool-server-data-ops: add a third tool `whoami`
(whoami_tool.py, class WhoamiTool) mounted by the SAME mount() using
the SAME shared ToolConfigResolver as session_summary and
delete_session -- one config/resolver, server configuration can never
diverge across the three tools. execute() resolves the server exactly
like its siblings (list_sources, source= selection, fail-loud
ambiguity via resolve_query_connection/_connectable_pool), calls the
library whoami(), and returns {"contributor_id": ..., "source": ...}.
- Tests: unit tests for the library method (sync + async, mock
transport) in tests/test_client.py, and for the tool in
modules/tool-server-data-ops/tests/test_whoami_tool.py (happy path,
list_sources, source selection/ambiguity fail-loud, config fallback,
server error surfacing). Updated test_module.py's tool-count/name
assertions and shared-resolver invariant test to cover all three
tools (was hardcoded to two).
🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)
Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…der-exclusion offer, forbid raw-prompt narrative Three agent-behavior gaps exposed by a Digital Twin evaluation: 1. Ownership false positives: the agent warned "created by X, not you" even on the user's own sessions, because it had no way to know who the acting user actually was. Now resolves the acting user via the whoami tool (same server as the session), compares contributor_id to created_by, and only warns on a genuine mismatch. A null contributor_id (auth disabled) asks the user instead of guessing or warning. 2. Flow 1 folder-exclusion offer was silently skipped because it was gated on first proving the folder was filter-included -- something the agent cannot reliably determine. The offer is now unconditional: it always fires for current-session deletes, before deleting. 3. Flow 2 session-details narrative sometimes used a raw quoted prompt instead of a graph-analyst summary. Raw-prompt-quoting is now explicitly forbidden; the Summary line must come from delegating to graph-analyst, falling back to "not available" only if that delegation fails. Updated files: - agents/server-data-ops.md: added the whoami tool to the Tools list, rewrote the ownership Hard Rule and Flow 3 summary, made the folder-exclusion Hard Rule unconditional, and extended the narrative Hard Rule to forbid raw-prompt quoting. - skills/context-intelligence-server-data-ops/SKILL.md: added whoami to the tools section, rewrote "Resolving current user" to use whoami instead of injected context, rewrote Flow 3 step-by-step around the whoami comparison (including the null-contributor_id fallback), made the Flow 1 folder-exclusion step and its subsection unconditional, and added an explicit forbidden-shortcut note under "Building the narrative." No new scope: no hand-off, fresh-session, tombstone, or archive behavior was added. All previously-passing behavior (all-servers completeness, preview-then-confirm, impact statement, tool-only access, 404/409 handling, permanence) is unchanged. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
The server-data-ops agent mounts BOTH tool-server-data-ops and tool-context-intelligence-query, so a "whoami" tool could not exist in both modules -- two tools with the same name in one agent collide. whoami is also generally useful to any agent mounting only the query module (e.g. graph-analyst needs "who am I" to scope "my sessions"), so the read (query) module is now its single home. - modules/tool-context-intelligence-query: add whoami_tool.py (identical behavior, ported docstring references from SessionSummaryTool/DeleteSessionTool parity to GraphQueryTool/BlobReadTool parity). Mount it as the third tool in mount(), sharing the module's single ToolConfigResolver. Ported tests/test_whoami_tool.py and updated tests/test_module.py's three-tool assertions (mount count, tool names, shared-resolver invariant across all three tools). - modules/tool-server-data-ops: remove whoami_tool.py and its mount() wiring; the module is back to two tools (session_summary, delete_session) sharing one resolver. Updated tests/test_module.py back to two-tool assertions and removed tests/test_whoami_tool.py. The server-data-ops agent still has whoami available because it already mounts tool-context-intelligence-query. - context_intelligence/client.py whoami() is untouched (shared library used by both modules). Verified: query module 213 tests pass, server-data-ops 54 tests pass, repo-root suite 783 tests pass, ruff/pyright clean on both modules. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
… use it whoami moved from tool-server-data-ops into tool-context-intelligence-query in 5b3252d. Update the docs/wording that still pointed at the old module, and teach the graph-navigation skill (and graph-analyst) to use it. - agents/server-data-ops.md: fix the tool attribution for whoami -- now credited to tool-context-intelligence-query. No behavior change; the whoami-based ownership rule itself is untouched. - skills/context-intelligence-graph-query/SKILL.md: add a short 'Resolving "my" -- use whoami, don't guess' subsection in the scoping section, teaching how to resolve the acting user via whoami and filter created_by against contributor_id, including the null-contributor_id (auth disabled) case. - agents/graph-analyst.md: add a brief note that whoami is available (from tool-context-intelligence-query) to resolve the acting user's identity for "my"-scoped questions, pointing at the skill for the full pattern. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…h-analyst narrative gate
Two targeted behavior fixes found by a Digital Twin re-eval:
- Flow 1 (delete current session) was being misrouted into a find-by-id
lookup whenever the user supplied a session id alongside phrasing like
"my current session" — causing the folder-exclusion offer to be
silently skipped for two eval rounds in a row. Flow 1 routing is now
decided by the user's phrasing ("my current session", "this session",
"this working directory", etc.), never by whether an id was given; a
supplied id no longer downgrades the request out of Flow 1. Mirrored
into the skill's Flow 1 trigger paragraph.
- The graph-analyst narrative for a session details block fired once and
was silently skipped once on identical requests — not deterministic
enough. Made it an explicit non-skippable gate in the agent body (MUST
delegate before presenting a details block or deleting; MUST NOT
proceed without either a real narrative or an explicit "narrative not
available"), and split the skill's Flow 2 step 3 into two ordered
steps (session_summary for facts, then the mandatory graph-analyst
delegation) so the sequence find -> narrative -> present -> confirm ->
delete is unambiguous.
No other behavior touched: whoami-based ownership comparison, all-servers
completeness, preview, confirmation gate, tool-only access, and 404/409
handling are unchanged.
🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)
Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…on offer front-loaded
Flow 1 ("delete my current session") now runs in a strict, explicit order in
both agents/server-data-ops.md and skills/context-intelligence-server-data-ops/SKILL.md:
1. RESOLVE - take the current session id from Amplifier's own runtime context
(the `Session ID` field in status context), never from the user typing one.
A typed id never replaces the runtime one for a "this session" request.
2. PROVE - call session_summary on that id and show the user the proof: the
resolved root session id, created_by (confirmed against the caller's own
identity via whoami), working_dir, and last_change (flagged if <1 min old).
If session_summary 404s on every configured server, STOP and say so plainly
- never delete an unresolved or absent session.
3. OFFER THE FOLDER EXCLUSION - mandatory, unconditional, front-loaded, before
the impact statement, confirmation, or delete. Skipping this offer in
Flow 1 is now stated explicitly as a defect, not a shortcut.
4. STATE THE IMPACT - what will be permanently removed, and from which
server(s).
5. CONFIRM - explicit, strong confirmation naming session + server(s).
6. DELETE, then VERIFY, on every server - all-servers completeness, unchanged.
Also adds a short rule near the top of the agent body making the
resolve-from-Amplifier-context requirement explicit and impossible to miss.
No new tools or APIs added - only session_summary, delete_session, whoami,
graph_query, delegate, and load_skill, all of which already existed. No new
scope: no hand-off, fresh-session, tombstone, or archive concepts introduced.
Flow 2 (find-by-theme, graph-analyst narrative gate), Flow 3 (not-owned,
whoami ownership compare), all-servers completeness, preview/confirmation
order, and tool-only access are unchanged (verified byte-identical via diff
against the prior revision).
🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)
Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…ollows them The agent body had grown to ~230 lines of overlapping, repeated rules and meta-commentary about prior eval failures. That wall was the cause of the skipped steps (exclusion offer, narrative delegation): the model satisficed under the load. Rewrote to ~115 lines — each rule stated once, the three flows as tight ordered checklists. No behavior added or removed; the instructions are now scannable and followable. Part of context-intelligence session data delete (bundle, B3). 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
The skill had grown to 334 lines of overlapping rules, repeated emphasis
("MANDATORY", "UNCONDITIONAL", "this is a defect"), and meta-commentary
about prior eval rounds. Rewrote to 199 lines matching the already-leaned
agent body (a67fecb): each rule stated once, the three flows as tight
ordered checklists, shared concepts (session id / user identity
resolution, multi-server handling) factored into single reference
sections instead of repeated per-flow. Dropped the open "folder-exclusion
timing" design question and duplicate design-notes section (non-behavioral,
already permitted to trim). No behavior added or removed.
Part of context-intelligence session data delete (bundle, B3).
🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)
Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
Bug: ApiKeyAuth.headers() raises a bare ValueError when the api_key is
unusable (empty, or the "[REDACTED]" redaction sentinel). AsyncCIClient's
methods called self._strategy.headers() INSIDE the request try: block, so
that ValueError fell through to the same
except (ValueError, json.JSONDecodeError) handler used for a genuinely
malformed JSON response, and was reported as CIClientError(error_type=
"decode_error", "malformed JSON from {url}") -- even when no request was
ever sent and the server was healthy. Confirmed live: a redacted key
produced "malformed JSON from http://.../sessions/..." while the server
returned HTTP 200.
Fix: add error_type="auth_error" and hoist auth-header computation out of
every request try: block, in both CIClient (sync) and AsyncCIClient
(async):
- CIClient._auth_headers(url) / AsyncCIClient._auth_headers(url): new
helper that calls self._strategy.headers() and converts a ValueError
into CIClientError(error_type="auth_error", "unusable credential for
{url}: ..."), computed BEFORE any request is attempted.
- Updated call sites (6 sync + 6 async): cypher, list_blob_keys,
fetch_blob, session_summary, delete_session, whoami.
- Left the existing except (ValueError, json.JSONDecodeError) handlers on
resp.json() untouched -- a genuinely malformed 200 body still classifies
as decode_error, and a real non-2xx status still classifies as
http_status.
- Documented the new error_type in CIClientError's comment, the
_http_get_strict/_http_delete_strict docstrings, and every public
method's Raises section.
context_intelligence/auth.py is unchanged -- ApiKeyAuth.headers() already
raised the correct ValueError; the bug was purely in how client.py
classified it.
Tests (tests/test_client.py): two new classes,
TestCIClientErrorClassification (sync) and
TestAsyncCIClientErrorClassification (async), covering:
(a) an empty api_key AND the literal "[REDACTED]" sentinel surface as
error_type="auth_error" (never decode_error) for cypher, fetch_blob,
session_summary, delete_session, and whoami, with the underlying
transport proven never invoked (mock_*.assert_not_called()) --
parametrized across both bad-key shapes;
(b) a genuinely malformed JSON body from a real 200 response still
classifies as decode_error, for session_summary, delete_session, and
whoami;
(c) a real 401 still classifies as http_status, for session_summary and
whoami.
Verified:
- uv run pytest tests/ -- 130/130 new-file tests pass (813/813 repo-root
tests pass)
- uv run ruff check . / ruff format --check . / uv run pyright -- clean
- modules/tool-context-intelligence-query (the other consumer of
CIClientError/error_type): 213/213 pass against this branch's code
- modules/tool-server-data-ops (same): 54/54 pass against this branch's
code
🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)
Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…raction rule Two decisions from a real Digital Twin run: 1. The candidate narrative (Flow 2 Summary line) is now built by the server-data-ops agent itself via graph_query against the session's root prompts, instead of delegating to graph-analyst. The narrative is a small, focused synthesis task that doesn't need graph-analyst's full data-navigation surface, and a nested delegate would lose content the same way the root session loses a sub-agent's internal work. The hard rule is unchanged: synthesized overview in the agent's own words, never a raw/verbatim prompt quote, never a from-memory guess, "not available" if graph_query has nothing usable. `delegate` stays in the tools list for other uses but is no longer used for the narrative. 2. Added an explicit rule (agent body + one mirrored line in the skill intro) that this is a direct, interactive conversation: the session-details preview, the folder-exclusion offer, the impact statement, and the confirmation request must always appear in the agent's own visible, user-facing turn -- never assumed to be relayed by another agent. Flow 1's exclusion offer and Flow 3's ownership warning are reworded to make explicit that the agent shows these to the user and waits for a response, rather than treating them as internal notes. No other scope changes. Untouched: current-session resolution from the runtime Session ID + session_summary proof, the front-loaded folder-exclusion offer, all-servers completeness, preview/confirm gate, whoami ownership compare, 404/409 handling, tools-only access. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…eep self-built narrative The prior commit (f287bde) went too far: it dropped graph-analyst entirely, having this agent run graph_query directly for both finding sessions and building the narrative. The user clarified the correct split: - SEARCH (Flow 2 step 1): finding a session by topic/content/date/criteria genuinely needs graph-analyst's data-navigation skills. Delegate to it — a data-fetch delegation, not a hand-off of the conversation. Candidate results (ids + key facts) come back to this agent, which keeps driving the flow. Trivial direct lookups (user names an exact session id) skip the delegation and call session_summary directly. - NARRATIVE (Flow 2 step 2): building a short root-prompt overview of one already-identified session does not need graph-analyst's full surface. This stays exactly as f287bde left it — the agent builds it itself via graph_query against root-session prompts only, synthesized in its own words, "not available" if nothing usable comes back. Added an explicit "never delegate this step to graph-analyst" line in both files so the two are not re-merged again by accident. Tools list updated to match: `delegate` is for search delegation only, `graph_query` is for the narrative and for direct lookups. No other scope changes. Untouched: Flow 1 (resolve + prove + mandatory exclusion offer), Flow 3 (whoami ownership), all-servers completeness, preview/confirm gate, 404/409 handling, tools-only access, the Change-2 direct-interaction rule. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…his working directory
Adds a second S1 flavor to the delete agent: instead of just the current
session, find and delete every root session pushed from the current working
directory, in this order — exclusion first, then find (delegate to
graph-analyst, all-servers), then propose (todo list, one item per session),
then delete all (normal preview -> impact -> confirm -> delete -> verify per
session, ownership check still applies).
- agents/server-data-ops.md: new "Flow 1-folder" section, updated
description/Role/Tools for four flows, added tool-todo to frontmatter tools
(agent-scoped, not added to a shared behavior).
- skills/context-intelligence-server-data-ops/SKILL.md: matching "Flow
1-folder" section with exact step wording, a "Current working directory"
key concept, and disambiguated the Flow 1 trigger phrases ("this session")
from the Flow 1-folder ones ("this working directory") so a folder-wide
request no longer gets misrouted to the single-session flow.
Flow 2, Flow 3, all-servers completeness, preview/confirm, 404/409, and the
tools-only rule are unchanged.
🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)
Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…lavor Flow 1-folder (added in b551839) was named as if it were a variant of Flow 1 (delete the current session). That's the wrong classification: Flow 1's defining trait is the CURRENT session resolved from runtime; this flow finds sessions by CRITERIA (working_dir = this folder AND created_by = me), which is exactly Flow 2's find-by-criteria shape. The only thing it borrows from Flow 1 is the folder-exclusion offer, and only because it's the user's own folder being pushed. Renamed to "Flow 2-folder — clean up everything pushed from this working directory (folder + mine)" and moved it to sit after Flow 2 (as a variation of it) instead of after Flow 1, in both the agent and its companion skill. Added a one-line classification note up front, and reframed step 2 explicitly as "the S2 search, by criteria." Kept the approved step order: apply the folder exclusion first, then run the S2 search, then propose the list via todo, then delete all with per-session preview -> impact -> confirm -> delete -> verify and ownership check. Updated all cross-references (todo-tool bullet, Key Concepts heading, Flow 1's routing text, Flow 3's "runs inside" list) from Flow 1-folder to Flow 2-folder. Trigger routing is otherwise unchanged: "this session"/"my current session" -> Flow 1; "this folder"/"this working directory"/"uploaded from here" -> Flow 2-folder; topic/date/server description -> plain Flow 2. Frontmatter, direct-interaction rule, all-servers completeness, self-built narrative rule, Flow 1, Flow 3, 404/409 handling, and the tools-only rule are all unchanged. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
The folder exclusion is a local push-config setting on this machine — it only stops future pushes from the current local context. Add one rule clarifying it applies only to Flow 1 and Flow 2-folder (mine AND from here), and explicitly does not apply to plain Flow 2 (found by topic, may be elsewhere) or Flow 3 (not yours). Mirrored in the skill's Key Concepts. No flow logic changed — wording clarification only. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…ools
Two tool-surface changes for the delete agent (server-data-ops):
1. whoami without graph_query
- Moved WhoamiTool out of tool-context-intelligence-query's own
package into the shared context_intelligence library
(context_intelligence/whoami_tool.py), since it is now mounted by
TWO independent modules with no code duplication.
- tool-context-intelligence-query still mounts graph_query + blob_read
+ whoami (imported from the shared location) -- graph-analyst is
unaffected.
- tool-server-data-ops now also mounts whoami (session_summary +
delete_session + whoami), imported from the same shared class.
- agents/server-data-ops.md frontmatter no longer lists
tool-context-intelligence-query at all, which drops graph_query AND
blob_read from the agent. Its tools are now: tool-delegate,
tool-server-data-ops, tool-skills, tool-todo. All searching now must
go through graph-analyst via delegation, per the existing Flow 2
design (agent body prose untouched -- separate pass).
- Moved the whoami test suite to the repo-root tests/ (shared-library
tests, alongside test_tool_resolver.py etc.) and updated patch
targets from amplifier_module_tool_context_intelligence_query.whoami_tool
to context_intelligence.whoami_tool.
- Added amplifier-core as a root dev dependency (+ pyright venv
config) since the shared library now imports amplifier_core.models.
2. No file-write tools for the delete agent
- Investigation: server-data-ops.md's frontmatter never declared any
filesystem module. write_file/edit_file (tool-filesystem) and
apply_patch (tool-apply-patch) arrive purely by INHERITANCE --
amplifier-foundation's own root bundle.md mounts tool-filesystem as
a base tool, and amplifier-bundle-filesystem's apply-patch.yaml
(also composed by foundation) mounts tool-apply-patch. The
delegate/session-spawner's default policy is additive inheritance:
a spawned agent gets everything its parent has unless the PARENT's
own tool-delegate config excludes it (agent-side declarations can
only ADD tools back, never restrict what's inherited -- confirmed
against amplifier_app_cli/session_spawner.py's _filter_tools()).
- Fix: behaviors/context-intelligence-analysis.yaml (the layer that
declares graph-analyst/session-navigator/server-data-ops together)
now configures tool-delegate's settings.exclude_tools to
[tool-delegate, tool-filesystem, tool-apply-patch]. Any agent that
genuinely needs filesystem access keeps it by declaring the module
explicitly in its own frontmatter (explicit declarations always win
over parent-side exclusion) -- graph-analyst and session-navigator
already did; context-intelligence-tool-designer did not (it uses
read_file/write_file per its own body) so it now explicitly
declares tool-filesystem too.
- Scope note (important, left for reviewer sign-off): this exclusion
is deliberately placed in context-intelligence-analysis.yaml, NOT in
context-intelligence-navigation.yaml. The navigation behavior is
composed directly into amplifier-foundation's own root bundle.md,
so any tool-delegate config change there would silently alter
default tool inheritance for every foundation-based session across
the whole ecosystem. The analysis/design/full-bundle path is only
reached when a session explicitly opts into this bundle's richer
capability layer, which is a proportionate place to enforce this
agent's own security posture. A session that composes ONLY
amplifier-foundation's default navigation layer (bare foundation,
no explicit context-intelligence-analysis/design) can still spawn
server-data-ops with full write access -- closing that residual gap
needs either a foundation-level change (out of scope for this repo)
or a session-scoped enforcement mechanism such as an
auto-activated mode (needs agent body-prose changes, explicitly
out of scope for this pass per the task).
- read_file is also excluded as an unavoidable side effect: tool-
filesystem registers read_file/write_file/edit_file from one
mount() call with no per-sub-tool exclusion granularity.
Testing:
- modules/tool-context-intelligence-query: 195/195 tests pass (verified
against local source via a temporary [tool.uv.sources] path override,
reverted before commit -- this repo's own
test_bundle_is_not_a_uv_path_source guards against committing it).
- modules/tool-server-data-ops: 54/54 tests pass (same verification).
- repo-root tests/ (shared context_intelligence library, incl. the
relocated test_whoami_tool.py): 831/831 pass.
- tests/dtu/test_tool_delegate_composition.py (Group D): still passes.
- ruff check / ruff format --check / pyright: clean in both modules and
at the repo root.
🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)
Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
a897c2d put settings.exclude_tools on tool-delegate inside
behaviors/context-intelligence-analysis.yaml to keep server-data-ops (the
delete agent) from inheriting write_file/edit_file/apply_patch. That is a
behavior-wide restriction: it applies to every agent that behavior
composes (graph-analyst, session-navigator, server-data-ops), and forces
any agent that legitimately needs those tools to re-declare them just to
opt back in. Tools/restrictions should be registered by the CONSUMING
agent, never shared/restricted broadly via a behavior.
1. Revert the behavior-level restriction
- behaviors/context-intelligence-analysis.yaml: removed the
exclude_tools config added to tool-delegate in a897c2d. The file is
now byte-for-byte identical to its pre-a897c2d state (default
additive tool inheritance restored; no behavior-wide subtraction).
- agents/context-intelligence-tool-designer.md: kept its explicit
tool-filesystem declaration (still correct -- this agent genuinely
needs read_file/write_file for its Step 2.1 confirmation gate) but
reworded the comment, which explained the declaration as
compensating for the now-reverted exclusion.
2. Agent-scoped lockdown for server-data-ops
- New module modules/hook-server-data-ops-lockdown/: registers a
tool:pre handler that returns HookResult(action="deny") for exactly
write_file, edit_file, apply_patch, and graph_query, and
HookResult(action="continue") for everything else. Packaging mirrors
modules/tool-server-data-ops/ (pyproject.toml shape, entry point,
dev dependency group, pytest/pyright/ruff config).
- Verified against amplifier-core docs before writing the handler:
core:docs/contracts/HOOK_CONTRACT.md confirms the tool:pre event data
dict carries the tool name under "tool_name" (its own worked example:
data.get("tool_name") not in [...]) and a denial is
HookResult(action="deny", reason=...). core:docs/HOOKS_API.md
confirms HookResult.action is a Literal including "deny" and
reason: str | None. Both cited inline in the module docstring.
- agents/server-data-ops.md: declares the hook under a new `hooks:`
key (sibling to `tools:`, same source-URI pattern as the module's
other declarations). Agent body Flow prose is untouched.
- Unit tests (18, all passing): denies each of the 4 tools with the
exact reason string; allows session_summary, delete_session, whoami,
delegate, read_file, load_skill, todo; allows a data dict with no
tool_name key; mount() registers on "tool:pre" with priority=10 and
returns a working cleanup callable.
Testing:
- modules/hook-server-data-ops-lockdown: 18/18 tests pass; ruff check,
ruff format --check, and pyright all clean.
- repo-root tests/: 831/831 pass (unaffected).
- tests/dtu/test_tool_delegate_composition.py (Group D): still passes.
- repo-root ruff check / ruff format --check / pyright: clean.
- Pre-existing, unrelated to this change: modules/tool-server-data-ops
and modules/tool-context-intelligence-query fail to import locally
because their pinned `amplifier-bundle-context-intelligence @
git+...@main` dependency resolves against the remote main branch,
which lags the whoami_tool.py / client.py symbols already committed
to this local branch in earlier commits (a897c2d itself noted
verifying these only via a temporary, reverted-before-commit
[tool.uv.sources] override). Neither module was touched by this
change.
🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)
Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
… skill The agent's frontmatter already dropped tool-context-intelligence-query and a lockdown hook already denies graph_query for this agent, but the body and skill prose still described the agent building narratives itself via graph_query. Update both to match reality: search and narrative both come from delegating to graph-analyst. - Flow 2 / Flow 2-folder: merge search + narrate into one delegated step — graph-analyst now returns a synthesized overview alongside each candidate, so the agent presents it instead of building it via graph_query. - Tools list: remove the stale graph_query bullet in both files; note the lockdown hook denies direct graph access, write_file, edit_file, and apply_patch for this agent. - No behavior change beyond wording — Flow 1, Flow 3, exclusion scope, all-servers completeness, preview/confirm, and 404/409 handling untouched. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…h_query Bug (proven in a DTU eval): hook-server-data-ops-lockdown is declared in server-data-ops's own frontmatter (hooks:), but hook inheritance from a parent session to a delegated child is ADDITIVE BY DEFAULT -- the same rule as tool inheritance. So when server-data-ops delegated search to graph-analyst, graph-analyst's spawned session ALSO inherited this hook and its own legitimate graph_query calls got denied. Flow 2/2-folder failed entirely because search never ran. Verified before fixing: - server-data-ops's own tools: list does not (and, per commit a897c2d, deliberately does not) declare tool-context-intelligence-query, so it never has graph_query available to call itself -- every graph_query in the DTU trace was graph-analyst's own call, not server-data-ops's. - core:docs/contracts/ORCHESTRATOR_CONTRACT.md's reference tool:pre emit call, and HOOK_CONTRACT.md's field table, both show the event's documented payload carries only tool_name/tool_input -- no session or agent identity. So a handler receiving (event, data) cannot itself distinguish "server-data-ops's own call" from "a descendant session's call" -- ruling out an in-handler session check as a fix. Fix: session-scope the WHOLE hook (not just graph_query) at the delegation boundary, where the actual inheritance decision is made. agents/server-data-ops.md's own tool-delegate entry now sets settings.exclude_hooks: [hook-server-data-ops-lockdown], mirroring the existing settings.exclude_tools precedent in behaviors/context-intelligence-analysis.yaml. This stops the hook from being composed onto any session server-data-ops spawns, while it stays fully in force for server-data-ops's own tool calls (its hooks: declaration is untouched). No change to DENIED_TOOLS -- the fix lives in composition, not in the deny list. This also corrects the write_file/edit_file/apply_patch denials, which were equally (if harmlessly, since graph-analyst/session-navigator are read-only) leaking subtree-wide before this fix -- they are now properly scoped to server-data-ops's own session too. Docstring corrected: the hook module's docstring previously claimed "It has no effect on graph-analyst, session-navigator... regardless of how tool inheritance evolves" -- false without the exclude_hooks companion setting. Rewritten to document the subtree leak, the fix, and why an in-handler identity check isn't possible, with contract citations. Tests: added TestSessionScopeComposition to modules/hook-server-data-ops-lockdown/tests/test_module.py, parsing agents/server-data-ops.md's frontmatter to verify (a) the hook is still declared for server-data-ops's own session, (b) tool-delegate's settings.exclude_hooks names this hook's own module id, and (c) tool-context-intelligence-query still is not among server-data-ops's own tools (graph_query stays unreachable to it directly). Verified the new composition test actually catches the regression by reverting the agent frontmatter change and re-running (1 failure, as expected) before restoring it. Added PyYAML>=6.0 as an explicit dev dependency for this parsing (matches the version floor already used at repo root). Testing: 21/21 tests pass (18 pre-existing + 3 new), ruff check clean, ruff format clean, pyright 0 errors/0 warnings. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
… scope Flow 1's exclusion-offer step already showed the correct destinations.<name>.exclude push-filter setting, but a DTU eval showed the model conflating it with excluding sub-sessions from the delete scope. Make the framing explicit in both files: state up front that this is the destination push filter on working_dir, and add a guard line that deletion always removes the whole session graph regardless of this setting. Flow 2-folder references "same as Flow 1 step 3" in both files, so it inherits the fix without duplication. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
server-data-ops's own tool-lockdown hook (hook-server-data-ops-lockdown) denies write_file/edit_file/apply_patch/graph_query for its OWN tool calls, but it is intentionally scoped (via tool-delegate's settings.exclude_hooks) to NOT apply to sessions it delegates to -- that scoping is required so graph-analyst's own graph_query calls aren't wrongly denied. Without a delegation allowlist, that same scoping meant server-data-ops could delegate a file-write to ANY other agent (e.g. foundation:file-ops) and have it succeed unchecked. A DTU eval proved exactly this: server-data-ops delegated a settings.yaml edit to foundation:file-ops, and file-ops wrote the file, bypassing the lockdown entirely. Fix: add a top-level `agents:` allowlist to server-data-ops.md's own frontmatter (sibling of tools:/hooks:, recognized by amplifier_foundation.bundle._dataclass._load_agent_file_metadata and forwarded to amplifier-app-cli's agent_config.merge_configs / session_spawner.py's live-registry reconciliation), restricting delegation to exactly context-intelligence:graph-analyst -- the only agent server-data-ops's own flows ever delegate to. The allowlist filter does an exact-string `k in agent_filter` check against the parent's composed agent-roster keys, which are namespaced in this bundle (behaviors/context-intelligence-analysis.yaml and context-intelligence-navigation.yaml both register agents as "context-intelligence:graph-analyst" / "context-intelligence:server-data-ops"), so the allowlist entry must use that same namespaced form. Adds TestDelegationAllowlist to the lockdown hook's test module, parsing server-data-ops.md's frontmatter to assert the allowlist exists and is exactly ["context-intelligence:graph-analyst"] -- verified to fail when temporarily widened to "all" and to pass again on revert. Agent body prose is untouched; a separate pass reframes the exclusion wording. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
Drop TestSessionScopeComposition and TestDelegationAllowlist: they parsed the agent .md YAML and asserted the strings we typed, proving only 'the file says what we wrote' -- false confidence, failing only if someone edits the same line the test reads. The real guarantees they gestured at (the lockdown hook does not leak into graph-analyst's delegated session; server-data-ops cannot hand a file-write to another agent) are behavioural properties, proven in the DTU security-validation profile, not by grepping a file. Keep the genuine handler behavioural tests (deny the four lockdown tools, allow everything else). Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
A behavioral DTU test proved the `agents:` frontmatter allowlist on
server-data-ops does NOT block delegation-bypass when the agent runs as
the ROOT agent: with no parent session to apply a parent-side allowlist
filter, server-data-ops called delegate(agent="foundation:file-ops") and
that delegate wrote /root/work/probe.txt to disk (verified). The
allowlist is only enforced by the app-layer spawn capability when a
PARENT spawns THIS agent; as the root/direct agent there is no such
filtering step.
Move the restriction into hook-server-data-ops-lockdown's `tool:pre`
handler, which fires on server-data-ops's own tool calls regardless of
root-vs-child:
- Extend `_deny_lockdown_tools` to deny any `delegate` call whose target
agent (tool_input["agent"]) is not exactly
"context-intelligence:graph-analyst" -- the only agent server-data-ops
needs to reach (for search).
- Field name verified against tool-delegate's own execute():
`agent_name = input.get("agent", "").strip()`, and against the
documented tool:pre contract (tool_input IS tool_call.input).
- Allowed-agent string verified against
behaviors/context-intelligence-analysis.yaml's own roster registration
(`context-intelligence:graph-analyst`, matching server-data-ops's
existing `agents:` allowlist entry).
- Fail closed: a delegate call with a missing or empty `agent` field
(e.g. a resume-by-session_id call) is denied, not allowed -- it cannot
be confirmed to target the allowed agent.
- New constant ALLOWED_DELEGATE_AGENT is the single source of truth for
the allowed target.
The existing four-tool DENIED_TOOLS deny (write_file, edit_file,
apply_patch, graph_query) is unchanged. The agent's own `agents:`
frontmatter allowlist is left as-is for defense-in-depth (not touched
this pass).
Tests: added TestDelegateTargetLockdown (8 new cases: allowed target
passes, 5 disallowed targets denied incl. bare "graph-analyst", missing
agent field denied, empty agent field denied, missing tool_input denied,
regression guard that the original four tools still deny). Removed
"delegate" from the old generic "allows every other tool" parametrize
list since it now has dedicated, non-trivial behavior. 28/28 tests pass
(up from 16). ruff format/check clean, pyright clean (module's own venv).
🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)
Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…the single delegation control The frontmatter agents: allowlist was overkill and, worse, ineffective for the actual usage: it is only enforced when a PARENT spawns this agent, so when server-data-ops runs as the root/direct interactive agent there is no parent to apply it -- a DTU test proved it did NOT block delegate(agent=foundation:file-ops) (the sub-agent wrote a file to disk). The real control is hook-server-data-ops-lockdown, which now gates the delegate tool itself (deny any target except graph-analyst) on this agent's own calls, root or child. One mechanism that actually works beats two where one gives false confidence. Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
- graph-analyst.md: replace meta.description to drop both <example> blocks (rejected under description-authoring-principles V3) and remove the 4x-repeated graph-analyst→session-navigator fallback rule, cutting description from 478 to ~191 tokens. - session-navigator.md: replace meta.description to drop the <example> block (its content was operational CONTEXT_INTELLIGENCE_ROOT procedure, already present in the agent body under "Root resolution — MANDATORY FIRST STEP") and the duplicated "not called directly" statement. - context-intelligence-design-facilitator.md: add tool-filesystem to tools: (verbatim entry matching context-intelligence-tool-designer.md, no allowed_write_paths) so the agent can write domain-concepts.md, domain-signals.md, and handoff.md without relying on inherited FS access from a parent session. No changes to agents/server-data-ops.md, behaviors, or modules. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
- README: drop bare 'pip install pyyaml' in favor of 'uv pip install pyyaml' (readme_pip_install needs_work). - README: document that the standalone install flow intentionally omits --app (bundle use selects a dedicated config rather than layering onto the active app), recording the reasoning per the validator's guidance instead of appending --app where it would be semantically wrong (readme_missing_app_flag). - Regenerate bundle.dot / bundle.png (was stale) via the foundation validate-bundle-repo overview regen. Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…y-only
Comments-only pass across the delete feature's production code -- no
logic, signatures, or tests changed (verified via AST diff with
docstrings stripped: identical). Trims prose-heavy comment/docstring
blocks that accreted during iteration down to short module docstrings
plus terse why-comments, per the repo's self-explanatory-code standard.
- agents/server-data-ops.md: condensed the two frontmatter YAML comment
blocks (exclude_hooks 'matched pair' + agent-scoped lockdown) from
~31 comment lines to ~10. Agent body instructions untouched.
- hook-server-data-ops-lockdown/__init__.py: the module docstring was a
126-line narrative including DTU-eval incident history ('SUBTREE LEAK,
found via a DTU eval...', 'DELEGATE-TARGET LOCKDOWN, added after a
behavioral DTU test proved...'). Condensed to a 27-line docstring plus
short why-comments on DENIED_TOOLS/ALLOWED_DELEGATE_AGENT and the
handler/mount docstrings.
- tool-server-data-ops/__init__.py, delete_session_tool.py,
session_summary_tool.py, whoami_tool.py: condensed module docstrings
that re-explained resolve_query_connection()'s selection algorithm
(already documented at its source in tool_resolver.py) down to a
pointer + the genuinely load-bearing facts (permanent/no-preview,
read-only, why WhoamiTool is shared).
- context_intelligence/client.py: reviewed only the lines this branch
added. Removed the 'was the original bug' decision-history sentence
from AsyncCIClient._auth_headers's docstring, and condensed the
duplicated 'NOTE: headers is computed by the caller...' explanation in
_http_get_strict/_http_delete_strict and the CIClientError.error_type
attribute comment to their essential why.
Verification: ruff format + ruff check + pyright clean in each module's
own venv (root repo, hook-server-data-ops-lockdown,
tool-server-data-ops); full root test suite (831 tests) and both
module test suites green.
🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)
Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
agents/server-data-ops.md and skills/context-intelligence-server-data-ops/SKILL.md used 'Flow 1', 'Flow 2', 'Flow 2-folder', 'Flow 3' as section labels -- numbering from internal (non-shipping) design docs that a reader of the shipped repo has no way to resolve. Renamed section headers to describe the behavior instead of a number: - Flow 1 -> Delete the current session - Flow 2 -> Find a session by description, then delete - Flow 2-folder -> Clean up everything pushed from this working directory (yours, from here) - Flow 3 -> Ownership check (before deleting any found or named session) Rewrote every in-text cross-reference to name the behavior it points at instead of a flow number (e.g. 'run the Flow 3 check' -> 'run the ownership check'). No behavioral change: tool names, settings keys, step ordering, and guardrails are all unchanged -- this is wording only. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
Runnable amplifier-digital-twin profile that proves the delete/session-summary seam and the delete agent's lockdown: log a real session, preview + delete it via the server-data-ops agent, verify it is gone on the server (404), and prove the agent cannot write files or delegate a write to another agent. Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…o restart Part of the delete feature (Flow-1 'stop the bleeding'): let the running session STOP forwarding a folder to a destination the moment its exclude lands in settings.yaml, without a restart — and have every sub-session spawned afterward inherit the same filter. - HookConfigResolver.update_destinations(): replace destinations + invalidate cache. - apply_active_dispatchers(): reusable match_key -> select_active -> build -> set_dispatchers (drain-safe), factored out of on_session_ready. - reapply_ingestion capability + root-session tool: re-read settings.yaml, re-route the running session's dispatchers, and patch coordinator.session.config's hook entry so future spawned sub-sessions inherit the change (bundle-only; reached via the coordinator the hook already holds). - verify_ingestion_consistency capability: fail-loud live-vs-disk exclude compare (both directions). - 23 new unit tests (652 total green); pyright/ruff clean. Proven on the wire in DTU against isolated CI servers: pre-fix a post-patch delegation still forwarded 34/34 to the excluded server; post-fix root stops and named/self sub-sessions forward 0 to the excluded server while the control keeps receiving. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
… narrative Folder-exclusion offer now states BOTH effects and how the agent performs the patch: - persist the pattern to settings.yaml => the exclude filter is correct in a NEW session too (durable source of truth); - run reapply_ingestion in the ROOT session => the already-running session and any sub-session spawned afterward stop immediately, no restart. The reapply tool lives in the root session (where the ingestion hook is mounted), not in this delegated agent; if unreachable, the agent asks the user/root to run it. The user-facing message closes the loop naming both effects. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…m live-reapply files - ruff format (0.15.11) the two new/modified files -> CI 'Check formatting' green. - Plainer wording in docstrings/description: drop 'spike-config', 'mid-flight', 'fan-out' phrasing and a mangled em-dash; no behaviour change. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
The server now returns a Retry-After on a delete refused because the graph is still draining. Make the client and delete tool act on it instead of surfacing a bare 409 the user has to poll by hand. - CIClientError carries retry_after; _http_delete_strict/_http_get_strict parse the Retry-After delta-seconds header across requests/httpx/urllib. - delete_session_tool: on a 409 WITH a retry hint, retry with a bounded backoff (honoring the hint) so a just-finished session drains and deletes on its own; if it never clears, return a precise 'still draining, wait ~Ns' error carrying retry_after. A 409 with no hint (ambiguous id) is never retried. - Tests: _retry_after_seconds parsing (absent/invalid/negative/zero); tool retries-then-succeeds, retries-then-precise-error, and ambiguous-not-retried. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…ternal refs from docstrings - Rename the tool/capability to set_ingestion_filters (by destination name): clearer than 'reapply', accurate whether the filters come from settings.yaml or an explicit block. Module, capability id, class, entry point, tests, behavior, agent and skill references all follow. Behavior identical. - Reword docstrings/comments to describe behavior in this bundle's own terms rather than naming symbols in other repos; no logic change. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…dits The prior rename commit captured the file/directory renames but not the in-file string edits (a partial git add), leaving HEAD referencing the old tool-context-intelligence-reapply module path and reapply_ingestion capability id in behaviors, hook, tool, tests, agent and skill. That broke bundle load. This commits the actual content so HEAD is internally consistent. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…ng agents The analysis and navigation behaviors carried the same three agents (graph-analyst, session-navigator, server-data-ops) as independent copies. analysis now imports navigation and only adds the graph skills, so the agent set lives in one place. Behavior for a composed app is unchanged (same agents + the union of both skill lists).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
server-data-ops— delete Context Intelligence session dataLets a user delete their Context Intelligence data — a whole session (and everything it references) — through a conversation, with a preview and confirmation before anything is removed.
Depends on server PR microsoft/amplifier-context-intelligence#97.
Scenarios delivered (from the design document)
1. "Delete my current session's data"
The agent knows which session is the current one — the user gives no id. It previews what will be removed, offers to also stop future uploads from this folder, and if the session is still running it won't delete it — it points the user to do so from a fresh session.
2. "Find the session about X and delete it"
The user describes the work instead of giving an id. The agent finds the right session, summarises it in plain language to confirm, and on approval deletes it from every server it lives on.
3. "Remove data I pushed from this folder that shouldn't have been"
The agent stops future uploads from the folder first, then finds and deletes every one of the user's sessions from that folder, and leaves the running session alone.
4. "Delete someone else's session"
The agent warns the user it isn't theirs and requires explicit confirmation before deleting it.
Draft — opened for early feedback; depends on #97.
New capability: live ingestion exclude for the delete flow ("stop the bleeding")
Deleting a folder's session data is pointless if the running system keeps re-ingesting it. This capability lets an ingestion
excludetake effect across the already-running system with no restart: the moment the exclude is applied, the root session and every sub-session it spawns afterward stop forwarding that folder to the destination.Behaviour (what the feature delivers)
settings.yaml— a freshly started session in that folder honours it from the start (durable source of truth).reapply_ingestion, which re-readssettings.yaml, re-routes the live dispatchers, and writes the new destinations intocoordinator.session.config's hook entry — the snapshotsession_spawner.merge_configscopies at spawn — so every sub-session spawned afterward inherits the exclude. Bundle-only, reached through the coordinator the hook already holds.verify_ingestion_consistencyfail-loud compares live vs on-disk (both directions); the tool reportsdisk_consistent.Design basis (verified in installed source)
session.py:73 self.config = config;session_spawner.py:298 merge_configs(parent_session.config, …)— a fresh spawn copies the parent's config snapshot;spawn_sub_session(231–922) never re-readssettings.yaml(onlyresumedoes); the kernel never reads it.ModuleCoordinatorexposes.session/.config, so the bundle reaches the exact object spawns copy from — no app-cli / core / foundation change.Scenario evidence — on the wire, isolated CI servers
team-shared= the destination being excluded,remote-server= a second destination left active as a reference. Each run is a realamplifiersession on the shipping branch: baseline events → apply exclude →reapply_ingestion→ more root work → delegate to a real sub-agent, measured by event nodes that actually arrived at each server.foundation:zen-architectafter the excludereapply_ingestionoutput:active: ["remote-server"],inherited_snapshot_patched: true,disk_consistent: true.Reproduced across delegation types — the sub-session sends 0 to the excluded server every time:
foundation:zen-architectRequirement check — sub-sessions must inherit too: the snapshot patch is what carries the exclude to spawned sub-sessions. Without writing the inherited snapshot a sub-session spawned after the exclude still forwards (measured 34 on the excluded server); with it, the sub-session sends 0. That is the propagation this capability guarantees.
Delete-feature validation recipe (unaffected by this addition)
context-intelligence-server-data-ops-validationB0–B3, real server + real agent, shipping branch:write_file✅ · B3 lockdown denies delegating a write tofoundation:file-ops✅Tests
23 new unit tests (
test_reapply_ingestion.py,test_reapply_tool.py) — 652 passing; pyright/ruff clean.Scope
Ships exclude. Include (reverse direction) and the subprocess/fork spawn path are out of scope here. Design note for review: propagation to future spawns is done by the hook writing into
coordinator.session.config— bundle-only and proven; whether it stays bundle-side or becomes a foundation/app-cli "live reconfigure" API is a team decision.