Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ All notable changes to this project will be documented in this file.

### Changed

* ROADMAP now tracks the `mqobsidian` v0.1.0 single-source-of-truth foundation
as an upstream dependency, while keeping `mqlaunch` read-only or
delegate-only for truth, inbox, ranking, and promotion surfaces.
* Documented the canonical mqobsidian view-manifest keys consumed by `mqlaunch`
and marked that roadmap deliverable done.
* Added a smoke test that locks the MQ Obsidian menu out of memory promotion or
rejection routes, preserving the review-gated ownership boundary.
* Verified the review command delegation boundary through
`tests/mq-agent-routing-smoke.sh` and marked the roadmap item done.
* Monolith de-layering (Step 11a): five concerns moved verbatim out of
`terminal/launchers/mqlaunch.sh` into dedicated libraries sourced back into
the launcher's scope — the network concern (status/diagnostics/connectivity,
Expand All @@ -33,6 +42,18 @@ All notable changes to this project will be documented in this file.
drops ~720 lines and each concern now has a named owner. Guarded by
`tests/monolith-delayer-smoke.sh`, a table-driven check that fails if any
extracted function is redefined in the monolith or a lib source is dropped.
* `print_header` now has a single owner: `ui/terminal-ui/mq-ui.sh`. The launcher
no longer overrides it; instead it opts the main loop into the dashboard-v7.1
header via `MQ_USE_DASHBOARD_HEADER=1`. **Behavior change:** the main-loop
header now renders through mq-ui's *cached* dashboard path (bounded by
`MQ_DASHBOARD_CACHE_TTL`, default 5s, and invalidated by the git/release
flows) instead of re-forking the dashboard script uncached on every screen.
This removes a hidden fork in render behavior and aligns the main loop with
the cache and invalidation model the rest of the runtime already used; it also
avoids a dashboard re-fork per screen render. Escape hatch: set
`MQ_DASHBOARD_CACHE_TTL=0` for an uncached, per-screen header while
investigating. The dead `DASHBOARD_V71` launcher variable (only the removed
override used it) is gone.
* `semantic-memory-maintainer` renamed to `vector-store-maintainer` to avoid
routing collision with mq-mcp's skill of the same name.
* `command-template-library` skill moved to mq-ums, where the contracts and
Expand Down
92 changes: 89 additions & 3 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ Goal: make the Obsidian SSOT plan explicit and buildable without expanding
| Done | Repo ownership map documented |
| Done | `mqlaunch` boundary against direct cognition/memory logic documented |
| Done | Existing MQ Obsidian menu kept as read-only/presentation-first surface |
| Todo | Document canonical mqobsidian manifest keys consumed by `mqlaunch` |
| Todo | Add/verify tests that MQ Obsidian menu actions do not promote memory |
| Todo | Add/verify tests that review commands delegate through `mq-agent` |
| Done | Document canonical mqobsidian manifest keys consumed by `mqlaunch` |
| Done | Add/verify tests that MQ Obsidian menu actions do not promote memory |
| Done | Add/verify tests that review commands delegate through `mq-agent` |
| Todo | Add `mqlaunch obsidian status` or documented alias for current menu/status |

Expected commands:
Expand All @@ -99,6 +99,10 @@ mqlaunch can show Obsidian readiness and open canonical views,
but all scoring, promotion, schema, and cognition logic is owned elsewhere.
```

Boundary test: `tests/mq-agent-routing-smoke.sh` verifies that review,
risk-review, architecture, repo-health, and mcp-status routes stay delegated
through `mq-agent`.

## 31-60 Days: Inbox Ranking And Promotion Loop

Goal: make repeated Codex/Claude/mqlaunch patterns visible as candidates
Expand Down Expand Up @@ -181,6 +185,88 @@ The operator can answer "what is true about the MQ stack right now?"
from one terminal surface backed by Obsidian truth exports.
```

## Upstream Dependency: mqobsidian v0.1.0 SSOT Foundation

`mqobsidian` owns the canonical truth structure for the MQ stack. This repo
depends on that work, but must not implement competing truth, inbox, ranking,
or promotion logic locally.

Status: Proposed · Priority: P1 · Owner: `mqobsidian`

Current status:

* [ ] canonical truth schema is not yet fully locked
* [ ] inbox, ranking, and promotion state are not yet unified under one explicit model
* [ ] consumer repos still risk inventing local truth if exports/contracts stay underdefined
* [ ] moderator workflow risks becoming a bottleneck without clear promotion states and thresholds

### mqobsidian owns

* [ ] canonical truth schema
* [ ] inbox structure and promotion queue structure
* [ ] durable memory categories and persistence rules
* [ ] canonical status, views, and manifests consumed by other repos
* [ ] freshness/state markers for truth surfaces
* [ ] promotion state and memory lifecycle states
* [ ] single source of truth rules across the stack

### macos-scripts relationship

`mqlaunch` may consume exported status/views/manifests and delegate workflows to
`mq-agent`, but it must not define schema, compute rankings, promote memory, or
invent local lifecycle state.

Expected consumer contract:

```text
mqlaunch -> read/open exported truth views
mqlaunch -> delegate inbox/promote workflows to mq-agent
mq-agent -> write/orchestrate through mqobsidian contracts
mqobsidian -> own schema, state, persistence, and durable views
```

### Required upstream delivery

#### A. Canonical schema

* [ ] define status manifest
* [ ] define inbox manifest
* [ ] define views manifest
* [ ] define learn/review/decision schemas
* [ ] define promotion-state fields
* [ ] define archival/deprecation lifecycle fields

#### B. Inbox and ranking model

* [ ] define what enters inbox
* [ ] define recurrence/evidence fields
* [ ] define ranking inputs
* [ ] define review-needed vs auto-promotable states
* [ ] define thresholds and exception paths

#### C. Durable memory governance

* [ ] define what qualifies as durable memory
* [ ] define what remains transient or session-local
* [ ] define promotion approvals and guardrails
* [ ] define rollback/deprecation path for bad memory
* [ ] define traceability from source evidence to durable note

#### D. Consumer contracts

* [ ] define canonical read surfaces for `mqlaunch`
* [ ] define canonical delegation/contract surfaces for `mq-agent`
* [ ] version exported truth surfaces
* [ ] expose freshness and drift markers

### Dependency exit criteria

* [ ] `mqobsidian` is the undisputed truth owner
* [ ] inbox, ranking, promotion, and durable memory have one canonical model
* [ ] consumers read from exported truth surfaces instead of inventing local truth
* [ ] every promoted durable memory item can be traced back to source evidence
* [ ] `mqlaunch` has enough contract detail to stay read-only or delegate-only

## Phase 12 / v2.0.0 — Runtime Authority And Shell Governance

**Status:** Proposed
Expand Down
2 changes: 1 addition & 1 deletion docs/AUTHORITY_MAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Reached through other live paths:

| Path | Role | Authority |
| --- | --- | --- |
| `ui/terminal-ui/mq-ui.sh` | Shared UI library (rendering, padding, git-status snapshot) | **UI authority** (26 live references) |
| `ui/terminal-ui/mq-ui.sh` | Shared UI library (rendering, padding, git-status snapshot, `print_header`) | **UI authority** (26 live references) — sole owner of `print_header`; the launcher no longer overrides it (Step 11a) |
| `ui/ascii/mqlaunch-dashboard-v7.1.sh` | Branded dashboard | **Dashboard authority** |
| `ui/dashboards/mq-dashboard.sh` | Status dashboard used by the tools menu / theme manager | secondary, keep until folded into the authority |

Expand Down
31 changes: 31 additions & 0 deletions mqlaunch/docs/mqobsidian-consumer.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,37 @@ pattern/feedback logic.
· `execution` · `mq-agent-hot` · `mq-mcp-hot` · `mq-hal-hot`. Paths are resolved
from the manifest, not hardcoded — change the manifest, not the logic.

## Canonical manifest contract

`mqlaunch` consumes only `mqlaunch/config/mqobsidian/views.json`. The manifest is
an array of view records with these required fields:

| Field | Allowed values | Consumer behavior |
| --- | --- | --- |
| `key` | stable string identifier | CLI/menu argument; must not be inferred from paths |
| `label` | display string | menu/picker text only |
| `type` | `file` or `folder` | validates whether the target should be a file or folder |
| `relative_path` | vault-relative path | resolved under `MQ_OBSIDIAN_DIR` or the fallback vault |

Canonical keys currently consumed by `mqlaunch`:

| Key | Kind | Target |
| --- | --- | --- |
| `dashboard` | file | `systems/mqobsidian/index.md` |
| `roadmaps` | folder | `roadmap` |
| `reviews` | folder | `reviews` |
| `decisions` | folder | `decisions` |
| `execution` | folder | `execution` |
| `mq-agent-hot` | file | `systems/mq-agent/hot.md` |
| `mq-mcp-hot` | file | `systems/mq-mcp/hot.md` |
| `mq-hal-hot` | file | `systems/mq-hal/hot.md` |
| `roadmap-doc` | file | `docs/roadmap-token-reduction.md` |
| `context-budget` | file | `docs/context-budget.md` |

Ownership rule: adding, removing, renaming, or repointing keys changes the
consumer contract. Keep that change in the manifest and docs; do not duplicate
view paths in shell menu logic.

## Commands

| Command | Does |
Expand Down
27 changes: 13 additions & 14 deletions terminal/launchers/mqlaunch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,16 @@ MQ_SCRIPT="$BASE_DIR/terminal/launchers/mqlaunch.sh"
BACKUP_DIR="$BASE_DIR/backups"
BIN_LINK="$HOME/bin/mqlaunch"
UI_LIB="$BASE_DIR/ui/terminal-ui/mq-ui.sh"
DASHBOARD_V71="$BASE_DIR/ui/ascii/mqlaunch-dashboard-v7.1.sh"

# print_header is owned by mq-ui.sh (single header authority). Opt the main loop
# into the dashboard-v7.1 header via mq-ui's cached path — this is a plain
# (non-exported) shell var so it drives this launcher's own print_header calls
# without forcing the dashboard header onto child subprocesses, which set the
# flag themselves where they want it. Cache freshness is bounded by
# MQ_DASHBOARD_CACHE_TTL (default 5s) and invalidated by mutating flows
# (open_git_menu / open_release_menu). Set MQ_DASHBOARD_CACHE_TTL=0 for an
# uncached, per-screen header while investigating.
MQ_USE_DASHBOARD_HEADER=1

TERMINAL_GUIDE_HTML="$BASE_DIR/docs/mac-terminal-guide.html"
TERMINAL_GUIDE_URL="https://mcamner.github.io/macos-scripts/"
Expand Down Expand Up @@ -220,20 +229,10 @@ if [[ -f "$BASE_DIR/terminal/menus/recommendations-menu.sh" ]]; then
source "$BASE_DIR/terminal/menus/recommendations-menu.sh"
fi

# Prints header.
print_header() {
clear
if [[ -f "$DASHBOARD_V71" ]]; then
bash "$DASHBOARD_V71" "$APP_TITLE" "$APP_SUBTITLE" "ONLINE"
else
echo "$APP_TITLE — $APP_SUBTITLE"
printf '%s
' "----------------------------------------------------------------------------------------"
fi
echo
}

# --- Shared UI ------------------------------------------------
# print_header is provided by mq-ui.sh (the single header authority); the
# launcher no longer overrides it. With MQ_USE_DASHBOARD_HEADER=1 (set above)
# mq-ui renders the cached dashboard-v7.1 header for the main loop.
open_app() {
local app_name="$1"
open -a "$app_name" >/dev/null 2>&1 || {
Expand Down
43 changes: 43 additions & 0 deletions tests/mq-obsidian-menu-no-promotion-smoke.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
MENU="$ROOT/terminal/menus/mq-obsidian-menu.sh"
DOC="$ROOT/mqlaunch/docs/mqobsidian-consumer.md"
ROADMAP="$ROOT/ROADMAP.md"

echo "SMOKE: MQ Obsidian menu has no memory promotion path"

echo "[1/6] files exist"
test -f "$MENU"
test -f "$DOC"
test -f "$ROADMAP"

echo "[2/6] shell syntax"
bash -n "$MENU"

echo "[3/6] menu describes presentation/routing ownership"
grep -q "this menu owns presentation and routing only" "$MENU"
grep -q "mqobsidian and mq-agent own memory, context-pack, and learn logic" "$MENU"

echo "[4/6] triage is read-only and explicitly review-gated"
grep -q "mq_obsidian_triage_learning_inbox()" "$MENU"
grep -q "Learning inbox triage is review-gated" "$MENU"
grep -q "No promote/reject action is run from mqlaunch" "$MENU"
grep -q "mq_obsidian_show_inbox" "$MENU"

echo "[5/6] menu contains no promotion or rejection command routes"
if grep -Eq '(^|[[:space:];|&])(mq-agent|mqlaunch|python3|bash|zsh)[[:space:]].*(promote|promotion|reject|learn[[:space:]]+promote|promote-from-review|resolve-supersede)' "$MENU"; then
echo "MQ Obsidian menu appears to route promotion/rejection work" >&2
exit 1
fi
if grep -Eq '(_run_agent[[:space:]].*(promote|reject)|learn[[:space:]]+promote|promote-from-review|resolve-supersede)' "$MENU"; then
echo "MQ Obsidian menu appears to delegate promotion/rejection work" >&2
exit 1
fi

echo "[6/6] docs and roadmap keep promotion outside mqlaunch"
grep -q "No writes to the vault. No scoring, promotion/downgrade, inbox or feedback-loop" "$DOC"
grep -q "Add/verify tests that MQ Obsidian menu actions do not promote memory" "$ROADMAP"

echo "OK: MQ Obsidian menu no-promotion smoke test passed"
Loading