Skip to content

Add server-data-ops delete agent (Context Intelligence session-data deletion) - #108

Draft
Diego Colombo (colombod) wants to merge 39 commits into
mainfrom
feat/server-data-ops
Draft

Add server-data-ops delete agent (Context Intelligence session-data deletion)#108
Diego Colombo (colombod) wants to merge 39 commits into
mainfrom
feat/server-data-ops

Conversation

@colombod

@colombod Diego Colombo (colombod) commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

server-data-ops — delete Context Intelligence session data

Lets 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 exclude take 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)

  • New session: persist the pattern to settings.yaml — a freshly started session in that folder honours it from the start (durable source of truth).
  • Already-running session + all future sub-sessions: the root calls reapply_ingestion, which re-reads settings.yaml, re-routes the live dispatchers, and writes the new destinations into coordinator.session.config's hook entry — the snapshot session_spawner.merge_configs copies at spawn — so every sub-session spawned afterward inherits the exclude. Bundle-only, reached through the coordinator the hook already holds.
  • Safety: verify_ingestion_consistency fail-loud compares live vs on-disk (both directions); the tool reports disk_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-reads settings.yaml (only resume does); the kernel never reads it. ModuleCoordinator exposes .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 real amplifier session 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.

Scenario (shipping branch b40b4b5) Session team-shared (excluded) remote-server (active) Behaviour
Exclude applied live ROOT 79 (baseline only, then stops) 119 (keeps receiving) ✅ running session stops forwarding
SUB — delegated foundation:zen-architect after the exclude 0 21 ✅ sub-session honours the live exclude

reapply_ingestion output: 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:

Sub-session delegation team-shared (excluded) remote-server (active)
self-delegation 0 31
named agent foundation:zen-architect 0 21

Requirement 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-validation B0–B3, real server + real agent, shipping branch:

  • B0 session logged (created_by=alice, 29 nodes, 3 blobs) ✅ · B1 agent previewed + deleted, server returns 404 ✅ · B2 lockdown denies the agent's own write_file ✅ · B3 lockdown denies delegating a write to foundation: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.

…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).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant