From e624fe230a4744accb42aa49bf90808a9e9b8f4b Mon Sep 17 00:00:00 2001 From: "otherness[bot]" Date: Thu, 23 Apr 2026 07:51:04 +0000 Subject: [PATCH 1/3] =?UTF-8?q?vision(auto):=20autonomous=20scan=20?= =?UTF-8?q?=E2=80=94=2014th=20scan,=20doc=2054=20added=20(5=20novel=20pres?= =?UTF-8?q?sure=20gaps)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vibe-vision autonomous scan (Step A). No human input required. Changes: 1 file changed, 74 insertions(+) Scans performed: - Scan 1: no Future items promotable via PR title match (no matching titles) - Scan 2: no stale Present items (all referenced files found) - Scan 3: no untracked TODOs/FIXMEs; backlog at 245 (below 400 ceiling) - Scan 4: no items 90+ days without issues - Scan 5: 5/5 bullets scored via domain-noun matching (over-broad per 50.3) β€” all five lenses remain genuinely open New doc 54 adds 5 novel gaps absent from prior 245-item corpus: - 54.1: coord.md at 1,806 lines is an attention-fragmentation risk (Lens 1) - 54.2: Step A wall-clock consumes time that should go to ENG/Step B (Lens 2) - 54.3: SCAN 0 ceiling at 400 is currently inactive (corpus=245) β€” needs dynamic rate-based ceiling (Lens 3) - 54.4: otherness-config.yaml has no migration path when schema evolves (Lens 4) - 54.5: managed project developers have no visibility into what otherness shipped for them (Lens 5) Signed-off-by: otherness[bot] --- ...54-fourteenth-vision-scan-pressure-gaps.md | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 docs/design/54-fourteenth-vision-scan-pressure-gaps.md diff --git a/docs/design/54-fourteenth-vision-scan-pressure-gaps.md b/docs/design/54-fourteenth-vision-scan-pressure-gaps.md new file mode 100644 index 00000000..2bf2a2be --- /dev/null +++ b/docs/design/54-fourteenth-vision-scan-pressure-gaps.md @@ -0,0 +1,74 @@ +# Design Doc 54 β€” Fourteenth Vision Scan Pressure Gaps + +**Vision scan date**: 2026-04-23 +**Scan**: 14th autonomous run +**Pressure result**: SCAN 5 scores 5/5 via domain-noun matching (over-broad, per 50.3/53) β€” all five lenses remain genuinely open +**Backlog size**: 245 `πŸ”² Future` items across all design docs (SCAN 0 ceiling at 400 not triggered) + +--- + +## The problem + +13 vision scans have run. The SCAN 0 stagnation gate (53.2) did not fire because the corpus is 245 items β€” below the 400 ceiling. But 245 is still large: doc 53.1 showed that 409 items defeated reliable COORD navigation; 245 is the post-53.1-backlog-triage number. The ceiling was set at 400 empirically at a specific point in the project's history, and has not been adjusted to reflect the observed degradation threshold. + +This doc applies the pressure lenses as a human analyst and identifies four gaps that are genuinely absent from all prior docs. + +The criterion: a gap must name a failure mode that (a) is live today, (b) has NO existing `πŸ”² Future` item addressing it, and (c) would, if fixed, directly reduce failure under one of the five pressure lenses. + +--- + +## Present (βœ…) + +*(No items shipped yet β€” doc created by this scan)* + +--- + +## Future (πŸ”²) + +### Lens 1 β€” Reliability: phase file instruction complexity is an unrecognized attention sink + +- πŸ”² 54.1 β€” `coord.md` at 1,806 lines creates attention fragmentation that reduces reliable execution β€” the distil-and-simplify work (doc 45) reduced sm.md from 5,070 to 1,895 lines but coord.md remains at 1,806 lines and has grown as features were added. An LLM running a 1,806-line instruction file does not read every instruction with equal attention β€” the probability of missing a section increases with file length. COORD's most critical sections (Β§1b-preflight, Β§1e item claim, Β§1d-exit) are buried after hundreds of lines of context-setting. The distil cycle (45.1–45.6) was designed to address this, but its scope was: reduce Python block duplication. The structural problem is different: `coord.md` has grown a new class of complexity β€” 23 named sub-sections (Β§1a through Β§1e-starvation-handler) with interdependencies that require the LLM to maintain a mental model of the entire section graph while executing any individual section. The fix is not another Python deduplication pass. It is a structural rewrite: `coord.md` must be reorganized into a linear decision tree of ≀15 numbered steps, where each step has exactly one condition, one action, and one output. No sub-sections of sub-sections. No `Β§1b-preflight` β†’ `Β§1b-vision` β†’ `Β§1b-sim` β†’ `Β§1b-session-type` chain that requires the LLM to track four distinct blocks before reaching the first claimable item. SM Β§4a (45.8 structural gate, per doc 45) must add `coord.md` to its line-count monitoring: if `wc -l agents/phases/coord.md > 1500`: open a `kind/chore priority/high` issue "coord.md exceeds 1,500 lines β€” reliability risk. The distil-and-simplify cycle must address this before adding new features to COORD." The 1,500-line cap is the same as the target set in doc 45 for sm.md. ⚠️ Inferred from reliability lens: sessions still fail silently; one structural cause is COORD's 1,806-line instruction complexity; this is the direct analog of the sm.md problem (5,070 β†’ 1,895 via 45.1) applied to coord.md; without a line-count gate, coord.md will grow to 2,000+ lines as more feature items are shipped. + +### Lens 2 β€” Honesty: Step A consumes session budget that should go to ENG + +- πŸ”² 54.2 β€” The scheduled workflow's Step A (vibe-vision-auto) and Step B (otherness.run) share a single GitHub Actions runner but NOT a single session budget β€” however, Step A runs as a full OpenCode session with its own LLM calls, and the workflow design means if Step A runs long (e.g. a large SCAN 5 scoring operation across 245 items), Step B starts with a shorter overall wall-clock window before the runner timeout. The honest accounting of session budget is missing: there is no mechanism that reports how much wall-clock time Step A consumed and how much remains for Step B. If Step A takes 15 minutes (5 scans, PR list fetch, design doc reads, commit), Step B starts 15 minutes into a 60-minute runner. When ENG hits a complex implementation, the runner may timeout before QA runs. SM Β§4g must add a `step_b_start_time` and `step_a_duration_min` field to `state.json` β€” written at the START of Step B by reading `$SECONDS` from the runner environment and comparing to the workflow start time. PM Β§5 must, every 10 batches, check whether `step_a_duration_min` correlates with `meaningful_prs=0` sessions: if sessions where Step A took >20 min have `meaningful_prs=0` at a rate >40%, PM Β§5 must open a `kind/chore priority/high` issue: "Step A duration (>20min) correlates with Step B zero-PR sessions β€” the scan is consuming wall-clock that ENG needs for implementation. Consider adding a `timeout-minutes` cap on the Step A job in `otherness-scheduled.yml`." Without this accounting, the dual-step design's implicit budget trade-off (scan time vs. implementation time) is invisible to the operator and to all monitoring mechanisms. ⚠️ Inferred from honesty lens: the loop is not honest enough β€” the dual-step workflow implies both steps get full session budget, but wall-clock is shared; the system has no mechanism to detect when Step A is crowding out Step B; this is a systematic bias toward backlog inflation over feature delivery that the operator cannot see from any existing metric. + +### Lens 3 β€” Self-improvement: SCAN 0 ceiling is too high relative to observed degradation threshold + +- πŸ”² 54.3 β€” The SCAN 0 backlog ceiling (53.2) was set at 400 items based on the observed point of COORD navigation degradation. But the current corpus has 245 items β€” 155 below the ceiling β€” and COORD is already showing degradation indicators: 12+ consecutive 0/5 pressure scores, housekeeping PRs, and the 245 items covering all five pressure lenses without resolving any. The ceiling was right for the batch when doc 53.2 was written (409 items). But doc 53.2 was implemented and the backlog triage reduced items to 245. The ceiling was NOT recalibrated after the reduction. The correct ceiling is not a fixed number β€” it is a function of the ratio `items_addressed_last_10_batches / total_future_items`. If this ratio drops below 0.02 (fewer than 2% of Future items shipped per 10-batch window), the backlog has already exceeded COORD's effective navigation capacity regardless of absolute count. `vibe-vision-auto.md` SCAN 0 must replace the fixed 400-item ceiling with a dynamic rate-based ceiling: if `items_shipped_last_10_batches / total_future_items < 0.02` AND `total_future_items > 150`: suppress SCAN 3 and SCAN 5 item generation for this run. This is stricter than the current 400-item gate (which allows unlimited backlog growth up to 400) and more accurate (it detects degradation by ratio, not count). The current implementation of SCAN 0 checks `total_future_items > 400` β€” this check is trivially false at 245 items and will remain false until the backlog grows back to 400. The entire SCAN 0 ceiling mechanism is currently inactive because the fixed threshold is wrong. ⚠️ Inferred from self-improvement lens: the agents are not meaningfully smarter; one structural reason is that backlog growth continues unchecked below 400 items; at 245 items and a 2% address rate, the backlog will return to 400 within 8–10 scan sessions; the rate-based ceiling catches this trajectory earlier and keeps it from repeating. + +### Lens 4 β€” Onboarding: `otherness-config.yaml` has no migration path when config schema evolves + +- πŸ”² 54.4 β€” Every time a new config field is added to `otherness-config.yaml` (e.g. `maqa.agents_path` in doc 27, `monitor.paused_projects` in 46.25, `observability.otlp` in 44.1), projects that were onboarded BEFORE the new field was added silently run without it β€” with no warning, no migration step, and no automated detection. PM Β§5 currently validates that `monitor.projects` entries are reachable (46.10) and that `schedule.cron` is present (48.12) β€” but no mechanism checks whether a running project's `otherness-config.yaml` is missing fields that were added to `otherness-config-template.yaml` after the project was onboarded. A project onboarded in week 1 is missing `observability.otlp`, `monitor.paused_projects`, and possibly `schedule.vibe_vision_step` β€” all of which were added later. For most of these, the agents fail-open (the field is optional). But for fields like `schedule.vibe_vision_step: false` (which disables the Step A scan), the absence means the default is assumed β€” which may not be what the operator wants. PM Β§5 must add a `config_schema_currency_check` every 20 batches: (1) read `otherness-config-template.yaml` to extract all section keys and their required/optional status; (2) read the project's `otherness-config.yaml` and identify missing sections; (3) for each missing section that is NOT optional (marked with `# OPTIONAL:` comment in template): open a `kind/chore priority/medium` issue: "Config migration: `otherness-config.yaml` is missing section `[section]` added in [date]. Run `/otherness.setup --migrate` to add defaults." Additionally, `/otherness.setup` must support a `--migrate` flag that reads the current config, identifies missing sections from the template, and adds them with default values β€” without overwriting existing values. Without this migration path, config schema debt accumulates silently: operators with long-running projects have stale configs that miss new features, and there is no automated signal that this is happening. ⚠️ Inferred from onboarding lens: a new project added today would get the current config template; but an existing project onboarded three weeks ago is missing fields added since then; there is no migration mechanism and no detection; the onboarding quality guarantee only covers day-zero setup, not ongoing schema currency. + +### Lens 5 β€” Visibility: managed project end-users have no visibility into what otherness shipped for them + +- πŸ”² 54.5 β€” otherness ships PRs to managed projects on behalf of their teams β€” but the end-users (developers on the managed project who are NOT otherness operators) have no summary of what was autonomously shipped to their repo. A developer on a managed project sees PRs appearing from `otherness[bot]` and must read each individual PR to understand what changed and why. There is no periodic summary comment or release-style digest that explains: "This week otherness shipped 3 improvements to your repo. They address: [plain descriptions]." PM Β§5 must add a `managed_project_digest` step every 7 days (tracked via `state.json: last_digest_sent_at`): for each project in `monitor.projects`, (1) query the last 7 days of merged PRs from `otherness[bot]`; (2) if β‰₯1 PR merged: compose a weekly digest comment on the managed project's equivalent report issue (or open a new `kind/docs` issue if none exists): "**otherness weekly digest** β€” past 7 days: N PRs merged. Summary: [1 line per PR: what changed and why in plain English]. Next: [top item in queue]." The comment must be readable without otherness background knowledge β€” no references to Β§4f, no `[NEEDS HUMAN]` format, no design doc references. The digest is for project developers, not system operators. Without this digest, autonomous development is invisible and opaque to the team receiving it β€” they see unannounced changes appearing in their repo without context. This visibility gap is the primary friction point for teams who are benefiting from otherness but have not read the architecture docs. ⚠️ Inferred from visibility lens: a human looking at GitHub right now cannot quickly tell if the system is healthy and what it shipped β€” this is doubly true for managed project developers who are not otherness operators; the weekly digest converts autonomous development from invisible activity to legible collaboration. + +--- + +## Zone 1 β€” Obligations + +| # | Obligation | +|---|---| +| 54.1 | SM Β§4a must add `coord.md` to line-count monitoring (45.8 structural gate): if `wc -l > 1500`, open `kind/chore priority/high` issue. 1,500-line cap is the doc 45 target. | +| 54.2 | SM Β§4g must write `step_a_duration_min` to `state.json`. PM Β§5 must correlate Step A duration >20min with `meaningful_prs=0`. When correlation >40%: open `kind/chore priority/high` issue recommending `timeout-minutes` cap on Step A job. | +| 54.3 | `vibe-vision-auto.md` SCAN 0 must replace fixed 400-item ceiling with dynamic: if `items_shipped_last_10_batches / total_future_items < 0.02` AND `total_future_items > 150`: suppress SCAN 3 and SCAN 5. | +| 54.4 | PM Β§5 must add `config_schema_currency_check` every 20 batches: compare running project config against template; flag missing non-optional sections. `/otherness.setup --migrate` must add missing fields with defaults without overwriting existing values. | +| 54.5 | PM Β§5 must add `managed_project_digest` every 7 days: for each `monitor.projects` entry, post a plain-English weekly summary of merged PRs to the managed project's report issue. Digest must be non-technical β€” for project developers, not otherness operators. | + +## Zone 2 β€” Implementer's judgment + +- 54.1: the structural rewrite of `coord.md` (linear 15-step decision tree) is a larger scope than the line-count gate. The gate must ship first. The structural rewrite is a follow-on item that the gate will force into the queue. +- 54.2: `step_a_duration_min` requires reading `$SECONDS` at Step B start and computing the delta from workflow start. The correlation analysis is a PM Β§5 Python block β€” no new infrastructure needed. +- 54.3: `items_shipped_last_10_batches` is computable from `metrics.md` rows (count rows where `prs_merged > 0` in the last 10 rows). The dynamic ceiling replaces the static 400 check in SCAN 0's if-condition β€” one line change. +- 54.4: The `# OPTIONAL:` comment convention must be added to `otherness-config-template.yaml` for all optional sections. This is the schema annotation step that makes the migration check implementable. +- 54.5: The digest comment must be posted to a dedicated `kind/docs` issue in the managed project titled "otherness automated activity digest" β€” not as a reply to every PR. The issue accumulates digest comments as a weekly log. + +## Zone 3 β€” Scoped out + +- 54.1 does NOT require a structural rewrite of coord.md immediately β€” only the monitoring gate. The rewrite is a follow-on that the gate makes mandatory. +- 54.2 does NOT require wall-clock timing to be perfect β€” an approximation from `$SECONDS` is sufficient for the correlation analysis. +- 54.3 does NOT remove items from the corpus. It only suppresses new-item generation when the rate-based threshold is crossed. +- 54.4 does NOT auto-apply migrations. It flags missing fields and provides a migration command. The operator runs the command. +- 54.5 does NOT post to every PR. It posts to one digest issue per managed project, weekly. The digest must never post if 0 PRs merged in the 7-day window (no noise when quiet). From ed97f9d7d8aaae63973b79fa57549c126b092d4e Mon Sep 17 00:00:00 2001 From: "otherness[bot]" Date: Thu, 23 Apr 2026 07:51:54 +0000 Subject: [PATCH 2/3] 14th scan done, doc 54: 5 new gaps --- .opencode/command/otherness.setup.md | 33 +++- .opencode/command/otherness.status.md | 233 ++++++++++++++++++++++++- .opencode/command/otherness.upgrade.md | 94 +++++++++- 3 files changed, 349 insertions(+), 11 deletions(-) diff --git a/.opencode/command/otherness.setup.md b/.opencode/command/otherness.setup.md index e94f45bf..dd7f245b 100644 --- a/.opencode/command/otherness.setup.md +++ b/.opencode/command/otherness.setup.md @@ -230,18 +230,43 @@ else fi ``` +## Step 8 β€” Deploy otherness scheduled workflow + +The otherness scheduled workflow enables the autonomous loop to run automatically without +human intervention. This step deploys it to `.github/workflows/` from the otherness repo. + +```bash +OTHERNESS_WORKFLOW="$HOME/.otherness/.github/workflows/otherness-scheduled.yml" +TARGET_DIR=".github/workflows" +TARGET_FILE="$TARGET_DIR/otherness-scheduled.yml" + +if [ -f "$TARGET_FILE" ]; then + echo "otherness-scheduled.yml already present β€” skipping." +elif [ ! -f "$OTHERNESS_WORKFLOW" ]; then + echo "⚠️ ~/.otherness/.github/workflows/otherness-scheduled.yml not found." + echo " Ensure ~/.otherness is cloned from pnz1990/otherness and run this setup again." +else + mkdir -p "$TARGET_DIR" + cp "$OTHERNESS_WORKFLOW" "$TARGET_FILE" + echo "Deployed otherness-scheduled.yml to $TARGET_FILE" + # Stage and commit the workflow file + git add "$TARGET_FILE" 2>/dev/null || true + echo "Workflow file staged. Commit and push to activate the scheduled loop." +fi +``` + ## Done Edit `otherness-config.yaml` to set your `BUILD_COMMAND`, `TEST_COMMAND`, `LINT_COMMAND`, and other project-specific values. If your project has a UI, add `project.job_family: FEE`; for platform/infrastructure projects use `SysDE`; backend-only projects can omit the field (defaults to `SDE`). **Before running `/otherness.run`**: edit `docs/aide/vision.md` to describe your project. This is the most important thing β€” the autonomous team reads it on every startup. -**To activate the scheduled loop (optional but recommended):** -The loop can run automatically every 6 hours via GitHub Actions β€” no human needed. +**To activate the scheduled loop:** +The workflow was deployed to `.github/workflows/otherness-scheduled.yml` in Step 8. 1. Go to: GitHub repo β†’ Settings β†’ Secrets and variables β†’ Actions β†’ New repository secret 2. Add `ANTHROPIC_API_KEY` (or your LLM provider key) as a secret name -3. In `otherness-config.yaml`, uncomment the `schedule:` section and set your cron -4. `.github/workflows/otherness-scheduled.yml` is already present and will fire on schedule +3. Commit and push the workflow file (if not already done) +4. The loop will fire automatically on schedule See `docs/design/19-scheduled-execution.md` for full details. diff --git a/.opencode/command/otherness.status.md b/.opencode/command/otherness.status.md index c4dbd273..40df05c6 100644 --- a/.opencode/command/otherness.status.md +++ b/.opencode/command/otherness.status.md @@ -11,7 +11,238 @@ FLEET_MODE=false echo "$ARGS" | grep -q "\-\-fleet" && FLEET_MODE=true ``` -## Step 1 β€” Read state (single-project mode) +## Step 0 β€” Health dashboard (single-project mode, design doc 35 Β§Future β†’ βœ…) + +Skip if `FLEET_MODE=true`. Prints a compact one-page health view readable in 30 seconds. + +```bash +if [ "$FLEET_MODE" != "true" ]; then + +REPO=$(git remote get-url origin 2>/dev/null | sed 's|.*github.com[:/]||;s|\.git$||') + +git fetch origin _state --quiet 2>/dev/null || true +git show origin/_state:.otherness/state.json > .otherness/state.json 2>/dev/null || true + +python3 - << 'DASHBOARD_EOF' +import json, re, os, subprocess, datetime, tempfile + +REPO = os.environ.get('REPO', '') + +print("=" * 60) +print("otherness STATUS") +print("=" * 60) + +# ── 3-line quick glance (design doc 06 Β§Future β†’ βœ…) ───────── +# A human should answer (1) healthy? (2) last shipped? (3) moving? in one glance +try: + ql_health = "UNKNOWN" + ql_last = "(none)" + ql_queue = "?" + try: + metrics_content = open('docs/aide/metrics.md').read() + rows = [] + for line in metrics_content.splitlines(): + if '|' not in line: continue + cells = [c.strip() for c in line.split('|')[1:-1]] + if len(cells) >= 10 and cells[0].startswith('20'): + rows.append(cells[9] if len(cells) > 9 else '?') + if rows: + recent = rows[-3:] + feat = sum(1 for o in recent if o in ('feature-rich', 'mixed')) + ql_health = "ADVANCING" if feat >= 2 else "STALLING" + except Exception: pass + try: + import subprocess as _sp + r = _sp.run(['gh','pr','list','--repo',REPO,'--state','merged','--limit','5', + '--json','title,mergedAt', + '--jq','[.[] | select(.title | test("^feat|^fix|^refactor";"i"))][0].title'], + capture_output=True, text=True, timeout=10) + if r.returncode == 0 and r.stdout.strip() and r.stdout.strip() != 'null': + ql_last = r.stdout.strip().strip('"')[:50] + except Exception: pass + try: + with open('.otherness/state.json') as f: _s = json.load(f) + ql_queue = str(len([d for d in _s.get('features',{}).values() if d.get('state')=='todo'])) + except Exception: pass + print(f"Health: {ql_health} | Last: {ql_last} | Queue: {ql_queue} todo") + print("-" * 60) +except Exception: pass + +# ── Section 1: Health signal with trend ───────────────────── +print() +print("1. HEALTH SIGNAL") +health = "UNKNOWN" +trend = "UNKNOWN" +try: + content = open('docs/aide/metrics.md').read() + rows = [] + for line in content.splitlines(): + if '|' not in line: continue + cells = [c.strip() for c in line.split('|')[1:-1]] + if len(cells) >= 11 and cells[0].startswith('20'): + outcome = cells[9] if len(cells) > 9 else '' + rows.append({'date': cells[0], 'outcome': outcome}) + if rows: + last = rows[-1] + recent = rows[-5:] + feature_count = sum(1 for r in recent if r.get('outcome') in ('feature-rich', 'mixed')) + if feature_count >= 3: + trend = "ADVANCING" + elif feature_count == 2: + trend = "STEADY" + else: + trend = "STALLING" + outcomes = [r.get('outcome','?') for r in recent] + print(f" Trend (last {len(recent)} batches): {trend}") + print(f" Outcomes: {' | '.join(outcomes)}") + else: + print(" Metrics: no batch rows yet") + trend = "UNKNOWN" +except Exception as e: + print(f" Metrics: unavailable ({e})") + +# ── Section 2: Skills ──────────────────────────────────────── +print() +print("2. SKILLS") +try: + skills_dir = os.path.expanduser('~/.otherness/agents/skills') + skill_files = [f for f in os.listdir(skills_dir) + if f.endswith('.md') and f not in ('PROVENANCE.md', 'README.md')] + print(f" Count: {len(skill_files)} skills") + try: + provenance = open(os.path.join(skills_dir, 'PROVENANCE.md')).read() + dates = re.findall(r'^## (\d{4}-\d{2}-\d{2})', provenance, re.MULTILINE) + if dates: + last_learn = datetime.date.fromisoformat(sorted(dates)[-1]) + days_since = (datetime.date.today() - last_learn).days + flag = " ⚠️ OVERDUE" if days_since > 14 else "" + print(f" Last learn: {last_learn} ({days_since}d ago){flag}") + else: + print(" Last learn: never (PROVENANCE.md empty)") + except: + print(" Last learn: unavailable") +except Exception as e: + print(f" Skills: unavailable ({e})") + +# ── Section 3: Queue ───────────────────────────────────────── +print() +print("3. QUEUE") +try: + with open('.otherness/state.json') as f: s = json.load(f) + features = s.get('features', {}) + todo = [(k, v) for k, v in features.items() if v.get('state') == 'todo'] + in_flight = [(k, v) for k, v in features.items() + if v.get('state') in ('assigned', 'in_review')] + PRIORITY_MAP = {'critical': 0, 'high': 1, 'medium': 2, 'low': 3} + todo.sort(key=lambda x: (PRIORITY_MAP.get(x[1].get('priority'), 4), x[0])) + print(f" Todo: {len(todo)} items | In-flight: {len(in_flight)}") + if todo: + next_item = todo[0] + print(f" Next: {next_item[0]} [{next_item[1].get('priority','?')}] {next_item[1].get('title','?')[:55]}") + else: + print(" Next: (queue empty β€” COORD will generate)") +except Exception as e: + print(f" Queue: unavailable ({e})") + +# ── Section 4: Journey status ──────────────────────────────── +print() +print("4. JOURNEYS") +try: + dod = open('docs/aide/definition-of-done.md').read() + journeys = re.findall(r'^## (Journey \d+[^\n]*)', dod, re.MULTILINE) + done_count = len(re.findall(r'βœ…', dod)) + pending_count = len(re.findall(r'πŸ”²', dod)) + print(f" {len(journeys)} journeys | {done_count} βœ… done | {pending_count} πŸ”² pending") + for j in journeys[:5]: + print(f" - {j[:55]}") + if len(journeys) > 5: + print(f" ... +{len(journeys)-5} more") +except Exception as e: + print(f" Journeys: unavailable ({e})") + +# ── Section 5: Simulation ──────────────────────────────────── +print() +print("5. SIMULATION") +state_wt = os.path.join(tempfile.gettempdir(), 'otherness-status-' + str(os.getpid())) +sim_shown = False +try: + if os.path.exists(state_wt): + subprocess.run(['git','worktree','remove',state_wt,'--force'], capture_output=True) + subprocess.run(['git','worktree','add','--no-checkout',state_wt,'origin/_state'], + capture_output=True, check=True) + pred_file = os.path.join(state_wt, '.otherness', 'sim-prediction.json') + subprocess.run(['git','-C',state_wt,'checkout','_state','--','.otherness/sim-prediction.json'], + capture_output=True) + if os.path.exists(pred_file): + pred = json.load(open(pred_file)) + calib_at = pred.get('calibrated_at', '?')[:10] + try: + calib_date = datetime.date.fromisoformat(calib_at) + calib_age = (datetime.date.today() - calib_date).days + calib_flag = " ⚠️ STALE" if calib_age > 14 else "" + except: + calib_age = '?' + calib_flag = '' + arch_conv = float(pred.get('arch_convergence_score', 0)) + arch_flag = " ⚠️ AMBER" if arch_conv >= 0.7 else "" + source = pred.get('source', '?') + print(f" Calibrated: {calib_at} ({calib_age}d ago){calib_flag}") + print(f" Source: {source}") + print(f" arch_convergence: {arch_conv:.3f}{arch_flag}") + print(f" Next batch floor: {pred.get('prs_next_batch_floor','?')} β€” ceiling: {pred.get('prs_next_batch_ceiling','?')}") + sim_shown = True + else: + print(" sim-prediction.json not found on _state branch") +except Exception as e: + print(f" Simulation: unavailable ({e})") +finally: + try: + subprocess.run(['git','worktree','remove',state_wt,'--force'], capture_output=True) + except: pass +subprocess.run(['git','worktree','prune'], capture_output=True) + +# ── Section 6: Reference project health ───────────────────── +print() +print("6. REFERENCE PROJECT") +try: + reference = None + in_monitor = in_projects = False + for line in open('otherness-config.yaml'): + if re.match(r'^monitor:', line): in_monitor = True + if in_monitor and re.match(r'\s+projects:', line): in_projects = True + if in_projects: + m = re.match(r'\s+- (.+)', line) + if m: + r = m.group(1).strip() + if not r.endswith('/otherness'): + reference = r + break + if reference: + r = subprocess.run(['gh','api',f'repos/{reference}/branches/_state', + '--jq','.commit.commit.committer.date'], + capture_output=True, text=True, timeout=10) + if r.returncode == 0 and r.stdout.strip(): + ts = datetime.datetime.fromisoformat(r.stdout.strip().replace('Z','+00:00')) + hours = (datetime.datetime.now(datetime.timezone.utc) - ts).total_seconds() / 3600 + flag = " ⚠️ STALE" if hours > 72 else "" + print(f" {reference}: last activity {hours:.1f}h ago{flag}") + else: + print(f" {reference}: no _state branch (not yet running?)") + else: + print(" No non-otherness project in monitor.projects") +except Exception as e: + print(f" Reference project: unavailable ({e})") + +# ── Summary line ───────────────────────────────────────────── +print() +print(f"Health: {trend} | Run /otherness.run to advance.") +print("=" * 60) +DASHBOARD_EOF + +fi +``` + + Skip if `FLEET_MODE=true`. diff --git a/.opencode/command/otherness.upgrade.md b/.opencode/command/otherness.upgrade.md index e7dcd625..523efdca 100644 --- a/.opencode/command/otherness.upgrade.md +++ b/.opencode/command/otherness.upgrade.md @@ -1,10 +1,10 @@ --- -description: "Show available otherness versions, changelog preview, and guide pinning/unpinning agent_version." +description: "Show available otherness versions, upgrade_policy, changelog preview, and guide pinning/unpinning agent_version." --- You are the otherness version manager. You show available releases, what changed, and help the operator pin or unpin their agent version. -## Step 1 β€” Current pinned version +## Step 1 β€” Current pinned version and upgrade policy ```bash CURRENT_PIN=$(python3 -c " @@ -13,7 +13,17 @@ for line in open('otherness-config.yaml'): m = re.match(r'^\s+agent_version:\s*[\"\'']?([^\"\'#\n]+)[\"\'']?', line) if m: v = m.group(1).strip() - if v not in ('', 'null'): + if v not in ('', 'null', '\"\"', \"''\"): + print(v); break +" 2>/dev/null || echo "") + +UPGRADE_POLICY=$(python3 -c " +import re +for line in open('otherness-config.yaml'): + m = re.match(r'^\s+upgrade_policy:\s*[\"\'']?([^\"\'#\n]+)[\"\'']?', line) + if m: + v = m.group(1).strip() + if v not in ('', 'null', '\"\"', \"''\"): print(v); break " 2>/dev/null || echo "") @@ -27,9 +37,34 @@ else echo "⚠️ WARNING: running version differs from pin β€” may be behind or ahead" fi fi + +if [ -z "$UPGRADE_POLICY" ]; then + echo "Upgrade policy: unset β€” fully pinned, no auto-upgrade" +else + echo "Upgrade policy: $UPGRADE_POLICY" + # Explain what the policy allows + python3 - </dev/null \ @@ -37,10 +72,57 @@ OTHERNESS_REPO=$(git -C ~/.otherness remote get-url origin 2>/dev/null \ echo "" echo "=== Available releases (from $OTHERNESS_REPO) ===" -gh release list --repo "$OTHERNESS_REPO" --limit 10 \ +RELEASES=$(gh release list --repo "$OTHERNESS_REPO" --limit 20 \ --json tagName,name,publishedAt \ --jq '.[] | "\(.tagName) \(.name) (\(.publishedAt[:10]))"' 2>/dev/null \ - || echo "(no releases found β€” repo may be unpinned-only)" + || echo "") + +if [ -n "$RELEASES" ]; then + echo "$RELEASES" +else + echo "(no releases found β€” repo may be unpinned-only)" +fi + +# Show which releases satisfy the upgrade_policy +if [ -n "$UPGRADE_POLICY" ] && [ -n "$RELEASES" ]; then + echo "" + echo "=== Releases allowed by upgrade_policy: $UPGRADE_POLICY ===" + python3 - < Date: Thu, 23 Apr 2026 08:14:26 +0000 Subject: [PATCH 3/3] PR #975 merged: board Status:Todo on create --- .otherness/state.json | 227 +++++++++++++++++++++++------------------- 1 file changed, 125 insertions(+), 102 deletions(-) diff --git a/.otherness/state.json b/.otherness/state.json index 7138df6c..8a928d5f 100644 --- a/.otherness/state.json +++ b/.otherness/state.json @@ -1,32 +1,7 @@ { - "report_issue": 741, - "batch_count": 8, "features": { - "issue-957": { - "state": "done", - "title": "45.5: simplification cycle \u2014 open chore/high issue every 30 batches", - "labels": [ - "area/agent-loop", - "size/xs", - "priority/high", - "kind/enhancement" - ], - "priority": "high", - "issue": 957, - "assigned_to": "sess-6515b10d", - "assigned_at": "2026-04-23T06:01:39Z", - "branch": "feat/issue-957", - "worktree": "../otherness.issue-957", - "file_spaces": [ - "agents/", - "scripts/" - ], - "pr_number": 968, - "pr_merged": true, - "done_at": "2026-04-23T06:06:22Z" - }, "issue-956": { - "state": "todo", + "state": "done", "title": "45.3: COORD issue-creation must always set board Status:Todo and active milestone", "labels": [ "area/agent-loop", @@ -35,11 +10,14 @@ "kind/enhancement" ], "priority": "high", - "issue": 956 + "issue": 956, + "file_spaces": [], + "pr_merged": true, + "done_at": "2026-04-23T08:11:37Z" }, "issue-953": { - "state": "todo", - "title": "feat: Audit and reduce sm.md: identify the top 5 sections by line count that have never demonstr", + "state": "done", + "title": "feat(sm): reduce sm.md from 5,070 to 1,895 lines (45.1)", "labels": [ "area/agent-loop", "size/s", @@ -47,7 +25,17 @@ "kind/enhancement" ], "priority": "high", - "issue": 953 + "issue": 953, + "file_spaces": [ + "agents/" + ], + "assigned_to": "sess-af26c017", + "assigned_at": "2026-04-23T06:54:32Z", + "branch": "feat/issue-953", + "worktree": "../otherness.issue-953", + "pr_number": 971, + "pr_merged": true, + "done_at": "2026-04-23T07:19:22Z" }, "issue-952": { "state": "todo", @@ -59,7 +47,8 @@ "kind/enhancement" ], "priority": "medium", - "issue": 952 + "issue": 952, + "file_spaces": [] }, "issue-951": { "state": "todo", @@ -71,7 +60,8 @@ "kind/enhancement" ], "priority": "medium", - "issue": 951 + "issue": 951, + "file_spaces": [] }, "issue-950": { "state": "todo", @@ -83,7 +73,8 @@ "kind/enhancement" ], "priority": "medium", - "issue": 950 + "issue": 950, + "file_spaces": [] }, "issue-949": { "state": "todo", @@ -95,7 +86,8 @@ "kind/enhancement" ], "priority": "medium", - "issue": 949 + "issue": 949, + "file_spaces": [] }, "issue-948": { "state": "todo", @@ -107,7 +99,8 @@ "kind/enhancement" ], "priority": "medium", - "issue": 948 + "issue": 948, + "file_spaces": [] }, "issue-947": { "state": "todo", @@ -119,7 +112,8 @@ "kind/enhancement" ], "priority": "medium", - "issue": 947 + "issue": 947, + "file_spaces": [] }, "issue-946": { "state": "todo", @@ -131,7 +125,8 @@ "kind/enhancement" ], "priority": "medium", - "issue": 946 + "issue": 946, + "file_spaces": [] }, "issue-944": { "state": "todo", @@ -143,7 +138,8 @@ "kind/enhancement" ], "priority": "medium", - "issue": 944 + "issue": 944, + "file_spaces": [] }, "issue-928": { "state": "todo", @@ -155,7 +151,8 @@ "kind/enhancement" ], "priority": "medium", - "issue": 928 + "issue": 928, + "file_spaces": [] }, "issue-917": { "state": "todo", @@ -167,19 +164,8 @@ "kind/enhancement" ], "priority": "low", - "issue": 917 - }, - "issue-909": { - "state": "todo", - "title": "feat(pm): minor release trigger PM \u00a75l (40.2) \u2014 auto-cut vX.Y.0 when \u22653 feat PRs since last tag", - "labels": [ - "size/s", - "area/tooling", - "priority/high", - "kind/enhancement" - ], - "priority": "high", - "issue": 909 + "issue": 917, + "file_spaces": [] }, "issue-894": { "state": "todo", @@ -191,7 +177,8 @@ "kind/enhancement" ], "priority": "low", - "issue": 894 + "issue": 894, + "file_spaces": [] }, "issue-893": { "state": "todo", @@ -203,7 +190,8 @@ "kind/enhancement" ], "priority": "low", - "issue": 893 + "issue": 893, + "file_spaces": [] }, "issue-884": { "state": "todo", @@ -215,7 +203,8 @@ "kind/enhancement" ], "priority": "medium", - "issue": 884 + "issue": 884, + "file_spaces": [] }, "issue-866": { "state": "todo", @@ -227,7 +216,8 @@ "kind/enhancement" ], "priority": "low", - "issue": 866 + "issue": 866, + "file_spaces": [] }, "issue-865": { "state": "todo", @@ -239,7 +229,8 @@ "kind/enhancement" ], "priority": "low", - "issue": 865 + "issue": 865, + "file_spaces": [] }, "issue-864": { "state": "todo", @@ -251,7 +242,8 @@ "kind/enhancement" ], "priority": "low", - "issue": 864 + "issue": 864, + "file_spaces": [] }, "issue-863": { "state": "todo", @@ -263,7 +255,8 @@ "kind/enhancement" ], "priority": "low", - "issue": 863 + "issue": 863, + "file_spaces": [] }, "issue-862": { "state": "todo", @@ -275,7 +268,8 @@ "kind/enhancement" ], "priority": "low", - "issue": 862 + "issue": 862, + "file_spaces": [] }, "issue-861": { "state": "todo", @@ -287,7 +281,8 @@ "kind/enhancement" ], "priority": "low", - "issue": 861 + "issue": 861, + "file_spaces": [] }, "issue-860": { "state": "todo", @@ -299,7 +294,8 @@ "kind/enhancement" ], "priority": "low", - "issue": 860 + "issue": 860, + "file_spaces": [] }, "issue-859": { "state": "todo", @@ -311,7 +307,8 @@ "kind/enhancement" ], "priority": "low", - "issue": 859 + "issue": 859, + "file_spaces": [] }, "issue-858": { "state": "todo", @@ -323,7 +320,8 @@ "kind/enhancement" ], "priority": "low", - "issue": 858 + "issue": 858, + "file_spaces": [] }, "issue-857": { "state": "todo", @@ -335,7 +333,8 @@ "kind/enhancement" ], "priority": "low", - "issue": 857 + "issue": 857, + "file_spaces": [] }, "issue-856": { "state": "todo", @@ -347,7 +346,8 @@ "kind/enhancement" ], "priority": "low", - "issue": 856 + "issue": 856, + "file_spaces": [] }, "issue-855": { "state": "todo", @@ -359,7 +359,8 @@ "kind/enhancement" ], "priority": "medium", - "issue": 855 + "issue": 855, + "file_spaces": [] }, "issue-854": { "state": "todo", @@ -371,7 +372,8 @@ "kind/enhancement" ], "priority": "medium", - "issue": 854 + "issue": 854, + "file_spaces": [] }, "issue-852": { "state": "todo", @@ -383,7 +385,8 @@ "kind/enhancement" ], "priority": "medium", - "issue": 852 + "issue": 852, + "file_spaces": [] }, "issue-851": { "state": "todo", @@ -395,76 +398,96 @@ "kind/enhancement" ], "priority": "medium", - "issue": 851 + "issue": 851, + "file_spaces": [] }, - "issue-817": { + "issue-808": { "state": "todo", - "title": "feat(observability): deploy AWS observability backend (account 569190534191) and wire all projects", + "title": "feat: Queue composition audit must run every 10 batches and post a plain-language summary: COORD", "labels": [ - "size/l", - "area/tooling", - "priority/high", + "area/agent-loop", + "size/s", + "blocked", + "priority/low", "kind/enhancement" ], - "priority": "high", - "issue": 817 + "priority": "low", + "issue": 808, + "file_spaces": [] }, - "issue-815": { + "issue-718": { "state": "todo", - "title": "feat(scheduled): apply workflow timeout + cleanup step once GH_TOKEN has workflows scope", + "title": "feat: `onboarding-existing-project.md` first-run smoke test section: the onboarding guides for e", "labels": [ "priority/medium", - "size/xs", - "area/tooling", + "area/agent-loop", + "size/s", "kind/enhancement" ], "priority": "medium", - "issue": 815 + "issue": 718, + "file_spaces": [] }, - "issue-808": { + "issue-909": { "state": "todo", - "title": "feat: Queue composition audit must run every 10 batches and post a plain-language summary: COORD", + "title": "feat(pm): minor release trigger PM \u00a75l (40.2) \u2014 auto-cut vX.Y.0 when \u22653 feat PRs since last tag", "labels": [ - "area/agent-loop", "size/s", - "blocked", - "priority/low", + "area/tooling", + "priority/high", "kind/enhancement" ], - "priority": "low", - "issue": 808 + "priority": "high", + "issue": 909, + "file_spaces": [] }, - "issue-745": { + "issue-817": { "state": "todo", - "title": "feat: validate.sh check [8/8]: \u2705 Present items referencing state.json fields must be verifiable", + "title": "feat(observability): deploy AWS observability backend (account 569190534191) and wire all projects", + "labels": [ + "size/l", + "area/tooling", + "priority/high", + "kind/enhancement" + ], + "priority": "high", + "issue": 817, + "file_spaces": [] + }, + "issue-815": { + "state": "todo", + "title": "feat(scheduled): apply workflow timeout + cleanup step once GH_TOKEN has workflows scope", "labels": [ "priority/medium", - "size/s", + "size/xs", "area/tooling", "kind/enhancement" ], "priority": "medium", - "issue": 745 + "issue": 815, + "file_spaces": [] }, - "issue-718": { + "issue-745": { "state": "todo", - "title": "feat: `onboarding-existing-project.md` first-run smoke test section: the onboarding guides for e", + "title": "feat: validate.sh check [8/8]: \u2705 Present items referencing state.json fields must be verifiable", "labels": [ "priority/medium", - "area/agent-loop", "size/s", + "area/tooling", "kind/enhancement" ], "priority": "medium", - "issue": 718 + "issue": 745, + "file_spaces": [] } }, "session_heartbeats": { - "sess-6515b10d": { - "last_seen": "2026-04-23T06:00:49Z", - "item": "coord", - "cycle": 1 + "sess-af26c017": { + "last_seen": "2026-04-23T06:54:32Z", + "item": "issue-953", + "cycle": 2 } }, - "bounded_sessions": {} + "sm_cycle_count": 2, + "batch_count": 2 } \ No newline at end of file