feat(guide): add MILESTONE nav section + 2026-07 release-scope page
CD - Develop (guide → bcos.dev) / build-and-deploy (push) Successful in 1m2s

- New top-level MILESTONE section (bcos-only), peer to PROCESSES, renders
  uppercase via .sec-head; first module is milestone.2026-07 (per-repo
  release-scope view with Gitea filter links).
- Nav UX: all sidebar sections start collapsed; no section/app auto-expands
  on entry; landing pane shows the HiveIQ logo instead of auto-selecting Agent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-10 15:58:15 -04:00
parent 33ed88e07c
commit b2fe064e7d
2 changed files with 59 additions and 8 deletions
@@ -0,0 +1,36 @@
---
module: milestone.2026-07
title: 2026-07
tab: Overview
order: 10
audience: bcos
---
Release scope for the **2026-07** milestone. **BCOS admin only.** One issue = one milestone
(see [[processes.gitea-issues]]); this page is the per-repo view of everything targeted at the
July 2026 release. **32 open** issues across 11 repos as of 2026-07-10 — the bulk in
**incident (13)** and **feedback (11)**.
## Open issues by repo (click to open in Gitea)
| Repo | Open | Filter |
|---|---|---|
| **incident** | 13 | [view](https://hiveiq-gitea.directlx.dev/hiveiq-src/hiveops-incident/issues?type=all&state=open&milestone=1) |
| **feedback** | 11 | [view](https://hiveiq-gitea.directlx.dev/hiveiq-src/hiveops-feedback/issues?type=all&state=open&milestone=47) |
| **reports** | 2 | [view](https://hiveiq-gitea.directlx.dev/hiveiq-src/hiveops-reports/issues?type=all&state=open&milestone=8) |
| **agent** | 1 | [view](https://hiveiq-gitea.directlx.dev/hiveiq-src/hiveops-agent/issues?type=all&state=open&milestone=5) |
| **auth** | 1 | [view](https://hiveiq-gitea.directlx.dev/hiveiq-src/hiveops-auth/issues?type=all&state=open&milestone=6) |
| **ai** | 1 | [view](https://hiveiq-gitea.directlx.dev/hiveiq-src/hiveops-ai/issues?type=all&state=open&milestone=2) |
| **journal** | 1 | [view](https://hiveiq-gitea.directlx.dev/hiveiq-src/hiveops-journal/issues?type=all&state=open&milestone=9) |
| **claims** | 1 | [view](https://hiveiq-gitea.directlx.dev/hiveiq-src/hiveops-claims/issues?type=all&state=open&milestone=7) |
| **browser** | 1 | [view](https://hiveiq-gitea.directlx.dev/hiveiq-src/hiveops-browser/issues?type=all&state=open&milestone=48) |
| **bom** | 0 (1 closed) | [view](https://hiveiq-gitea.directlx.dev/hiveiq-src/hiveops-bom/issues?type=all&state=all&milestone=3) |
| **devices** | 0 | [view](https://hiveiq-gitea.directlx.dev/hiveiq-src/hiveops-devices/issues?type=all&state=all&milestone=49) |
> **Note:** `milestone=<id>` is the **per-repo** numeric id — a `2026-07` link differs per repo.
> The counts above are a point-in-time snapshot; the links are always live.
## Everything at once (cross-repo rollup)
`GET /repos/issues/search?state=open&milestones=2026-07&owner=hiveiq-src` — one query, all repos,
no ids. See the milestone-viewing section of [[processes.gitea-issues]] for the copy-paste
one-liner that regenerates this table for any month.
+23 -8
View File
@@ -16,8 +16,9 @@
let activeModuleKey = '';
let activeTab = 0;
let search = '';
// collapse state: 'modules' | 'platform' | 'technical' | 'app:<name>'
let open: Record<string, boolean> = { modules: true };
// collapse state: 'modules' | 'platform' | 'technical' | 'milestone' | 'app:<name>'
// all sections start collapsed on load (no section auto-expands on entry)
let open: Record<string, boolean> = {};
function toggle(key: string) { open = { ...open, [key]: !open[key] }; }
function expandFor(key: string) {
const app = key.split('.')[0];
@@ -82,21 +83,19 @@
// group nav: product-app "Modules" section (all except platform/technical) + platform + technical
$: searching = !!search.trim();
const SPECIAL = ['platform', 'devops', 'technical', 'processes'];
const SPECIAL = ['platform', 'devops', 'technical', 'processes', 'milestone'];
$: productApps = filtered.filter(a => !SPECIAL.includes(a.app));
$: platformApp = filtered.find(a => a.app === 'platform') ?? null;
$: devopsApp = filtered.find(a => a.app === 'devops') ?? null;
$: technicalApp = filtered.find(a => a.app === 'technical') ?? null;
$: processesApp = filtered.find(a => a.app === 'processes') ?? null;
$: milestoneApp = filtered.find(a => a.app === 'milestone') ?? null;
async function loadNav() {
loadingNav = true;
try {
nav = await fetchNav();
// auto-select the first product module (or first available)
const first = (nav.find(a => a.app !== 'platform' && a.app !== 'technical' && a.modules.length)
?? nav.find(a => a.modules.length))?.modules[0];
if (first) { expandFor(first.module); selectModule(first.module); }
// no auto-select on entry: land on the HiveIQ icon with every section collapsed
} catch (e: any) {
addToast('error', 'Failed to load guides', e?.response?.data?.message ?? e?.message ?? '');
} finally {
@@ -224,6 +223,21 @@
{/if}
</div>
{/if}
<!-- MILESTONE (release scope — BCOS admin only) -->
{#if milestoneApp}
<div class="nav-sec">
<button class="sec-head" on:click={() => toggle('milestone')}>
<span class="chev">{(searching || open['milestone']) ? '▾' : '▸'}</span> Milestone
</button>
{#if (searching || open['milestone'])}
{#each milestoneApp.modules as m (m.module)}
<button class="nav-item" class:active={m.module === activeModuleKey}
on:click={() => selectModule(m.module)} title={m.module}>{m.title}</button>
{/each}
{/if}
</div>
{/if}
{/if}
</nav>
@@ -243,7 +257,7 @@
{#if loadingModule}
<div class="content-msg"><div class="spinner"></div></div>
{:else if !module}
<div class="content-msg">Select a guide from the left.</div>
<div class="content-msg"><img src="/hiveiq_logo.png" alt="HiveIQ" class="landing-logo" /></div>
{:else}
<div class="content-head">
<div class="content-title">{module.title}</div>
@@ -435,6 +449,7 @@
/* ── Content ─────────────────────────────────────────── */
.content { flex: 1; display: flex; flex-direction: column; overflow: hidden; background: #0b1220; }
.content-msg { flex: 1; display: flex; align-items: center; justify-content: center; color: #94a3b8; }
.landing-logo { width: min(340px, 55%); height: auto; opacity: 0.9; }
.spinner { width: 32px; height: 32px; border: 3px solid #e5e7eb; border-top-color: #2563eb; border-radius: 50%; animation: spin 0.7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }