Commit Graph
1241 Commits
Author SHA1 Message Date
sysadmin ed9414ebda Merge pull request 'fix(test): add pytest.ini to restrict testpaths and ignore worktree branches (#927)' (#928) from fix/issue-927-pytest-config into master 2026-07-27 15:38:45 -05:00
sysadmin 5fea326988 Merge pull request 'feat(mcp): expose sanctioned Codex MCP reconnect request (Closes #678)' (#918) from fix/issue-678-codex-mcp-reconnect into master 2026-07-27 15:32:10 -05:00
sysadmin dc5d2c8caa Merge pull request 'feat(webui): Sentry/GlitchTip observability console & correlation view (Closes #649)' (#917) from feat/issue-649-sentry-console-correlation into master 2026-07-27 15:23:36 -05:00
sysadmin c30b381eb2 Merge pull request 'fix(mcp): add active IDE vs global config-drift diagnostic (Closes #672)' (#920) from fix/issue-672-mcp-config-drift into master 2026-07-27 05:40:04 -05:00
sysadmin aab54d4825 Merge pull request 'fix(scope): wire author bootstrap scope into workflow scope guard' (#942) from fix/issue-941-scope-guard-bootstrap-wiring into master 2026-07-26 06:20:00 -05:00
jcwalker3andClaude Opus 4.8 (1M context) <[email protected]> a09c485fc0 fix(scope): wire author bootstrap scope into workflow scope guard (Closes #941)
PR #926 (#892) taught create_issue_bootstrap.bootstrap_permits_control_checkout
to accept task_scope=author_issue_bootstrap and wired that canonical decision
into the #274 branches-only enforcer and the #604 anti-stomp preflight. A third
enforcement path was left unwired.

workflow_scope_guard kept its own copy of the clean-root author decision, gated
on create_issue_bootstrap.is_create_issue_task -- a task-name allowlist that
never contained bootstrap_author_issue_worktree. The real call path

    gitea_bootstrap_author_issue_worktree
      -> verify_preflight_purity
        -> _enforce_issue_scope_guard
          -> workflow_scope_guard.assess_production_mutation_guards

therefore raised ProductionGuardError(missing_issue_worktree) before
assess_author_issue_bootstrap was ever consulted, leaving the #892 deadlock
partially present and blocking issue #931.

Changes:

* workflow_scope_guard.assess_root_source_mutation accepts the server-derived
  bootstrap_assessment and, for the clean-root author case, consults the
  canonical bootstrap_permits_control_checkout decision instead of a local
  task-name allowlist. The create_issue arm is unchanged.
* workflow_scope_guard.assess_production_mutation_guards forwards the evidence.
* _enforce_issue_scope_guard accepts and threads the same assessment the #274
  and #604 guards already consume, so all three judge identical evidence, and
  waives the pre-ownership issue-lock requirement for the bootstrap task via
  that same canonical decision rather than a second task-name allowlist.
* verify_preflight_purity passes the once-computed assessment at both sites.

The waiver cannot widen: the predicate fails closed on missing, malformed,
cross-scope, dirty, drifted, or wrongly bound evidence, so ordinary author
source and test mutation from the control checkout stays forbidden and the
#274/#604/#618/#683 protections are unchanged.

Regression: tests/test_issue_941_scope_guard_bootstrap_wiring.py drives the
real enforcer rather than the authorization helper in isolation, which is why
#892's own predicate tests passed while the live bootstrap stayed blocked.

Closes #941

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-26 05:00:09 -05:00
sysadmin 8c1d22a658 Merge pull request 'fix(bootstrap): allow author worktree bootstrap from clean control checkout (Closes #892)' (#926) from fix/issue-892-author-bootstrap-deadlock into master 2026-07-26 03:25:34 -05:00
sysadmin 6a56260768 Merge pull request 'docs(remote-mcp): inventory stdio- and localhost-coupled assumptions (#930)' (#940) from docs/issue-930-remote-mcp-coupling-inventory into master 2026-07-26 02:10:51 -05:00
sysadminandClaude Opus 5 97bc190fc2 docs(remote-mcp): inventory stdio- and localhost-coupled assumptions (#930)
Add docs/remote-mcp/coupling-inventory.md, the blocking first child of epic
#929. It enumerates every place gitea_mcp_server.py and its supporting modules
depend on being a local, client-spawned, stdio-attached process on the
operator's machine.

62 entries across the seven required categories: transport bind, launch
provenance, role binding, credentials, runtime freshness, local filesystem,
and durable state. Each entry carries a file and line anchor resolving at
7bf4f12584, states what the code assumes today
and what it would observe on a remote host, is classified as portable as
written / needs a seam / needs a replacement / cannot be remote, and is
assigned to exactly one epic child. Every child from #931 through #939 is
named by at least one entry. Summary tables count entries per category, per
classification, per category-by-classification, and per child.

Documentation only. No server behavior changes.

Closes #930

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01HvJz7bUz5CkZgUxq8twHMz
2026-07-26 02:09:09 -04:00
sysadmin 17dd05ec9d fix(test): add pytest.ini to restrict testpaths and ignore worktree branches (#927) 2026-07-25 23:07:15 -04:00
sysadmin 7bf4f12584 Merge pull request 'fix(guardrail): detect and reject manually launched duplicate MCP role servers (#686)' (#925) from fix/issue-686-detect-reject-manual-mcp into master 2026-07-25 18:32:23 -05:00
jcwalker3andClaude Opus 4.8 2066623986 fix(bootstrap): allow author worktree bootstrap from clean control checkout (Closes #892)
Align assess_author_issue_bootstrap with bootstrap_permits_control_checkout
so gitea_bootstrap_author_issue_worktree can create the first branches/
worktree without the lock↔worktree deadlock.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-25 18:27:18 -05:00
sysadmin dc0bff764d test(runtime): patch _trusted_session_repository in test_activate_profile_succeeds_when_enabled 2026-07-25 19:27:12 -04:00
sysadmin dfe8d7c28d fix(mcp): detect and reject manually launched duplicate MCP role servers (Closes #686) 2026-07-25 19:25:23 -04:00
sysadmin fad44669d9 fix(mcp): add active IDE vs global config-drift diagnostic (Closes #672) 2026-07-25 19:07:10 -04:00
jcwalker3andGrok 4.5 29ad93d145 feat(mcp): expose sanctioned Codex MCP reconnect request (Closes #678)
Add gitea_request_mcp_reconnect as a report-only callable surface so Codex
and other agent hosts can request host/IDE reconnect with typed blockers
and exact UI steps. Never kills processes or edits config.

Co-Authored-By: Grok 4.5 <[email protected]>
2026-07-25 17:52:08 -05:00
sysadmin f2dbf30e81 feat(webui): Sentry/GlitchTip observability console & correlation view (Closes #649) 2026-07-25 18:48:36 -04:00
sysadmin 2b4e43042a Merge pull request 'feat(tests): add concurrent-session MCP restart safety tests (Closes #666)' (#910) from feat/issue-666-concurrent-mcp-restart-tests into master 2026-07-25 17:44:09 -05:00
sysadmin 0f9390aab4 Merge remote-tracking branch 'prgs/master' into feat/issue-666-concurrent-mcp-restart-tests 2026-07-25 18:43:28 -04:00
sysadmin d7ad2838ec Merge pull request 'docs(incident): retroactive audit for direct-to-master commit 2fa97c26 (#670)' (#915) from fix/issue-670-direct-master-incident into master 2026-07-25 17:40:23 -05:00
sysadmin c6d68dbc7b Merge pull request 'feat(webui): notifications and human-attention routing (#648)' (#905) from feat/issue-648-notifications-console into master 2026-07-25 17:40:03 -05:00
sysadmin c83a10d7c2 Merge remote-tracking branch 'prgs/master' into feat/issue-648-notifications-console 2026-07-25 18:37:17 -04:00
sysadmin ca22c326a4 Merge pull request 'docs(architecture): ADR for high-availability and rolling-restart MCP architecture (Closes #668)' (#912) from docs/issue-668-mcp-ha-rolling-restart into master 2026-07-25 17:34:31 -05:00
sysadmin 3bbe6df6c7 Merge pull request 'feat(webui): add read-only console restart status and impact controls (Closes #667)' (#911) from feat/issue-667-console-restart-controls into master 2026-07-25 17:34:12 -05:00
jcwalker3 71031c812e Merge branch 'master' into feat/issue-648-notifications-console 2026-07-25 17:29:57 -05:00
jcwalker3 e43ddd3cbe docs(incident): retroactive audit for direct-to-master commit 2fa97c26 (#670) 2026-07-25 17:29:34 -05:00
sysadmin a64ba08e27 fix(webui): address #905 REQUEST_CHANGES on notifications classifier
B1: classify_attention_event uses structured flags/category only — never
substring-match human-authored title/summary for escalation.

B2: make notification ids unique across probe_errors and collisions
(include loop index / kind).

B3: do not assign probe_errors to fetch_error (avoids false Fetch Warning
and double-reporting).

Regression tests cover all three blockers.

Refs #648
2026-07-25 18:26:46 -04:00
sysadmin 26f54851d1 Merge pull request 'feat(mcp): enforce scoped recovery playbook before full restart (Closes #669)' (#914) from feat/issue-669-scoped-component-recovery into master 2026-07-25 17:14:21 -05:00
sysadmin f02a2dc030 Merge pull request 'feat(webui): Web Console stale-runtime recovery & reconciliation controls (Phase 2) (#644)' (#903) from feat/issue-644-console-recovery into master 2026-07-25 17:14:06 -05:00
sysadminandClaude Opus 4.8 bb8c3a537b merge(master): resolve PR #905 conflicts with requests/linkage
Keep notifications (#648) routes and nav alongside master requests (#643)
and other base updates.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-25 18:11:06 -04:00
sysadminandClaude Opus 4.8 04ae3532cc merge(master): resolve #903 conflicts with #643 request initiation
Keep #644 recovery console actions and #643 initiate_workflow side by side
in console_authz and authz audit docs after merging latest master.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-25 18:03:04 -04:00
sysadmin 7bb5ff4719 Merge pull request 'feat(webui): request preview, authorization, and workflow initiation (Closes #643)' (#902) from feat/issue-643-request-preview-initiate into master 2026-07-25 17:02:17 -05:00
sysadmin 5b7ceefa9a Merge remote-tracking branch 'prgs/master' into feat/issue-644-console-recovery 2026-07-25 18:00:31 -04:00
sysadminandClaude Opus 4.8 4a2fae8495 fix(webui): arm the recovery gates and make the playbooks reach the process (#644)
Reviewer REQUEST_CHANGES on PR #903 at head 1c88b87 raised five blockers, all
reproduced by executing that head. The shared shape: a write path that declared
itself gated, audited, and verified, but never armed the gate, mutated a copy of
the state it claimed to fix, and then verified against that same copy.

B1 - the apply path never asked the execution gate.
execute_recovery_playbook called console_authz.authorize with the default
for_execution=False, and the phase branch only fires when it is True. ACTIVE_PHASE
is 1 and every new action is phase 2, so an operator executed a phase-2 write
through POST /api/v1/system/recovery/apply while build_recovery_preview reported
execution_enabled false. The call now passes for_execution=True and surfaces the
phase_not_active refusal. Preview reports the same decision under
execution_authorization / execution_blocked_reason instead of a hardcoded False it
could not explain.

B2 - both env playbooks mutated a discarded copy and verified against it.
source_env = dict(os.environ) meant clear_stale_binding and rebind_session_worktree
never touched the running process, and verify_post_recovery(env=source_env)
re-diagnosed the same copy, confirming a change that had not happened. Mutations
now target the live mapping (apply_recovery's sanctioned env=None -> os.environ
path, #702 AC2) and verification re-reads state rather than the mutated input.
binding_before / binding_after / binding_changed are returned, and a playbook that
changed nothing reports performed: false. verify_post_recovery no longer reads an
unverified_inherited binding as clean, because unproven is not clean.

B3 - the reconcile playbook called a function that does not exist.
merged_cleanup_reconcile.reconcile_merged_cleanups is absent from that module and a
bare except turned the AttributeError into a generic failure, so the playbook could
never succeed. It now calls gitea_mcp_server.gitea_reconcile_merged_cleanups, the
real orchestrator, imported lazily; failures carry error_type. task_capability_map
declared gitea.pr.close for reconcile_cleanups while the entry point gates on
gitea.read; the two authority statements are reconciled to the one that is enforced.

B4 - the #630 contamination integration could not block.
assess_contamination_gate was fed marker=None, which short-circuits to block: False
on its first statement; the task passed was a console action id outside
CONTAMINATION_GATED_TASKS; and the result was read through a "contaminated" key the
gate never returns, making STATUS_BLOCKED_CONTAMINATION unreachable. The live marker
now comes from the #641 session inventory reader, the gated task key
console_recovery_apply is added to CONTAMINATION_GATED_TASKS, every read uses the
"block" key the gate actually returns, and the marker is forwarded to
sanctioned_restart.execute_restart so a restart cannot launder a contaminated
runtime. The reconciler cleanup playbook stays exempt as the designated remedy.

B5 - the parity baseline was captured from the head it was compared against.
capture_startup_parity(root, head=checkout_head) stores the head verbatim, so
in_parity was structurally incapable of being false, and live_remote_head was never
passed. The baseline is now the daemon start head that assess_stale_runtime already
returns, and the #610 live-remote dimension is restored.

Also: _recovery_card was the one renderer in system_health_views.py interpolating
without _esc(), and it is where a marker's operator-supplied command_summary lands
once B4 is wired; it now escapes, including the except branch. Docs no longer claim
apply enforces master parity or that verify asserts clean: true, and the absolute
file:///Users/... links are relative.

Tests: the two that asserted the defects as intended are inverted -
test_api_recovery_apply_with_dev_auth asserted the phase-gate bypass, and the rebind
test asserted the input echoed back. Added coverage per blocker, including a no-op
detection test that fails when a playbook reports success without changing anything,
the previously untested reconcile playbook, contamination block and remedy-exemption
tests, and parity baseline/live-remote tests. Both new guards were mutation-verified:
disarming for_execution fails 2 tests, restoring the env copy fails 2 tests.

Validation: WEBUI_TEST_OFFLINE=1 ../../venv/bin/python -m pytest tests/ -q from
branches/feat-issue-644 gives 27 failed / 5291 passed / 6 skipped / 953 subtests;
the same command from branches/baseline-master-76f293e at 76f293eb28 gives
28 failed / 5262 passed / 6 skipped / 926 subtests. Suites run one at a time.
comm of the sorted FAILED lines shows no new signature at the head. The single
absent signature, test_workspace_guard_alignment.py::
TestRuntimeContextGuardAlignment::test_declared_branches_worktree_passes_when_mcp_root_differs,
is suite-order dependent: that file passes 9/9 in isolation at both revisions.

Closes #644

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-25 17:42:49 -04:00
sysadminandGrok 4.5 461e1dac78 feat(mcp): enforce scoped recovery playbook before full restart (Closes #669)
Add recovery_playbook.py with the narrow-to-broad recovery ladder, symptom
routing, attempt-log helpers, and escalation metrics. Wire the attempt-log
gate into restart_coordinator so rolling/full/host restarts require prior
insufficient narrower attempts (or break-glass). Document the ladder and
update gitea_request_mcp_restart for prior_recovery_attempts_json.

Co-Authored-By: Grok 4.5 <[email protected]>
2026-07-25 17:35:11 -04:00
sysadmin 9c69bfcd80 Merge pull request 'feat(webui): Gitea issue and PR linkage console (Closes #645)' (#904) from feat/issue-645-linkage-console into master 2026-07-25 16:32:21 -05:00
sysadmin 6010f4295b docs(architecture): add ADR for HA and rolling-restart MCP architecture (Closes #668) 2026-07-25 17:27:50 -04:00
sysadminandClaude Opus 4.8 9b8e315b49 docs(webui): document the read-only restart console surface (#667)
Records the two GET routes, what each panel consumes, and the three
properties the surface is held to: an unreadable source reports
unavailable rather than green, authorization is probed with
for_execution=True so a Phase 1 refusal is never shown as an allow, and
the control-plane database is opened mode=ro so reading status never
creates it.

Refs #655 #642 #658 #661 #662 #663 #633 #652 #653 #664

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-25 17:26:30 -04:00
sysadmin 9a01543477 feat(webui): add read-only console restart status and impact controls (Closes #667) 2026-07-25 17:23:52 -04:00
sysadmin 59aab06fe1 feat(tests): add concurrent-session MCP restart safety tests (Closes #666) 2026-07-25 17:14:14 -04:00
sysadmin 4f06d30e07 feat(webui): implement notifications and human-attention routing (#648) 2026-07-25 16:41:16 -04:00
sysadminandClaude Opus 4.8 211890f361 feat(webui): Gitea issue and PR linkage console (Closes #645)
Add a Phase 3 read-only console that resolves issue↔PR linkage with
evidence (closes keyword, branch marker, body mention), surfaces the
latest canonical handoff for a focused thread, and deep-links to Gitea
only under the admin reveal opt-in.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-25 16:40:07 -04:00
sysadmin 1c88b87ec5 feat(webui): implement Phase 2 recovery controls & playbooks (#644) 2026-07-25 08:19:06 -04:00
jcwalker3 b993ad1c64 Merge branch 'master' into feat/issue-643-request-preview-initiate 2026-07-25 07:13:21 -05:00
sysadmin 76f293eb28 Merge pull request 'fix(gate): stop classifying stale-runtime blocks as permission denials (Closes #897)' (#901) from fix/issue-897-permission-stale-runtime-classification into master 2026-07-25 06:56:16 -05:00
jcwalker3 d0006e9f71 Merge branch 'master' into feat/issue-643-request-preview-initiate 2026-07-25 06:42:41 -05:00
jcwalker3 54559aebc3 Merge branch 'master' into fix/issue-897-permission-stale-runtime-classification 2026-07-25 06:42:27 -05:00
sysadmin 715863799f Merge pull request 'feat(webui): Runtime and session view (Phase 1) (Closes #641)' (#898) from feat/issue-641-runtime-session-view into master 2026-07-25 05:50:48 -05:00
jcwalker3 6da68fffb8 Merge branch 'master' into feat/issue-643-request-preview-initiate 2026-07-25 02:44:58 -05:00
jcwalker3 daf7ed4c2b Merge branch 'master' into feat/issue-641-runtime-session-view 2026-07-25 02:41:46 -05:00