@chllming/wave-orchestration
Advanced tools
| # Recommendations for 0.9.12 | ||
| ## Upgrade | ||
| ```bash | ||
| wave self-update | ||
| # or: npm install -g @chllming/wave-orchestration@0.9.12 | ||
| ``` | ||
| ## What changed | ||
| ### Low-entropy closure is now explicit | ||
| Bootstrap closure keeps its fast path, but it is now constrained to the cases where closure actually stayed lightweight. If semantic closure stewards already ran, the launcher no longer skips a missing `cont-QA` run as if nothing meaningful happened. | ||
| Practical effect: | ||
| - low-entropy bootstrap waves still avoid unnecessary closeout churn | ||
| - waves that escalated into real semantic closure work now keep the stronger closeout contract | ||
| - closure metadata and mode resolution now agree about when bootstrap behavior applies | ||
| ### TMUX is optional, not the execution backend | ||
| The packaged docs, setup flow, and launcher help now all say the same thing: | ||
| - live agents run as detached processes | ||
| - `vscode` and `tmux` only change the operator-facing dashboard or projection surface | ||
| - `tmux` matters only when you actually want terminal-native dashboard attach | ||
| If you launch with `--terminal-surface tmux --no-dashboard`, Wave now prints an explicit note that TMUX is optional in that shape. | ||
| ### Wave Control dashboard-first UI | ||
| The shipped `wave-control-web` surface is now organized around: | ||
| - `Dashboard` | ||
| - `Operations` | ||
| - `Access` | ||
| - `Account` | ||
| Operators get a cleaner summary-first landing page, better access-review routing, and richer benchmark or run analytics without hunting across flat tabs. | ||
| ## Recommendations | ||
| - **Closure policy**: keep the bootstrap fast path for genuinely low-entropy work, but do not treat it as a general excuse to skip `cont-QA` after integration or documentation stewards already had to intervene. | ||
| - **Operator surfaces**: choose `vscode` or `tmux` based on where you want to follow logs and dashboards. Do not encode TMUX as if it were required for live execution. | ||
| - **Budgets**: keep using `budget.minutes` as the main wall-clock budget. Keep generic `budget.turns` advisory unless you deliberately need a runtime-specific hard ceiling. | ||
| - **Coordination severity**: continue to use `mark-advisory`, `mark-stale`, and `resolve-policy` for follow-up that should stay visible without falsely reopening proof-critical closure. | ||
| - **Targeted recovery**: prefer targeted recovery when one slice regresses. The lower-entropy closure path is most useful when the remaining work is genuinely narrow and machine-visible. |
| function normalizeBoolean(value, fallback = false) { | ||
| if (value === undefined || value === null || value === "") { | ||
| return fallback; | ||
| } | ||
| if (typeof value === "boolean") { | ||
| return value; | ||
| } | ||
| const normalized = String(value || "") | ||
| .trim() | ||
| .toLowerCase(); | ||
| if (["true", "1", "yes", "on"].includes(normalized)) { | ||
| return true; | ||
| } | ||
| if (["false", "0", "no", "off"].includes(normalized)) { | ||
| return false; | ||
| } | ||
| return fallback; | ||
| } | ||
| function normalizeThreshold(value, fallback) { | ||
| if (value === null || value === undefined || value === "") { | ||
| return fallback; | ||
| } | ||
| const parsed = Number.parseInt(String(value), 10); | ||
| return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback; | ||
| } | ||
| function contradictionList(value) { | ||
| if (!value) { | ||
| return []; | ||
| } | ||
| if (value instanceof Map) { | ||
| return Array.from(value.values()); | ||
| } | ||
| if (Array.isArray(value)) { | ||
| return value; | ||
| } | ||
| if (typeof value === "object") { | ||
| return Object.values(value); | ||
| } | ||
| return []; | ||
| } | ||
| function openCoordinationRecords(records = []) { | ||
| return (Array.isArray(records) ? records : []).filter( | ||
| (record) => | ||
| !["resolved", "closed", "cancelled", "superseded"].includes( | ||
| String(record?.status || "") | ||
| .trim() | ||
| .toLowerCase(), | ||
| ), | ||
| ); | ||
| } | ||
| function closureSignalsFromDerivedState(derivedState = {}) { | ||
| const integrationSummary = derivedState?.integrationSummary || {}; | ||
| const docsQueueItems = Array.isArray(derivedState?.docsQueue?.items) | ||
| ? derivedState.docsQueue.items | ||
| : []; | ||
| const coordinationState = derivedState?.coordinationState || {}; | ||
| const clarificationBarrier = derivedState?.clarificationBarrier || { ok: true }; | ||
| const helperAssignmentBarrier = derivedState?.helperAssignmentBarrier || { ok: true }; | ||
| const dependencyBarrier = derivedState?.dependencyBarrier || { ok: true }; | ||
| const securitySummary = derivedState?.securitySummary || null; | ||
| const corridorSummary = | ||
| derivedState?.corridorSummary || derivedState?.securitySummary?.corridor || null; | ||
| const blockingContradictions = contradictionList(derivedState?.contradictions).filter( | ||
| (entry) => | ||
| ["blocking", "high"].includes(String(entry?.severity || "").trim().toLowerCase()) && | ||
| ((Array.isArray(entry?.impactedGates) && entry.impactedGates.includes("integrationBarrier")) || | ||
| !Array.isArray(entry?.impactedGates) || | ||
| entry.impactedGates.length === 0) && | ||
| !["resolved", "closed", "cleared"].includes( | ||
| String(entry?.status || "") | ||
| .trim() | ||
| .toLowerCase(), | ||
| ), | ||
| ); | ||
| const openClarifications = openCoordinationRecords(coordinationState?.clarifications); | ||
| const openHuman = [ | ||
| ...openCoordinationRecords(coordinationState?.humanEscalations), | ||
| ...openCoordinationRecords(coordinationState?.humanFeedback), | ||
| ]; | ||
| const blockingAssignments = (Array.isArray(derivedState?.capabilityAssignments) | ||
| ? derivedState.capabilityAssignments | ||
| : [] | ||
| ).filter((assignment) => assignment?.blocking !== false); | ||
| const openDependencies = [ | ||
| ...((Array.isArray(derivedState?.dependencySnapshot?.openInbound) | ||
| ? derivedState.dependencySnapshot.openInbound | ||
| : []) || []), | ||
| ...((Array.isArray(derivedState?.dependencySnapshot?.openOutbound) | ||
| ? derivedState.dependencySnapshot.openOutbound | ||
| : []) || []), | ||
| ...((Array.isArray(derivedState?.dependencySnapshot?.unresolvedInboundAssignments) | ||
| ? derivedState.dependencySnapshot.unresolvedInboundAssignments | ||
| : []) || []), | ||
| ]; | ||
| const sharedPlanItems = docsQueueItems.filter((item) => item?.kind === "shared-plan"); | ||
| const componentMatrixItems = docsQueueItems.filter((item) => item?.kind === "component-matrix"); | ||
| return { | ||
| integrationReady: | ||
| integrationSummary?.recommendation === "ready-for-doc-closure", | ||
| openClaims: Array.isArray(integrationSummary?.openClaims) ? integrationSummary.openClaims : [], | ||
| conflictingClaims: Array.isArray(integrationSummary?.conflictingClaims) | ||
| ? integrationSummary.conflictingClaims | ||
| : [], | ||
| unresolvedBlockers: Array.isArray(integrationSummary?.unresolvedBlockers) | ||
| ? integrationSummary.unresolvedBlockers | ||
| : [], | ||
| changedInterfaces: Array.isArray(integrationSummary?.changedInterfaces) | ||
| ? integrationSummary.changedInterfaces | ||
| : [], | ||
| crossComponentImpacts: Array.isArray(integrationSummary?.crossComponentImpacts) | ||
| ? integrationSummary.crossComponentImpacts | ||
| : [], | ||
| proofGaps: Array.isArray(integrationSummary?.proofGaps) ? integrationSummary.proofGaps : [], | ||
| docGaps: Array.isArray(integrationSummary?.docGaps) ? integrationSummary.docGaps : [], | ||
| deployRisks: Array.isArray(integrationSummary?.deployRisks) | ||
| ? integrationSummary.deployRisks | ||
| : [], | ||
| inboundDependencies: Array.isArray(integrationSummary?.inboundDependencies) | ||
| ? integrationSummary.inboundDependencies | ||
| : [], | ||
| outboundDependencies: Array.isArray(integrationSummary?.outboundDependencies) | ||
| ? integrationSummary.outboundDependencies | ||
| : [], | ||
| helperAssignments: Array.isArray(integrationSummary?.helperAssignments) | ||
| ? integrationSummary.helperAssignments | ||
| : [], | ||
| sharedPlanItems, | ||
| componentMatrixItems, | ||
| blockingContradictions, | ||
| openClarifications, | ||
| openHuman, | ||
| blockingAssignments, | ||
| openDependencies, | ||
| clarificationBarrier, | ||
| helperAssignmentBarrier, | ||
| dependencyBarrier, | ||
| securityState: | ||
| integrationSummary?.securityState || securitySummary?.overallState || "not-applicable", | ||
| corridorSummary, | ||
| }; | ||
| } | ||
| export function resolveClosureMode(waveNumber, thresholds) { | ||
| if (!thresholds) { | ||
| return "strict"; | ||
| } | ||
| const bootstrapStart = normalizeThreshold(thresholds.bootstrap, 0); | ||
| const standardStart = Math.max( | ||
| bootstrapStart, | ||
| normalizeThreshold(thresholds.standard, 4), | ||
| ); | ||
| const strictStart = Math.max( | ||
| standardStart, | ||
| normalizeThreshold(thresholds.strict, 10), | ||
| ); | ||
| if (waveNumber >= strictStart) { | ||
| return "strict"; | ||
| } | ||
| if (waveNumber >= standardStart) { | ||
| return "standard"; | ||
| } | ||
| return "bootstrap"; | ||
| } | ||
| export function resolveClosurePolicyConfig(source = {}) { | ||
| const validation = source?.laneProfile?.validation || source?.validation || {}; | ||
| const rawThresholds = | ||
| source?.closureModeThresholds || validation?.closureModeThresholds || null; | ||
| const rawAutoClosure = source?.autoClosure || validation?.autoClosure || {}; | ||
| return { | ||
| closureModeThresholds: { | ||
| bootstrap: normalizeThreshold(rawThresholds?.bootstrap, 0), | ||
| standard: normalizeThreshold(rawThresholds?.standard, 4), | ||
| strict: normalizeThreshold(rawThresholds?.strict, 10), | ||
| }, | ||
| autoClosure: { | ||
| allowInferredIntegration: normalizeBoolean( | ||
| rawAutoClosure?.allowInferredIntegration, | ||
| false, | ||
| ), | ||
| allowAutoDocNoChange: normalizeBoolean( | ||
| rawAutoClosure?.allowAutoDocNoChange, | ||
| false, | ||
| ), | ||
| allowAutoDocProjection: normalizeBoolean( | ||
| rawAutoClosure?.allowAutoDocProjection, | ||
| false, | ||
| ), | ||
| allowSkipContQaInBootstrap: normalizeBoolean( | ||
| rawAutoClosure?.allowSkipContQaInBootstrap, | ||
| false, | ||
| ), | ||
| }, | ||
| }; | ||
| } | ||
| export function classifyClosureComplexity(derivedState = {}) { | ||
| const signals = closureSignalsFromDerivedState(derivedState); | ||
| const hasStrictSignals = | ||
| signals.blockingContradictions.length > 0 || | ||
| signals.openClarifications.length > 0 || | ||
| signals.openHuman.length > 0 || | ||
| signals.clarificationBarrier?.ok === false || | ||
| signals.helperAssignmentBarrier?.ok === false || | ||
| signals.dependencyBarrier?.ok === false || | ||
| signals.securityState === "blocked" || | ||
| signals.corridorSummary?.blocking === true || | ||
| (signals.corridorSummary?.ok === false && | ||
| signals.corridorSummary?.requiredAtClosure !== false); | ||
| if (hasStrictSignals) { | ||
| return "strict-full-closure"; | ||
| } | ||
| const hasSemanticIntegrationSignals = | ||
| signals.openClaims.length > 0 || | ||
| signals.conflictingClaims.length > 0 || | ||
| signals.unresolvedBlockers.length > 0 || | ||
| signals.changedInterfaces.length > 0 || | ||
| signals.crossComponentImpacts.length > 0 || | ||
| signals.proofGaps.length > 0 || | ||
| signals.deployRisks.length > 0 || | ||
| signals.helperAssignments.length > 0 || | ||
| signals.inboundDependencies.length > 0 || | ||
| signals.outboundDependencies.length > 0 || | ||
| signals.blockingAssignments.length > 0 || | ||
| signals.openDependencies.length > 0; | ||
| if (hasSemanticIntegrationSignals) { | ||
| return "semantic-integration"; | ||
| } | ||
| if (signals.sharedPlanItems.length > 0) { | ||
| return "semantic-docs"; | ||
| } | ||
| return "low-entropy"; | ||
| } | ||
| export function evaluateInferredIntegrationClosure(derivedState = {}, source = {}) { | ||
| const policy = resolveClosurePolicyConfig(source); | ||
| if (!policy.autoClosure.allowInferredIntegration) { | ||
| return null; | ||
| } | ||
| const signals = closureSignalsFromDerivedState(derivedState); | ||
| if (!signals.integrationReady) { | ||
| return null; | ||
| } | ||
| const hasSemanticSignals = | ||
| signals.openClaims.length > 0 || | ||
| signals.conflictingClaims.length > 0 || | ||
| signals.unresolvedBlockers.length > 0 || | ||
| signals.changedInterfaces.length > 0 || | ||
| signals.crossComponentImpacts.length > 0 || | ||
| signals.proofGaps.length > 0 || | ||
| signals.deployRisks.length > 0 || | ||
| signals.helperAssignments.length > 0 || | ||
| signals.inboundDependencies.length > 0 || | ||
| signals.outboundDependencies.length > 0 || | ||
| signals.blockingContradictions.length > 0 || | ||
| signals.openClarifications.length > 0 || | ||
| signals.openHuman.length > 0 || | ||
| signals.clarificationBarrier?.ok === false || | ||
| signals.helperAssignmentBarrier?.ok === false || | ||
| signals.dependencyBarrier?.ok === false || | ||
| signals.blockingAssignments.length > 0 || | ||
| signals.openDependencies.length > 0 || | ||
| signals.securityState === "blocked" || | ||
| signals.corridorSummary?.blocking === true || | ||
| (signals.corridorSummary?.ok === false && | ||
| signals.corridorSummary?.requiredAtClosure !== false); | ||
| if (hasSemanticSignals) { | ||
| return null; | ||
| } | ||
| return { | ||
| ok: true, | ||
| state: "inferred", | ||
| statusCode: "pass", | ||
| detail: | ||
| "Integration closure was inferred from derived state; no semantic integration contradictions or blockers remain.", | ||
| }; | ||
| } | ||
| export function evaluateDocumentationAutoClosure( | ||
| derivedState = {}, | ||
| source = {}, | ||
| options = {}, | ||
| ) { | ||
| const policy = resolveClosurePolicyConfig(source); | ||
| const signals = closureSignalsFromDerivedState(derivedState); | ||
| const componentMatrixGate = options.componentMatrixGate || { ok: true }; | ||
| if ( | ||
| policy.autoClosure.allowAutoDocNoChange && | ||
| signals.sharedPlanItems.length === 0 && | ||
| signals.componentMatrixItems.length === 0 | ||
| ) { | ||
| return { | ||
| ok: true, | ||
| state: "no-change", | ||
| statusCode: "pass", | ||
| detail: | ||
| "Documentation closure was auto-satisfied because derived state shows no shared-plan or component-matrix delta.", | ||
| }; | ||
| } | ||
| if ( | ||
| policy.autoClosure.allowAutoDocProjection && | ||
| signals.sharedPlanItems.length === 0 && | ||
| signals.componentMatrixItems.length > 0 && | ||
| componentMatrixGate.ok | ||
| ) { | ||
| return { | ||
| ok: true, | ||
| state: "auto-closed", | ||
| statusCode: "pass", | ||
| detail: | ||
| "Documentation closure was auto-satisfied because only mechanical component-matrix reconciliation remained and the canonical matrix is already current.", | ||
| }; | ||
| } | ||
| return null; | ||
| } |
+17
-0
| # Changelog | ||
| ## 0.9.12 - 2026-04-08 | ||
| ### Added | ||
| - `docs/guides/recommendations-0.9.12.md` with the current operating guidance for advisory turn budgets, targeted recovery, low-entropy closure, and optional TMUX operator surfaces. | ||
| ### Changed | ||
| - TMUX is now described consistently as an optional dashboard/projection layer across setup, launcher help, autonomous help, runbooks, and examples. Live agents remain process-backed, and `tmux + --no-dashboard` now emits an explicit informational note instead of implying TMUX is part of the execution backend. | ||
| - Wave Control's browser surface now uses a dashboard-first information architecture with `Dashboard`, `Operations`, `Access`, and `Account` views, cleaner section navigation, and richer summaries for runs, benchmarks, and access review work. | ||
| - Release docs, migration guidance, runtime-config references, package-publishing docs, the release manifest, and tracked install-state fixtures now align on the `0.9.12` surface. | ||
| ### Fixed | ||
| - Bootstrap closure no longer silently skips a missing `cont-QA` run after semantic closure stewards already ran. The low-entropy fast path now stays limited to genuinely lightweight closure attempts. | ||
| - `closureModeThresholds.bootstrap` now participates in runtime mode resolution instead of being normalized and then ignored. | ||
| - Derived `closureComplexity` now incorporates clarification, helper-assignment, dependency, and contradiction barriers so emitted closure metadata matches the real closure state machine. | ||
| - Wave Control benchmark and run projections now expose richer status, comparison-readiness, item, review, and verification rollups for both API consumers and the browser UI. | ||
| - `normalizeWaveVerdict()` now preserves `hold` as its own verdict instead of collapsing it into `concerns`, which brings the shared parser back in line with the shipped verdict grammar and tests. | ||
| ## 0.9.11 - 2026-04-07 | ||
@@ -4,0 +21,0 @@ |
@@ -91,2 +91,2 @@ # Oversight, Dark-Factory, And Human Feedback | ||
| The stricter execution semantics are still future work, not a hidden already-finished feature in `0.9.2`. | ||
| The stricter execution semantics are still future work, not a hidden already-finished feature in `0.9.12`. |
@@ -77,3 +77,3 @@ # Authoring And Running Waves | ||
| The starter contract in `0.9.2` is: | ||
| The starter contract in `0.9.12` is: | ||
@@ -152,2 +152,3 @@ - import `docs/agents/wave-design-role.md` | ||
| pnpm exec wave launch --lane main --start-wave 1 --end-wave 1 --terminal-surface vscode | ||
| pnpm exec wave launch --lane main --start-wave 1 --end-wave 1 --no-dashboard | ||
| pnpm exec wave launch --lane main --start-wave 1 --end-wave 1 --terminal-surface tmux --keep-sessions | ||
@@ -161,3 +162,3 @@ ``` | ||
| - `--keep-sessions` | ||
| Preserve tmux sessions for inspection after the wave completes. | ||
| Preserve tmux dashboard and projection sessions for inspection after the wave completes. | ||
| - `--keep-terminals` | ||
@@ -164,0 +165,0 @@ Preserve temporary VS Code terminal entries. |
@@ -9,3 +9,3 @@ # Planner Guide | ||
| The published `0.9.2` package already includes the optional `design` worker role for pre-implementation design packets. This guide calls out where that affects drafting. | ||
| The published `0.9.12` package already includes the optional `design` worker role for pre-implementation design packets. This guide calls out where that affects drafting. | ||
@@ -52,3 +52,3 @@ ## What Ships Today | ||
| Those remain future work outside the current `0.9.2` release line. The planner foundation is about better structured authoring, not a second execution engine. | ||
| Those remain future work outside the current `0.9.12` release line. The planner foundation is about better structured authoring, not a second execution engine. | ||
@@ -75,3 +75,3 @@ ## Project Profile | ||
| - default oversight mode | ||
| - default terminal surface for live runs (`vscode` or `tmux`; `none` remains dry-run only) | ||
| - default terminal surface for live runs (`vscode` or `tmux`; `none` remains dry-run only). This is an operator viewing preference, not the agent execution backend. | ||
| - default draft template | ||
@@ -78,0 +78,0 @@ - default lane |
@@ -11,3 +11,3 @@ # Running Wave In Sandboxed Environments | ||
| The core rule in `0.9.3` is simple: | ||
| The core rule in `0.9.12` is simple: | ||
@@ -98,3 +98,3 @@ - clients should be short-lived | ||
| Docker works well with the `0.9.3` process-backed runner model, but only if the state directories survive container restarts. | ||
| Docker works well with the `0.9.12` process-backed runner model, but only if the state directories survive container restarts. | ||
@@ -101,0 +101,0 @@ Recommended container posture: |
@@ -60,3 +60,3 @@ # Terminal Surfaces And Dashboards | ||
| Those commands work for both `tmux` and `vscode` terminal surfaces because the live dashboard projections still run on the lane tmux socket. If no live dashboard session exists, the attach command falls back to the last written dashboard JSON instead of failing immediately. | ||
| Those commands work for both `tmux` and `vscode` terminal surfaces because live dashboard projection sessions currently use the lane tmux socket when dashboards are enabled. If no live dashboard session exists, the attach command falls back to the last written dashboard JSON instead of failing immediately. | ||
@@ -63,0 +63,0 @@ When `--terminal-surface vscode` is active, Wave also maintains a stable current-wave dashboard terminal entry instead of creating a new wave-numbered dashboard attach target for every wave transition. |
| # Current State | ||
| - The published package is `0.9.4`; that release keeps the shipped monorepo, design-role, signal-hygiene, detached process-runner, and sandbox supervisor surfaces, and now also accepts `gap` as a valid wave-gate dimension value (alongside `pass`, `concerns`, and `blocked`) so that agents reporting a documented gap no longer trigger missing-wave-gate failures. First-time `wave launch` now auto-triggers `wave project setup` when no project profile exists, and the interactive setup flow shows descriptive help text and inline option explanations. The current authenticated Wave Control plus Corridor-backed security surface continues to ship in this repo. | ||
| - The published package is `0.9.12`; that release keeps the shipped monorepo, design-role, signal-hygiene, detached process-runner, and sandbox supervisor surfaces, and adds a cleaner low-entropy closure fast path plus a release-surface sweep that makes TMUX explicitly optional across setup, launcher help, and operator docs. The current authenticated Wave Control plus Corridor-backed security surface continues to ship in this repo, with the browser UI now organized around dashboard-first navigation and richer run or benchmark analytics summaries. | ||
| - The canonical shipped runtime architecture is documented in `docs/plans/end-state-architecture.md`; the sandbox-runtime companion is `docs/plans/sandbox-end-state-architecture.md`; historical cutover notes remain in `docs/plans/architecture-hardening-migration.md`. | ||
| - The repository contains the published `@chllming/wave-orchestration` package plus the starter scaffold used by `wave init`. | ||
| - The runtime is package-first and non-destructive for adopting repos: `wave init --adopt-existing` records existing repo-owned plans, waves, prompts, and config without overwriting them, and `wave upgrade` writes only `.wave/install-state.json` plus `.wave/upgrade-history/`. | ||
| - The recommended `0.9.4` operating stance is documented in `docs/guides/recommendations-0.9.4.md`: keep proof and closure strict, keep generic `budget.turns` advisory, and use softer coordination states only for non-proof follow-up. | ||
| - The recommended `0.9.12` operating stance is documented in `docs/guides/recommendations-0.9.12.md`: keep proof and closure strict, keep generic `budget.turns` advisory, use targeted recovery for low-entropy closure work, and treat TMUX as an optional operator surface rather than a runtime requirement. | ||
| - Sandbox-safe setup guidance now ships in `docs/guides/sandboxed-environments.md`: use `wave submit/supervise/status/wait/attach` for short-lived clients, keep `tmux` optional and dashboard-only, and preserve `.tmp/` plus `.wave/` when running inside Nemoshell or Docker. | ||
@@ -12,3 +12,3 @@ - Runtime launch entrypoints now perform a best-effort npmjs version check, cache the result under `.wave/package-update-check.json`, and point operators at `pnpm exec wave self-update` when a newer published package exists. | ||
| - `services/wave-control/` is the backend for typed telemetry, Stack-authenticated app users, Wave-managed approval states and provider grants, PATs, dedicated service tokens, encrypted per-user credential storage, runtime env leasing, and owned broker routes for Context7 or Corridor | ||
| - `services/wave-control-web/` is the Vite/Lit browser frontend that signs in through Stack, persists the browser session, exposes overview/runs/benchmarks/tokens, and adds superuser-only user, provider-grant, and write-only credential management | ||
| - `services/wave-control-web/` is the Vite/Lit browser frontend that signs in through Stack, persists the browser session, exposes dashboard-first navigation across runs, benchmarks, tokens, and access review, and adds superuser-only user, provider-grant, and write-only credential management | ||
| - This source repo is itself kept as an adopted Wave workspace, so `node scripts/wave.mjs doctor --json` should pass from the repo root. | ||
@@ -15,0 +15,0 @@ - The default lane is `main`. |
| # End-State Architecture | ||
| This document describes the canonical architecture for the current Wave runtime. It is the authoritative reference for the engine boundaries, canonical authority set, and artifact ownership model that the shipped `0.9.2` surface now follows. | ||
| This document describes the canonical architecture for the current Wave runtime. It is the authoritative reference for the engine boundaries, canonical authority set, and artifact ownership model that the shipped `0.9.12` surface now follows. | ||
@@ -5,0 +5,0 @@ For the sandbox-specific execution model, including async supervisor ownership, daemon adoption goals, and forwarded closure-gap behavior, read [sandbox-end-state-architecture.md](./sandbox-end-state-architecture.md). |
| # Wave 12 - Optional Design Steward Handoff | ||
| This is a showcase-first sample wave for the shipped `design` worker role in `0.9.2`. | ||
| This is a showcase-first sample wave for the shipped `design` worker role in `0.9.12`. | ||
@@ -5,0 +5,0 @@ This example demonstrates the docs-first design-steward path where a design packet is published before code-owning implementation begins. |
@@ -5,3 +5,3 @@ # Wave 14 - Example Full Modern Release Surface | ||
| Use it as the single reference example for the current `0.9.2` Wave surface. | ||
| Use it as the single reference example for the current `0.9.12` Wave surface. | ||
@@ -8,0 +8,0 @@ It intentionally combines more sections than a normal production wave so one file can demonstrate: |
+32
-28
| # Migration | ||
| This page is the practical repo-upgrade guide for the current `0.9.10` surface. | ||
| This page is the practical repo-upgrade guide for the current `0.9.12` surface. | ||
@@ -16,14 +16,18 @@ Use it when you are: | ||
| ## What `0.9.4` Changes | ||
| ## What `0.9.12` Changes | ||
| The `0.9.4` surface adds laddered gate modes and fixes the steward threshold enforcement. | ||
| The `0.9.12` surface keeps the existing proof-first runtime and adds one focused closure fix plus a broad operator-surface cleanup. | ||
| - **Laddered gate modes**: bootstrap (waves 0-3), standard (4-9), strict (10+). Bootstrap mode requires only implementation agent exit 0 and deliverables exist — no formal QA signals needed. | ||
| - **Steward threshold fix**: `requireDocumentationStewardFromWave` is now strictly respected. Previously it was OR'd with `componentPromotionRuleActive`. | ||
| - **New config fields**: `gateModeThresholds`, `bootstrapPassConditions`, `testCommand`, `testCommandTimeout`. | ||
| - **No breaking changes**: existing repos get bootstrap mode for waves 0-3 by default. | ||
| - **Hybrid closure fast path**: bootstrap closure still supports low-entropy waves, but a wave no longer skips missing `cont-QA` once semantic closure stewards already ran. | ||
| - **Closure policy wiring**: `closureModeThresholds.bootstrap` now actually affects runtime mode resolution, and derived closure-complexity metadata now includes the real barrier set. | ||
| - **Optional TMUX language**: setup prompts, launcher help, docs, and canned commands now all describe TMUX as an optional dashboard/projection layer instead of a required execution backend. | ||
| - **Wave Control operator UI**: the browser surface is now dashboard-first and exposes richer run, benchmark, and access summaries. | ||
| There are no breaking changes. Existing repos can upgrade in place with `pnpm up @chllming/wave-orchestration` and `pnpm exec wave upgrade`. | ||
| For the practical `0.9.12` operating stance after the upgrade, read [../guides/recommendations-0.9.12.md](../guides/recommendations-0.9.12.md). | ||
| ## What `0.9.4` Changes | ||
| The current `0.9.10` surface keeps everything from `0.9.2` and adds two focused improvements with no breaking changes. | ||
| The current `0.9.12` surface keeps everything from `0.9.2` and adds two focused improvements with no breaking changes. | ||
@@ -44,7 +48,7 @@ The practical changes are: | ||
| For the practical `0.9.4` operating stance after the upgrade, read [../guides/recommendations-0.9.4.md](../guides/recommendations-0.9.4.md). | ||
| For the practical `0.9.12` operating stance after the upgrade, read [../guides/recommendations-0.9.12.md](../guides/recommendations-0.9.12.md). | ||
| ## What `0.9.2` Changes | ||
| The current `0.9.2` surface keeps the packaged operator-guidance alignment, monorepo project support, and project-aware default telemetry from `0.9.0`, but adds a more sandbox-friendly execution model and lower-overhead live orchestration. | ||
| The `0.9.2` release established the packaged operator-guidance alignment, monorepo project support, and project-aware default telemetry from `0.9.0`, then added a more sandbox-friendly execution model and lower-overhead live orchestration. | ||
@@ -60,7 +64,7 @@ The practical changes are: | ||
| - the `0.9.0` monorepo and project-aware state layout remains part of the release surface, including `defaultProject`, `projects.<projectId>`, project-scoped state roots, and project-aware CLI routing | ||
| - the current release surface and tracked install-state fixtures now all move together on `0.9.2` | ||
| - the current release surface and tracked install-state fixtures now move together on the active package version | ||
| If your repo copied starter docs, shell automation, runbooks, or `wave.config.json` defaults, these are the areas most likely to need a sync before the `0.9.2` package cut. | ||
| If your repo copied starter docs, shell automation, runbooks, or `wave.config.json` defaults, these are the areas most likely to need a sync before the current package cut. | ||
| For a practical `0.9.2` operating stance after the upgrade, read [../guides/recommendations-0.9.2.md](../guides/recommendations-0.9.2.md). | ||
| For a practical `0.9.12` operating stance after the upgrade, read [../guides/recommendations-0.9.12.md](../guides/recommendations-0.9.12.md). | ||
| For the concrete operator setup in Nemoshell, Docker, and other sandboxed shells, also read [../guides/sandboxed-environments.md](../guides/sandboxed-environments.md). | ||
@@ -133,3 +137,3 @@ | ||
| The most common sync set for `0.9.2` is: | ||
| The most common sync set for the current release line is: | ||
@@ -187,5 +191,5 @@ - `docs/agents/wave-launcher-role.md` | ||
| ## `0.9.4` Release Model | ||
| ## `0.9.12` Release Model | ||
| The current `0.9.10` surface combines these strands: | ||
| The current `0.9.12` surface combines these strands: | ||
@@ -204,3 +208,3 @@ - the gap-value wave-gate fix and first-time setup UX improvements released in `0.9.4` | ||
| This is the main new behavior in `0.9.2`. | ||
| This remains the main execution-model shift introduced in `0.9.2`. | ||
@@ -214,3 +218,3 @@ The runtime now: | ||
| If your repo copied sandbox, CI, or container runbooks, this is the main sync set to apply from `0.9.2`: | ||
| If your repo copied sandbox, CI, or container runbooks, this is the main sync set to apply from that `0.9.2` execution-model cut: | ||
@@ -226,3 +230,3 @@ - `README.md` | ||
| The same `0.9.2` doc surface also now describes the current control-plane and security model as shipped: | ||
| That same `0.9.2` doc surface also describes the current control-plane and security model as shipped: | ||
@@ -234,3 +238,3 @@ - owned Wave Control deployments use Stack for browser sign-in, then apply Wave-managed approval states and provider grants on top of that identity | ||
| If your repo copied release docs, security runbooks, or Wave Control setup docs, this is the main sync set to apply from `0.9.2`: | ||
| If your repo copied release docs, security runbooks, or Wave Control setup docs, this is the main sync set to apply from that `0.9.2` security-surface cut: | ||
@@ -304,3 +308,3 @@ - `README.md` | ||
| ## Upgrading From `0.8.5` To `0.9.4` | ||
| ## Upgrading From `0.8.5` To `0.9.12` | ||
@@ -342,3 +346,3 @@ This is the smallest upgrade, but it changes the live wait-loop contract for external automation and intentionally long-running agents. | ||
| ## Upgrading From `0.8.4` To `0.9.4` | ||
| ## Upgrading From `0.8.4` To `0.9.12` | ||
@@ -381,3 +385,3 @@ ### What changed | ||
| ## Upgrading From `0.9.9` To `0.9.10` | ||
| ## Upgrading From `0.9.9` To `0.9.12` | ||
@@ -390,5 +394,5 @@ Run-state history is now capped at 200 entries (20 per wave). Existing bloated run-state files will be automatically pruned on the next write. No config changes needed. | ||
| ## Upgrading From `0.8.3` To `0.9.10` | ||
| ## Upgrading From `0.8.3` To `0.9.12` | ||
| Treat this as one move to the current `0.9.2` surface. | ||
| Treat this as one move to the current `0.9.12` surface. | ||
@@ -426,3 +430,3 @@ ### What changed across that range | ||
| ## Upgrading From `0.6.x` Or `0.7.x` To `0.9.10` | ||
| ## Upgrading From `0.6.x` Or `0.7.x` To `0.9.12` | ||
@@ -468,3 +472,3 @@ This is the main migration path for older adopted repos. | ||
| ## Upgrading From `0.5.x` Or Earlier To `0.9.4` | ||
| ## Upgrading From `0.5.x` Or Earlier To `0.9.12` | ||
@@ -579,2 +583,2 @@ Do not treat this as a tiny patch bump. | ||
| The current `0.9.10` surface keeps the same authority-set and phase-engine architecture, ships both the design-role starter surface and the signal-driven long-running-agent starter surface, keeps the `0.8.7` policy and routing hardening, and now also packages the practical operator recommendations guide inside the release line. For most repos already on `0.8.x`, the upgrade is package bump plus validation. For older adopted repos, the real work is syncing repo-owned prompts, skills, planner corpus, wrapper scripts, and runbooks so they describe the runtime the package now ships. | ||
| The current `0.9.12` surface keeps the same authority-set and phase-engine architecture, ships both the design-role starter surface and the signal-driven long-running-agent starter surface, keeps the `0.8.7` policy and routing hardening, adds the hybrid closure fast-path fixes, and now packages the practical operator recommendations guide inside the release line. For most repos already on `0.8.x`, the upgrade is package bump plus validation. For older adopted repos, the real work is syncing repo-owned prompts, skills, planner corpus, wrapper scripts, and runbooks so they describe the runtime the package now ships. |
@@ -129,3 +129,3 @@ # Wave Orchestrator | ||
| 1. Install the package with `pnpm add -D @chllming/wave-orchestration`. | ||
| 2. Confirm `tmux` and at least one real executor (`codex`, `claude`, or `opencode`) are available if you want real wave execution. | ||
| 2. Confirm at least one real executor (`codex`, `claude`, or `opencode`) is available if you want live wave execution. Install `tmux` only if you want terminal-native dashboard or projection attach. | ||
| 3. Run `pnpm exec wave init` for a fresh repo, or `pnpm exec wave init --adopt-existing` for a repo with existing Wave files you want preserved. | ||
@@ -132,0 +132,0 @@ 4. Review [wave.config.json](../../wave.config.json). |
+4
-10
@@ -20,3 +20,3 @@ # Wave Documentation | ||
| - `docs/guides/` | ||
| Task-oriented workflows. Use these when you need to set up the planner, choose an operating mode, or decide how to run tmux and terminal surfaces. | ||
| Task-oriented workflows. Use these when you need to set up the planner, choose an operating mode, or pick an operator terminal surface such as optional tmux-backed dashboards. | ||
| - `docs/reference/` | ||
@@ -42,3 +42,3 @@ Exact command, config, and file-format details. Use this when you need precise key names, runtime options, or bundle structure. | ||
| - Adding an optional pre-implementation design steward: | ||
| Read [guides/author-and-run-waves.md](./guides/author-and-run-waves.md), then the standing prompt in [agents/wave-design-role.md](./agents/wave-design-role.md). The shipped `0.9.3` surface includes `role-design` plus `tui-design`, with docs-first design stewards by default and explicit hybrid design stewards when a wave also gives that same agent code ownership. | ||
| Read [guides/author-and-run-waves.md](./guides/author-and-run-waves.md), then the standing prompt in [agents/wave-design-role.md](./agents/wave-design-role.md). The shipped `0.9.12` surface includes `role-design` plus `tui-design`, with docs-first design stewards by default and explicit hybrid design stewards when a wave also gives that same agent code ownership. | ||
| - Running in LEAPclaw, OpenClaw, Nemoshell, Docker, or another short-lived sandbox: | ||
@@ -58,10 +58,4 @@ Read [guides/sandboxed-environments.md](./guides/sandboxed-environments.md) first for the submit or supervise pattern, persistent-state expectations, and dashboard guidance, then use [plans/sandbox-end-state-architecture.md](./plans/sandbox-end-state-architecture.md) for the deeper runtime design. | ||
| Read [reference/package-publishing-flow.md](./reference/package-publishing-flow.md) for the end-to-end release path, the GitHub publish workflows, the lifecycle scripts, and the verification or repair flow. | ||
| - Want the practical `0.9.3` operating stance: | ||
| Read [guides/recommendations-0.9.7 | ||
| - [0.9.8 Operating Recommendations](guides/recommendations-0.9.8.md | ||
| - [0.9.9 Recommendations](guides/recommendations-0.9.9.md | ||
| - [0.9.10 Recommendations](guides/recommendations-0.9.10.md))).md](./guides/recommendations-0.9.7 | ||
| - [0.9.8 Operating Recommendations](guides/recommendations-0.9.8.md | ||
| - [0.9.9 Recommendations](guides/recommendations-0.9.9.md | ||
| - [0.9.10 Recommendations](guides/recommendations-0.9.10.md))).md) for the recommended default around relaxed blocker states, advisory turn budgets, and targeted recovery. | ||
| - Want the practical `0.9.12` operating stance: | ||
| Read [guides/recommendations-0.9.12.md](./guides/recommendations-0.9.12.md) for the recommended default around advisory turn budgets, targeted recovery, low-entropy closure, and optional TMUX operator surfaces. | ||
| - Want the concrete runtime module map: | ||
@@ -68,0 +62,0 @@ Read [plans/end-state-architecture.md](./plans/end-state-architecture.md) for the engine-by-engine architecture and artifact ownership model. |
@@ -57,3 +57,3 @@ --- | ||
| | `--no-dashboard` | off | Disable the per-wave dashboard projection session | | ||
| | `--cleanup-sessions` | on | Kill lane tmux dashboard and projection sessions after each wave | | ||
| | `--cleanup-sessions` | on | Clean up lane tmux dashboard and projection sessions after each wave | | ||
| | `--keep-sessions` | off | Keep lane tmux dashboard and projection sessions | | ||
@@ -633,3 +633,3 @@ | `--keep-terminals` | off | Keep temporary terminal entries | | ||
| Agentic planner payloads also accept `workerAgents[].roleKind = "design"`. The shipped `0.9.2` surface uses `design-pass` as the default executor profile for that role and typically assigns a packet path like `docs/plans/waves/design/wave-<n>-<agentId>.md`. Interactive draft scaffolds the docs-first default; hybrid design stewards are authored by explicitly adding implementation-owned paths and the normal implementation contract sections. | ||
| Agentic planner payloads also accept `workerAgents[].roleKind = "design"`. The shipped `0.9.12` surface uses `design-pass` as the default executor profile for that role and typically assigns a packet path like `docs/plans/waves/design/wave-<n>-<agentId>.md`. Interactive draft scaffolds the docs-first default; hybrid design stewards are authored by explicitly adding implementation-owned paths and the normal implementation contract sections. | ||
@@ -636,0 +636,0 @@ ## Ad-Hoc Task Commands |
@@ -145,3 +145,3 @@ --- | ||
| For the practical `0.9.2` recommendation on when to keep records blocking versus when to downgrade them to `soft`, `stale`, or `advisory`, see [../guides/recommendations-0.9.2.md](../guides/recommendations-0.9.2.md). | ||
| For the practical `0.9.12` recommendation on when to keep records blocking versus when to downgrade them to `soft`, `stale`, or `advisory`, see [../guides/recommendations-0.9.12.md](../guides/recommendations-0.9.12.md). | ||
@@ -148,0 +148,0 @@ This page is documenting runtime semantics first. The important contract is that closure follows the durable coordination state, not that a particular human or agent used one exact command path to mutate it. |
@@ -5,3 +5,3 @@ # npmjs Token Publishing | ||
| The current `0.9.2` release procedure publishes through a repository Actions secret named `NPM_TOKEN`. | ||
| The current `0.9.12` release procedure publishes through a repository Actions secret named `NPM_TOKEN`. | ||
@@ -52,4 +52,4 @@ ## What This Repo Already Does | ||
| 4. Confirm `README.md`, `CHANGELOG.md`, `releases/manifest.json`, and `docs/plans/migration.md` all describe the same release surface. | ||
| 5. Push the release commit and release tag, for example `v0.9.2`. | ||
| 5. Push the release commit and release tag, for example `v0.9.12`. | ||
| 6. Verify both `publish-npm.yml` and `publish-package.yml` start from the tag push. | ||
| 7. Verify the npmjs publish completes successfully for the tagged source. |
@@ -18,3 +18,3 @@ # Package Publishing Flow | ||
| - merge the release changes to `main` | ||
| - push a version tag such as `v0.9.2` | ||
| - push a version tag such as `v0.9.12` | ||
@@ -126,3 +126,3 @@ Registry publishing happens in GitHub Actions after the tag push: | ||
| This repository protects `main`, so release changes must land through a pull request rather than a direct push. | ||
| This repository normally protects `main`, so release changes should land through a pull request unless the repo policy has been intentionally relaxed for a one-off release cut. | ||
@@ -132,5 +132,5 @@ Typical git flow: | ||
| ```bash | ||
| git checkout -b release/0.9.2 | ||
| git push -u origin release/0.9.2 | ||
| gh pr create --base main --head release/0.9.2 | ||
| git checkout -b release/0.9.12 | ||
| git push -u origin release/0.9.12 | ||
| gh pr create --base main --head release/0.9.12 | ||
| gh pr merge <pr-number> --merge --delete-branch | ||
@@ -144,4 +144,4 @@ ``` | ||
| ```bash | ||
| git tag v0.9.2 | ||
| git push origin v0.9.2 | ||
| git tag v0.9.12 | ||
| git push origin v0.9.12 | ||
| ``` | ||
@@ -151,3 +151,3 @@ | ||
| The tag must match the checked-in package version exactly. Example: if `package.json.version` is `0.9.2`, the pushed tag must be `v0.9.2`. | ||
| The tag must match the checked-in package version exactly. Example: if `package.json.version` is `0.9.12`, the pushed tag must be `v0.9.12`. | ||
@@ -220,5 +220,5 @@ ## GitHub Actions Workflows | ||
| { | ||
| "version": "0.9.2", | ||
| "version": "0.9.12", | ||
| "dist-tags": { | ||
| "latest": "0.9.2" | ||
| "latest": "0.9.12" | ||
| } | ||
@@ -240,4 +240,4 @@ } | ||
| ```bash | ||
| git tag -f v0.9.2 <fixed-commit> | ||
| git push origin refs/tags/v0.9.2 --force | ||
| git tag -f v0.9.12 <fixed-commit> | ||
| git push origin refs/tags/v0.9.12 --force | ||
| ``` | ||
@@ -244,0 +244,0 @@ |
@@ -194,3 +194,3 @@ # Runtime Configuration Reference | ||
| - only set `claude.maxTurns` or `opencode.steps` when you deliberately want a hard ceiling for that runtime | ||
| - see [../../guides/recommendations-0.9.3.md](../../guides/recommendations-0.9.3.md) for the recommended `0.9.3` operating stance that combines advisory turn budgets with softer non-proof coordination states | ||
| - see [../../guides/recommendations-0.9.12.md](../../guides/recommendations-0.9.12.md) for the recommended `0.9.12` operating stance that combines advisory turn budgets with softer non-proof coordination states, targeted recovery, and optional TMUX operator surfaces | ||
@@ -207,3 +207,3 @@ ## Runtime Pages | ||
| Packaged defaults in `@chllming/wave-orchestration@0.9.3`: | ||
| Packaged defaults in `@chllming/wave-orchestration@0.9.12`: | ||
@@ -210,0 +210,0 @@ - `endpoint`: `https://wave-control.up.railway.app/api/v1` |
| --- | ||
| title: "Sample Waves" | ||
| summary: "Showcase-first sample waves that demonstrate the shipped 0.9.2 authored surface, including the optional design-role path." | ||
| summary: "Showcase-first sample waves that demonstrate the shipped 0.9.12 authored surface, including the optional design-role path." | ||
| --- | ||
@@ -8,3 +8,3 @@ | ||
| This guide points to showcase-first sample waves that demonstrate the shipped `0.9.2` authored Wave surface. | ||
| This guide points to showcase-first sample waves that demonstrate the shipped `0.9.12` authored Wave surface. | ||
@@ -21,3 +21,3 @@ The examples are intentionally denser than typical production waves. Their job is to teach the current authoring and runtime surface quickly, not to be the smallest possible launch-ready files. | ||
| - [Full modern sample wave](../plans/examples/wave-example-live-proof.md) | ||
| Shows the combined `0.9.2` authored surface in one file: closure roles, `E0`, optional security review, delegated and pinned benchmark targets, richer executor config, `### Skills`, `### Capabilities`, `### Deliverables`, `### Exit contract`, `### Proof artifacts`, sticky retry, deploy environments, and proof-first live-wave structure. | ||
| Shows the combined `0.9.12` authored surface in one file: closure roles, `E0`, optional security review, delegated and pinned benchmark targets, richer executor config, `### Skills`, `### Capabilities`, `### Deliverables`, `### Exit contract`, `### Proof artifacts`, sticky retry, deploy environments, and proof-first live-wave structure. | ||
@@ -51,3 +51,3 @@ - [Optional design-steward handoff wave](../plans/examples/wave-example-design-handoff.md) | ||
| Together these samples cover the main surfaces added or hardened through `0.9.2`: | ||
| Together these samples cover the main surfaces added or hardened through `0.9.12`: | ||
@@ -190,3 +190,3 @@ - repo-landed maturity discipline and anti-overclaim framing | ||
| 1. Start with [High-fidelity repo-landed rollout wave](../plans/examples/wave-example-rollout-fidelity.md) if you want the clearest example of good closure-ready wave fidelity for a repo-only outcome. | ||
| 2. Read [Full modern sample wave](../plans/examples/wave-example-live-proof.md) if you want the denser proof-first and eval-heavy `0.9.2` surface. | ||
| 2. Read [Full modern sample wave](../plans/examples/wave-example-live-proof.md) if you want the denser proof-first and eval-heavy `0.9.12` surface. | ||
| 3. Read [Optional design-steward handoff wave](../plans/examples/wave-example-design-handoff.md) if the task needs a design packet before implementation fan-out. | ||
@@ -193,0 +193,0 @@ 4. Read [docs/evals/README.md](../evals/README.md) if you want more background on benchmark target selection. |
@@ -127,3 +127,3 @@ # Skills Reference | ||
| Optional design workers in the shipped `0.9.2` surface normally attach `role-design`. That bundle is intended for docs/spec-first design packets and explicit implementation handoff work before implementation starts. When the design packet covers terminal UX, dashboards, or other operator surfaces, add `tui-design` explicitly in the wave's `### Skills`. | ||
| Optional design workers in the shipped `0.9.12` surface normally attach `role-design`. That bundle is intended for docs/spec-first design packets and explicit implementation handoff work before implementation starts. When the design packet covers terminal UX, dashboards, or other operator surfaces, add `tui-design` explicitly in the wave's `### Skills`. | ||
@@ -130,0 +130,0 @@ Long-running agents that should stay resident and react only to orchestrator signal changes can add `signal-hygiene` explicitly in `### Skills`. That bundle is not auto-attached and is not meant for normal one-shot implementation agents. |
@@ -26,3 +26,3 @@ --- | ||
| This is the release default in `@chllming/wave-orchestration@0.9.2`. | ||
| This is the release default in `@chllming/wave-orchestration@0.9.12`. | ||
@@ -48,2 +48,4 @@ - receives local-first telemetry uploads | ||
| The packaged browser UI now defaults to a dashboard-first information architecture with `Dashboard`, `Operations`, `Access`, and `Account` views. The goal is to put operator triage first, then let deeper run, benchmark, token, and access-management screens hang off that navigation instead of treating every surface as a flat peer tab. | ||
| ## What Gets Reported | ||
@@ -50,0 +52,0 @@ |
+3
-3
@@ -5,5 +5,5 @@ # Wave Orchestrator Roadmap | ||
| ## Current Release: 0.9.2 | ||
| ## Current Release: 0.9.12 | ||
| `0.9.2` is the current packaged surface. | ||
| `0.9.12` is the current packaged surface. | ||
@@ -60,4 +60,4 @@ It includes: | ||
| 1. Ship `0.9.2` with the sandbox/runtime hardening and aligned docs. | ||
| 1. Ship `0.9.12` with the closure, operator-surface, and release-doc alignment fixes. | ||
| 2. Maintain this Node package for bug fixes, compatibility, operational hardening, and release-surface sync rather than a broad new feature wave. | ||
| 3. Move long-term execution investment to the LEAPclaw + Go + Temporal architecture and the Rust standalone runtime. |
+8
-9
| { | ||
| "name": "@chllming/wave-orchestration", | ||
| "version": "0.9.11", | ||
| "version": "0.9.12", | ||
| "license": "MIT", | ||
| "description": "Generic wave-based multi-agent orchestration for repository work.", | ||
| "packageManager": "pnpm@10.23.0", | ||
| "repository": { | ||
@@ -35,2 +34,8 @@ "type": "git", | ||
| }, | ||
| "devDependencies": { | ||
| "@mozilla/readability": "^0.6.0", | ||
| "jsdom": "^29.0.1", | ||
| "pdfjs-dist": "^5.5.207", | ||
| "vitest": "3.2.4" | ||
| }, | ||
| "scripts": { | ||
@@ -49,9 +54,3 @@ "context7:api-check": "bash scripts/context7-export-env.sh run bash scripts/context7-api-check.sh", | ||
| "wave:local": "node scripts/wave-local-executor.mjs" | ||
| }, | ||
| "devDependencies": { | ||
| "@mozilla/readability": "^0.6.0", | ||
| "jsdom": "^29.0.1", | ||
| "pdfjs-dist": "^5.5.207", | ||
| "vitest": "3.2.4" | ||
| } | ||
| } | ||
| } |
+7
-8
@@ -110,14 +110,13 @@ # Wave Orchestration | ||
| - `@chllming/wave-orchestration@0.9.7` | ||
| - Release tag: [`v0.9.5`](https://github.com/chllming/agent-wave-orchestrator/releases/tag/v0.9.7) | ||
| - `@chllming/wave-orchestration@0.9.12` | ||
| - Release tag: [`v0.9.12`](https://github.com/chllming/agent-wave-orchestrator/releases/tag/v0.9.12) | ||
| - Public install path: npmjs | ||
| - Authenticated fallback: GitHub Packages | ||
| Highlights in `0.9.4`: | ||
| Highlights in `0.9.12`: | ||
| - Wave-gate markers now accept `gap` alongside `pass`, `concerns`, and `blocked` for all five gate dimensions. Agents that report a documented gap (e.g. `live=gap` for an infrastructure topology constraint) no longer have their marker rejected entirely, and `cont-QA` treats gap values as a conditional pass instead of a hard blocker. | ||
| - First-time `wave launch` now auto-triggers `wave project setup` when no project profile exists, matching existing `wave draft` behavior. The interactive setup flow now shows descriptive help text, explains all template and posture options inline, and adds whitespace between question groups for readability. | ||
| - `PromptSession` gains a `describe(text)` method for writing contextual help to stderr during interactive setup flows. | ||
| - `parseArgs` now passes the loaded config object through to `runLauncherCli`, avoiding a redundant `loadWaveConfig()` call. | ||
| - Release docs, migration guidance, runtime-config and closure references, the manifest, and the tracked install-state fixtures now all point at the `0.9.4` surface. | ||
| - Closure bootstrap mode now has a real low-entropy fast path: missing `cont-QA` runs are skipped only when semantic closure did not already escalate into the deeper steward path, and the closure-mode thresholds now apply consistently across launcher, closure, and derived-state logic. | ||
| - TMUX is now documented and surfaced consistently as an optional dashboard/projection layer. Live agents remain process-backed, and `tmux + --no-dashboard` now prints an explicit note instead of implying a mandatory tmux runtime. | ||
| - Wave Control's browser surface now defaults to a dashboard-first information architecture with clearer `Dashboard`, `Operations`, `Access`, and `Account` navigation, plus richer run and benchmark analytics summaries for operators. | ||
| - Release docs, migration guidance, runtime-config and closure references, the manifest, and the tracked install-state fixtures now all point at the `0.9.12` surface. | ||
@@ -124,0 +123,0 @@ Requirements: |
@@ -65,4 +65,4 @@ import { spawnSync } from "node:child_process"; | ||
| --codex-sandbox <mode> Codex sandbox mode override passed to launcher (default: lane config) | ||
| --dashboard Enable dashboards (default: disabled) | ||
| --keep-sessions Keep tmux sessions between waves | ||
| --dashboard Enable dashboard projection sessions (default: disabled) | ||
| --keep-sessions Keep tmux dashboard/projection sessions between waves | ||
| --keep-terminals Keep temporary terminal entries between waves | ||
@@ -69,0 +69,0 @@ `); |
@@ -27,2 +27,6 @@ import path from "node:path"; | ||
| import { summarizeResolvedSkills } from "./skills.mjs"; | ||
| import { | ||
| resolveClosureMode as resolveClosurePolicyMode, | ||
| resolveClosurePolicyConfig, | ||
| } from "./closure-policy.mjs"; | ||
@@ -138,2 +142,26 @@ function failureResultFromGate(gate, fallbackLogPath) { | ||
| function shouldEvaluateStageBeforeLaunch(stage) { | ||
| return stage.key === "integration" || stage.key === "documentation"; | ||
| } | ||
| function shouldSkipContQaStage({ | ||
| stage, | ||
| wave, | ||
| lanePaths, | ||
| semanticClosureStagesRan, | ||
| }) { | ||
| if (stage.key !== "cont-qa" || semanticClosureStagesRan) { | ||
| return false; | ||
| } | ||
| const closurePolicy = resolveClosurePolicyConfig(lanePaths); | ||
| if (!closurePolicy.autoClosure.allowSkipContQaInBootstrap) { | ||
| return false; | ||
| } | ||
| const closureMode = resolveClosurePolicyMode( | ||
| wave.wave, | ||
| closurePolicy.closureModeThresholds, | ||
| ); | ||
| return closureMode === "bootstrap"; | ||
| } | ||
| export async function runClosureSweepPhase({ | ||
@@ -200,5 +228,54 @@ lanePaths, | ||
| const _resolvedGateMode = resolveGateMode(wave.wave, _gateThresholds); | ||
| let semanticClosureStagesRan = false; | ||
| for (const [stageIndex, stage] of stagedRuns.entries()) { | ||
| const currentDerivedState = refreshDerivedState?.(dashboardState?.attempt || 0) || null; | ||
| if (shouldEvaluateStageBeforeLaunch(stage)) { | ||
| const preLaunchGate = evaluateClosureStage({ | ||
| stage, | ||
| wave, | ||
| closureRuns, | ||
| lanePaths, | ||
| dashboardState, | ||
| derivedState: currentDerivedState, | ||
| refreshDerivedState, | ||
| readWaveContEvalGateFn: readContEvalGate, | ||
| readWaveSecurityGateFn: readSecurityGate, | ||
| readWaveIntegrationBarrierFn: readIntegrationBarrier, | ||
| readWaveDocumentationGateFn: readDocumentationGate, | ||
| readWaveComponentMatrixGateFn: readComponentMatrixGate, | ||
| readWaveContQaGateFn: readContQaGate, | ||
| contEvalAgentId, | ||
| integrationAgentId, | ||
| documentationAgentId, | ||
| contQaAgentId, | ||
| }); | ||
| const autoSatisfiedStage = | ||
| preLaunchGate.ok && | ||
| !preLaunchGate.agentId && | ||
| (preLaunchGate.integrationState || preLaunchGate.docClosureState); | ||
| if (autoSatisfiedStage) { | ||
| recordCombinedEvent({ | ||
| agentId: stage.agentId || null, | ||
| message: `${stage.label} already satisfied before launch: ${preLaunchGate.detail}`, | ||
| }); | ||
| continue; | ||
| } | ||
| } | ||
| if ( | ||
| shouldSkipContQaStage({ | ||
| stage, | ||
| wave, | ||
| lanePaths, | ||
| semanticClosureStagesRan, | ||
| }) | ||
| ) { | ||
| recordCombinedEvent({ | ||
| agentId: stage.agentId || null, | ||
| message: | ||
| "cont-QA gate skipped in bootstrap because closure remained on the low-entropy fast path.", | ||
| }); | ||
| continue; | ||
| } | ||
| if (stage.runs.length === 0) { | ||
| if (_resolvedGateMode === "bootstrap") { | ||
| if (_resolvedGateMode === "bootstrap" && stage.key !== "cont-qa") { | ||
| continue; | ||
@@ -221,2 +298,5 @@ } | ||
| } | ||
| if (stage.key !== "cont-qa") { | ||
| semanticClosureStagesRan = true; | ||
| } | ||
| for (const runInfo of stage.runs) { | ||
@@ -318,2 +398,3 @@ const existing = dashboardState.agents.find((entry) => entry.agentId === runInfo.agent.agentId); | ||
| dashboardState, | ||
| derivedState: refreshDerivedState?.(dashboardState?.attempt || 0) || currentDerivedState, | ||
| refreshDerivedState, | ||
@@ -443,2 +524,3 @@ readWaveContEvalGateFn: readContEvalGate, | ||
| dashboardState, | ||
| derivedState, | ||
| refreshDerivedState, | ||
@@ -473,3 +555,3 @@ readWaveContEvalGateFn, | ||
| closureRuns, | ||
| refreshDerivedState?.(dashboardState?.attempt || 0), | ||
| derivedState || refreshDerivedState?.(dashboardState?.attempt || 0), | ||
| { | ||
@@ -479,7 +561,18 @@ integrationAgentId, | ||
| requireIntegrationStewardFromWave: lanePaths.requireIntegrationStewardFromWave, | ||
| laneProfile: lanePaths.laneProfile, | ||
| autoClosure: lanePaths.autoClosure, | ||
| }, | ||
| ); | ||
| case "documentation": { | ||
| const componentMatrixGate = readWaveComponentMatrixGateFn(wave, closureRuns, { | ||
| laneProfile: lanePaths.laneProfile, | ||
| documentationAgentId, | ||
| }); | ||
| const documentationGate = readWaveDocumentationGateFn(wave, closureRuns, { | ||
| mode: "live", | ||
| derivedState: derivedState || refreshDerivedState?.(dashboardState?.attempt || 0), | ||
| documentationAgentId, | ||
| laneProfile: lanePaths.laneProfile, | ||
| autoClosure: lanePaths.autoClosure, | ||
| componentMatrixGate, | ||
| }); | ||
@@ -489,6 +582,10 @@ if (!documentationGate.ok) { | ||
| } | ||
| return readWaveComponentMatrixGateFn(wave, closureRuns, { | ||
| laneProfile: lanePaths.laneProfile, | ||
| documentationAgentId, | ||
| }); | ||
| return { | ||
| ...componentMatrixGate, | ||
| docClosureState: documentationGate.docClosureState || null, | ||
| detail: | ||
| documentationGate.docClosureState && componentMatrixGate.ok | ||
| ? documentationGate.detail | ||
| : componentMatrixGate.detail, | ||
| }; | ||
| } | ||
@@ -495,0 +592,0 @@ case "cont-qa": |
@@ -539,2 +539,17 @@ import fs from "node:fs"; | ||
| }, | ||
| closureModeThresholds: { | ||
| bootstrap: rawValidation.closureModeThresholds?.bootstrap ?? 0, | ||
| standard: rawValidation.closureModeThresholds?.standard ?? 4, | ||
| strict: rawValidation.closureModeThresholds?.strict ?? 10, | ||
| }, | ||
| autoClosure: { | ||
| allowInferredIntegration: | ||
| normalizeOptionalBoolean(rawValidation.autoClosure?.allowInferredIntegration, false), | ||
| allowAutoDocNoChange: | ||
| normalizeOptionalBoolean(rawValidation.autoClosure?.allowAutoDocNoChange, false), | ||
| allowAutoDocProjection: | ||
| normalizeOptionalBoolean(rawValidation.autoClosure?.allowAutoDocProjection, false), | ||
| allowSkipContQaInBootstrap: | ||
| normalizeOptionalBoolean(rawValidation.autoClosure?.allowSkipContQaInBootstrap, false), | ||
| }, | ||
| bootstrapPassConditions: { | ||
@@ -541,0 +556,0 @@ requireA0Verdict: rawValidation.bootstrapPassConditions?.requireA0Verdict ?? false, |
@@ -6,3 +6,6 @@ import fs from "node:fs"; | ||
| materializeAgentExecutionSummaries, | ||
| readClarificationBarrier, | ||
| readRunExecutionSummary, | ||
| readWaveAssignmentBarrier, | ||
| readWaveDependencyBarrier, | ||
| } from "./gate-engine.mjs"; | ||
@@ -55,2 +58,7 @@ import { | ||
| } from "./corridor.mjs"; | ||
| import { | ||
| classifyClosureComplexity, | ||
| resolveClosureMode, | ||
| resolveClosurePolicyConfig, | ||
| } from "./closure-policy.mjs"; | ||
@@ -722,2 +730,3 @@ export function waveCoordinationLogPath(lanePaths, waveNumber) { | ||
| }); | ||
| const corridorSummary = readWaveCorridorContext(lanePaths, wave.wave); | ||
| const securitySummary = buildWaveSecuritySummary({ | ||
@@ -728,3 +737,3 @@ lanePaths, | ||
| summariesByAgentId, | ||
| corridorSummary: readWaveCorridorContext(lanePaths, wave.wave), | ||
| corridorSummary, | ||
| }); | ||
@@ -744,2 +753,31 @@ const integrationSummary = buildWaveIntegrationSummary({ | ||
| }); | ||
| const closurePolicy = resolveClosurePolicyConfig(lanePaths); | ||
| const closureMode = resolveClosureMode(wave.wave, closurePolicy.closureModeThresholds); | ||
| const clarificationBarrier = readClarificationBarrier({ | ||
| coordinationState, | ||
| }); | ||
| const helperAssignmentBarrier = readWaveAssignmentBarrier( | ||
| { | ||
| capabilityAssignments, | ||
| }, | ||
| { | ||
| gateMode: closureMode, | ||
| }, | ||
| ); | ||
| const dependencyBarrier = readWaveDependencyBarrier({ | ||
| dependencySnapshot, | ||
| }); | ||
| const closureComplexity = classifyClosureComplexity({ | ||
| contradictions: coordinationState?.contradictions || [], | ||
| coordinationState, | ||
| docsQueue, | ||
| capabilityAssignments, | ||
| dependencySnapshot, | ||
| securitySummary, | ||
| corridorSummary, | ||
| integrationSummary, | ||
| clarificationBarrier, | ||
| helperAssignmentBarrier, | ||
| dependencyBarrier, | ||
| }); | ||
| const ledger = deriveWaveLedger({ | ||
@@ -810,3 +848,3 @@ lane: lanePaths.lane, | ||
| securitySummaryPath: waveSecurityPath(lanePaths, wave.wave), | ||
| corridorSummary: readWaveCorridorContext(lanePaths, wave.wave), | ||
| corridorSummary, | ||
| corridorSummaryPath: waveCorridorContextPath(lanePaths, wave.wave), | ||
@@ -817,2 +855,7 @@ integrationSummary, | ||
| securityMarkdownPath: waveSecurityMarkdownPath(lanePaths, wave.wave), | ||
| clarificationBarrier, | ||
| helperAssignmentBarrier, | ||
| dependencyBarrier, | ||
| closureMode, | ||
| closureComplexity, | ||
| ledger, | ||
@@ -819,0 +862,0 @@ ledgerPath: waveLedgerPath(lanePaths, wave.wave), |
@@ -56,2 +56,6 @@ import fs from "node:fs"; | ||
| import { contradictionsBlockingGate } from "./contradiction-entity.mjs"; | ||
| import { | ||
| evaluateDocumentationAutoClosure, | ||
| evaluateInferredIntegrationClosure, | ||
| } from "./closure-policy.mjs"; | ||
@@ -864,3 +868,17 @@ function contradictionList(value) { | ||
| const mode = normalizeReadMode(options.mode || "live"); | ||
| const documentationAgentId = wave.documentationAgentId || "A9"; | ||
| const documentationAgentId = | ||
| options.documentationAgentId || wave.documentationAgentId || "A9"; | ||
| const autoClosure = evaluateDocumentationAutoClosure(options.derivedState, options, { | ||
| componentMatrixGate: options.componentMatrixGate, | ||
| }); | ||
| if (autoClosure?.ok) { | ||
| return { | ||
| ok: true, | ||
| agentId: null, | ||
| statusCode: autoClosure.statusCode, | ||
| detail: autoClosure.detail, | ||
| logPath: null, | ||
| docClosureState: autoClosure.state, | ||
| }; | ||
| } | ||
| const docRun = | ||
@@ -1008,2 +1026,13 @@ agentRuns.find((run) => run.agent.agentId === documentationAgentId) ?? null; | ||
| wave.wave >= options.requireIntegrationStewardFromWave); | ||
| const autoClosure = evaluateInferredIntegrationClosure(options.derivedState, options); | ||
| if (autoClosure?.ok) { | ||
| return { | ||
| ok: true, | ||
| agentId: null, | ||
| statusCode: autoClosure.statusCode, | ||
| detail: autoClosure.detail, | ||
| logPath: null, | ||
| integrationState: autoClosure.state, | ||
| }; | ||
| } | ||
| const integrationRun = | ||
@@ -1065,6 +1094,12 @@ agentRuns.find((run) => run.agent.agentId === integrationAgentId) ?? null; | ||
| export function readWaveIntegrationBarrier(wave, agentRuns, derivedState, options = {}) { | ||
| const markerGate = readWaveIntegrationGate(wave, agentRuns, options); | ||
| const markerGate = readWaveIntegrationGate(wave, agentRuns, { | ||
| ...options, | ||
| derivedState, | ||
| }); | ||
| if (!markerGate.ok) { | ||
| return markerGate; | ||
| } | ||
| if (!markerGate.agentId) { | ||
| return markerGate; | ||
| } | ||
| const integrationSummary = derivedState?.integrationSummary || null; | ||
@@ -1247,2 +1282,3 @@ if (!integrationSummary) { | ||
| laneProfile: lanePaths?.laneProfile, | ||
| autoClosure: lanePaths?.autoClosure, | ||
| benchmarkCatalogPath: lanePaths?.laneProfile?.paths?.benchmarkCatalogPath, | ||
@@ -1454,2 +1490,15 @@ componentMatrixPayload, | ||
| const documentationAgentId = options.documentationAgentId || wave.documentationAgentId || "A9"; | ||
| const autoClosure = evaluateDocumentationAutoClosure(options.derivedState, options, { | ||
| componentMatrixGate: options.componentMatrixGate, | ||
| }); | ||
| if (autoClosure?.ok) { | ||
| return { | ||
| ok: true, | ||
| agentId: null, | ||
| statusCode: autoClosure.statusCode, | ||
| detail: autoClosure.detail, | ||
| logPath: null, | ||
| docClosureState: autoClosure.state, | ||
| }; | ||
| } | ||
| if (!waveDeclaresAgent(wave, documentationAgentId)) { | ||
@@ -1516,2 +1565,13 @@ return { ok: true, agentId: null, statusCode: "pass", | ||
| (options.requireIntegrationStewardFromWave != null && wave.wave >= options.requireIntegrationStewardFromWave); | ||
| const autoClosure = evaluateInferredIntegrationClosure(options.derivedState, options); | ||
| if (autoClosure?.ok) { | ||
| return { | ||
| ok: true, | ||
| agentId: null, | ||
| statusCode: autoClosure.statusCode, | ||
| detail: autoClosure.detail, | ||
| logPath: null, | ||
| integrationState: autoClosure.state, | ||
| }; | ||
| } | ||
| if (!waveDeclaresAgent(wave, integrationAgentId)) { | ||
@@ -1567,2 +1627,5 @@ return { | ||
| requireIntegrationStewardFromWave: laneConfig.requireIntegrationStewardFromWave, | ||
| derivedState, | ||
| laneProfile: laneConfig.laneProfile, | ||
| autoClosure: laneConfig.autoClosure, | ||
| }); | ||
@@ -1596,4 +1659,2 @@ const integrationBarrier = (() => { | ||
| })(); | ||
| const documentationGate = readWaveDocumentationGatePure(wave, agentResults, { | ||
| documentationAgentId: laneConfig.documentationAgentId }); | ||
| const componentMatrixGate = readWaveComponentMatrixGatePure(wave, agentResults, { | ||
@@ -1603,2 +1664,9 @@ laneProfile: laneConfig.laneProfile, documentationAgentId: laneConfig.documentationAgentId, | ||
| componentMatrixJsonPath: laneConfig.componentMatrixJsonPath }); | ||
| const documentationGate = readWaveDocumentationGatePure(wave, agentResults, { | ||
| documentationAgentId: laneConfig.documentationAgentId, | ||
| derivedState, | ||
| laneProfile: laneConfig.laneProfile, | ||
| autoClosure: laneConfig.autoClosure, | ||
| componentMatrixGate, | ||
| }); | ||
| const contEvalGate = readWaveContEvalGatePure(wave, agentResults, { | ||
@@ -1605,0 +1673,0 @@ contEvalAgentId: laneConfig.contEvalAgentId, mode: validationMode, |
@@ -72,3 +72,3 @@ import fs from "node:fs"; | ||
| "docs/guides/planner.md", | ||
| "docs/guides/recommendations-0.9.7.md", | ||
| "docs/guides/recommendations-0.9.12.md", | ||
| "docs/guides/sandboxed-environments.md", | ||
@@ -75,0 +75,0 @@ "docs/guides/signal-wrappers.md", |
@@ -280,2 +280,4 @@ import crypto from "node:crypto"; | ||
| gateModeThresholds: laneProfile.validation.gateModeThresholds, | ||
| closureModeThresholds: laneProfile.validation.closureModeThresholds, | ||
| autoClosure: laneProfile.validation.autoClosure, | ||
| executors: laneProfile.executors, | ||
@@ -432,5 +434,2 @@ skills: laneProfile.skills, | ||
| .toLowerCase(); | ||
| if (normalized === "hold") { | ||
| return "concerns"; | ||
| } | ||
| if (normalized === "fail") { | ||
@@ -437,0 +436,0 @@ return "blocked"; |
@@ -799,3 +799,3 @@ import crypto from "node:crypto"; | ||
| const launch = runShellCommand( | ||
| `node ${shellQuote(WAVE_ENTRY)} launch --lane main --start-wave 1 --end-wave 1 --no-dashboard --terminal-surface tmux`, | ||
| `node ${shellQuote(WAVE_ENTRY)} launch --lane main --start-wave 1 --end-wave 1 --no-dashboard`, | ||
| { | ||
@@ -802,0 +802,0 @@ cwd: taskWorkspace.repoDir, |
@@ -626,2 +626,3 @@ import fs from "node:fs"; | ||
| const normalized = { ...gateSnapshot }; | ||
| const overallGate = String(gateSnapshot.overall?.gate || "").trim(); | ||
| for (const key of [ | ||
@@ -642,3 +643,23 @@ "implementationGate", | ||
| ]) { | ||
| normalized[key] = normalizeGateLogPath(gateSnapshot[key], agentArtifacts); | ||
| const nextValue = normalizeGateLogPath(gateSnapshot[key], agentArtifacts); | ||
| if (key === "documentationGate") { | ||
| normalized[key] = | ||
| overallGate === "documentationGate" && nextValue | ||
| ? { | ||
| ok: Boolean(nextValue.ok), | ||
| statusCode: nextValue.statusCode || null, | ||
| } | ||
| : null; | ||
| continue; | ||
| } | ||
| if (key === "integrationGate" || key === "integrationBarrier") { | ||
| normalized[key] = nextValue | ||
| ? { | ||
| ok: Boolean(nextValue.ok), | ||
| statusCode: nextValue.statusCode || null, | ||
| } | ||
| : null; | ||
| continue; | ||
| } | ||
| normalized[key] = nextValue; | ||
| } | ||
@@ -645,0 +666,0 @@ return normalized; |
+13
-2
@@ -279,3 +279,14 @@ { | ||
| "requireComponentPromotionsFromWave": 0, | ||
| "requireAgentComponentsFromWave": 0 | ||
| "requireAgentComponentsFromWave": 0, | ||
| "closureModeThresholds": { | ||
| "bootstrap": 0, | ||
| "standard": 4, | ||
| "strict": 10 | ||
| }, | ||
| "autoClosure": { | ||
| "allowInferredIntegration": true, | ||
| "allowAutoDocNoChange": true, | ||
| "allowAutoDocProjection": false, | ||
| "allowSkipContQaInBootstrap": true | ||
| } | ||
| }, | ||
@@ -313,2 +324,2 @@ "capabilityRouting": { | ||
| } | ||
| } | ||
| } |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
3998642
0.74%277
0.73%55101
1.11%407
-0.25%