codymaster 4.5.4 → 4.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -1
- package/README.md +86 -31
- package/dist/backends/viking-backend.js +235 -0
- package/dist/backends/viking-http-client.js +176 -0
- package/dist/browse-server.js +251 -0
- package/dist/cli/command-registry.js +26 -0
- package/dist/cli/commands/agent.js +120 -0
- package/dist/cli/commands/dashboard.js +93 -0
- package/dist/cli/commands/design-studio.js +111 -0
- package/dist/cli/commands/distro.js +25 -0
- package/dist/cli/commands/engineering.js +488 -0
- package/dist/cli/commands/project.js +324 -0
- package/dist/cli/commands/skill-chain.js +269 -0
- package/dist/cli/commands/system.js +89 -0
- package/dist/cli/commands/task.js +254 -0
- package/dist/cli/update-check.js +83 -0
- package/dist/cm-config.js +110 -0
- package/dist/cm-suggest.js +77 -0
- package/dist/continuity.js +8 -0
- package/dist/distro-validate.js +54 -0
- package/dist/guardian-core.js +74 -0
- package/dist/index.js +36 -2759
- package/dist/mcp-context-server.js +60 -1
- package/dist/mcp-skills-tools.js +81 -0
- package/dist/retro-summary.js +70 -0
- package/dist/second-opinion-providers.js +79 -0
- package/dist/sprint-pipeline.js +228 -0
- package/dist/storage-backend.js +63 -0
- package/dist/utils/cli-utils.js +76 -0
- package/dist/utils/skill-utils.js +32 -0
- package/install.sh +286 -58
- package/package.json +16 -5
- package/scripts/build-skills.mjs +51 -0
- package/scripts/gate-0-repo-hygiene.js +75 -0
- package/scripts/postinstall.js +56 -1
- package/scripts/security-scan.js +1 -1
- package/scripts/validate-skills.mjs +42 -0
- package/scripts/viking-demo.ts +105 -0
- package/skills/CLAUDE.md +2 -2
- package/skills/_shared/helpers.md +10 -0
- package/skills/cm-ads-tracker/SKILL.md +3 -6
- package/skills/cm-browse/SKILL.md +28 -0
- package/skills/cm-conductor-worktrees/SKILL.md +24 -0
- package/skills/cm-content-factory/SKILL.md +1 -1
- package/skills/cm-content-factory/landing/docs/content/changelog.md +36 -0
- package/skills/cm-content-factory/landing/docs/content/deployment.md +46 -0
- package/skills/cm-content-factory/landing/docs/content/execution-flow.md +67 -0
- package/skills/cm-content-factory/landing/docs/content/openspace.md +27 -0
- package/skills/cm-content-factory/landing/docs/content/openviking.md +33 -0
- package/skills/cm-content-factory/landing/docs/content/use-cases.md +26 -0
- package/skills/cm-content-factory/landing/docs/content/v5-intro.md +28 -0
- package/skills/cm-content-factory/landing/docs/index.html +240 -0
- package/skills/cm-content-factory/landing/index.html +99 -99
- package/skills/cm-content-factory/landing/script.js +42 -0
- package/skills/cm-content-factory/landing/translations.js +400 -400
- package/skills/cm-continuity/SKILL.md +33 -6
- package/skills/cm-design-studio/SKILL.md +30 -0
- package/skills/cm-ecosystem-roadmap/SKILL.md +11 -0
- package/skills/cm-engineering-meta/SKILL.md +69 -0
- package/skills/cm-growth-hacking/SKILL.md +1 -12
- package/skills/cm-guardian-runtime/SKILL.md +22 -0
- package/skills/cm-mcp-engineering/SKILL.md +18 -0
- package/skills/cm-notebooklm/SKILL.md +1 -17
- package/skills/cm-post-deploy-canary/SKILL.md +18 -0
- package/skills/cm-qa-visual-cli/SKILL.md +18 -0
- package/skills/cm-retro-cli/SKILL.md +19 -0
- package/skills/cm-second-opinion-cli/SKILL.md +19 -0
- package/skills/cm-secret-shield/SKILL.md +2 -2
- package/skills/cm-sprint-bus/SKILL.md +29 -0
- package/skills/cm-start/SKILL.md +11 -2
- package/skills/cm-tdd/SKILL.md +61 -74
- package/skills/profiles/README.md +21 -0
- package/skills/profiles/core.txt +23 -0
- package/skills/profiles/design.txt +6 -0
- package/skills/profiles/full.txt +58 -0
- package/skills/profiles/growth.txt +10 -0
- package/skills/profiles/knowledge.txt +7 -0
- package/scripts/test-gemini.js +0 -13
- package/skills/cm-frappe-agent/SKILL.md +0 -134
- package/skills/cm-frappe-agent/agents/doctype-architect.md +0 -596
- package/skills/cm-frappe-agent/agents/erpnext-customizer.md +0 -643
- package/skills/cm-frappe-agent/agents/frappe-backend.md +0 -814
- package/skills/cm-frappe-agent/agents/frappe-custom-frontend.md +0 -557
- package/skills/cm-frappe-agent/agents/frappe-debugger.md +0 -625
- package/skills/cm-frappe-agent/agents/frappe-fixer.md +0 -275
- package/skills/cm-frappe-agent/agents/frappe-frontend.md +0 -660
- package/skills/cm-frappe-agent/agents/frappe-installer.md +0 -158
- package/skills/cm-frappe-agent/agents/frappe-performance.md +0 -307
- package/skills/cm-frappe-agent/agents/frappe-planner.md +0 -419
- package/skills/cm-frappe-agent/agents/frappe-remote-ops.md +0 -153
- package/skills/cm-frappe-agent/agents/github-workflow.md +0 -286
- package/skills/cm-frappe-agent/commands/frappe-app.md +0 -351
- package/skills/cm-frappe-agent/commands/frappe-backend.md +0 -162
- package/skills/cm-frappe-agent/commands/frappe-bench.md +0 -254
- package/skills/cm-frappe-agent/commands/frappe-debug.md +0 -263
- package/skills/cm-frappe-agent/commands/frappe-doctype-create.md +0 -272
- package/skills/cm-frappe-agent/commands/frappe-doctype-field.md +0 -310
- package/skills/cm-frappe-agent/commands/frappe-erpnext.md +0 -210
- package/skills/cm-frappe-agent/commands/frappe-fix.md +0 -59
- package/skills/cm-frappe-agent/commands/frappe-frontend.md +0 -210
- package/skills/cm-frappe-agent/commands/frappe-fullstack.md +0 -243
- package/skills/cm-frappe-agent/commands/frappe-github.md +0 -57
- package/skills/cm-frappe-agent/commands/frappe-install.md +0 -52
- package/skills/cm-frappe-agent/commands/frappe-plan.md +0 -442
- package/skills/cm-frappe-agent/commands/frappe-remote.md +0 -58
- package/skills/cm-frappe-agent/commands/frappe-test.md +0 -356
- package/skills/cm-frappe-agent/docs/README.md +0 -51
- package/skills/cm-frappe-agent/docs/agents-catalog.md +0 -113
- package/skills/cm-frappe-agent/docs/architecture.md +0 -149
- package/skills/cm-frappe-agent/docs/commands-catalog.md +0 -82
- package/skills/cm-frappe-agent/docs/resources-catalog.md +0 -66
- package/skills/cm-frappe-agent/docs/sitemap-urls.txt +0 -52
- package/skills/cm-frappe-agent/docs/sitemap.md +0 -81
- package/skills/cm-frappe-agent/docs/sop/user-guide.md +0 -178
- package/skills/cm-frappe-agent/docs/sop/vibe-coding-guide.md +0 -122
- package/skills/cm-frappe-agent/resources/7-layer-architecture.md +0 -985
- package/skills/cm-frappe-agent/resources/bench_commands.md +0 -73
- package/skills/cm-frappe-agent/resources/code-patterns-guide.md +0 -948
- package/skills/cm-frappe-agent/resources/common_pitfalls.md +0 -266
- package/skills/cm-frappe-agent/resources/doctype-registry.md +0 -158
- package/skills/cm-frappe-agent/resources/installation-guide.md +0 -289
- package/skills/cm-frappe-agent/resources/rest-api-patterns.md +0 -182
- package/skills/cm-frappe-agent/resources/scaffold_checklist.md +0 -82
- package/skills/cm-frappe-agent/resources/upgrade_patterns.md +0 -113
- package/skills/cm-frappe-agent/resources/web-form-patterns.md +0 -252
- package/skills/cm-frappe-agent/skills/bench-commands/SKILL.md +0 -621
- package/skills/cm-frappe-agent/skills/client-scripts/SKILL.md +0 -642
- package/skills/cm-frappe-agent/skills/doctype-patterns/SKILL.md +0 -576
- package/skills/cm-frappe-agent/skills/frappe-api/SKILL.md +0 -740
- package/skills/cm-frappe-agent/skills/remote-operations/SKILL.md +0 -47
- package/skills/cm-frappe-agent/skills/server-scripts/SKILL.md +0 -608
- package/skills/cm-frappe-agent/skills/web-forms/SKILL.md +0 -46
- package/skills/frappe-app-builder.zip +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,52 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
Categories: 🚀 **Improvements** | 🐛 **Bug Fixes** | 🔒 **Security**
|
|
6
6
|
|
|
7
|
+
## [4.8.0] - 2026-04-10
|
|
8
|
+
|
|
9
|
+
### 🚀 Improvements — Documentation site & README accuracy
|
|
10
|
+
|
|
11
|
+
- **VitePress documentation** — Rebuilt `docs/` as a browsable site with sidebar IA (Getting Started, Architecture, Operations, Skills Library, API, Resources). Config: `docs/.vitepress/config.mts`. Local preview: `npm run docs:dev`; production build: `npm run docs:build`.
|
|
12
|
+
- **Skills index** — Documented all **56** bundled `skills/cm-*/SKILL.md` packs with category pages under `docs/skills/`.
|
|
13
|
+
- **API hub** — Added `docs/api/api-reference.md` (CLI + dashboard + browse daemon + MCP tools) aligned to `src/mcp-context-server.ts` (**13** MCP tools).
|
|
14
|
+
- **README refresh (all languages)** — Version badges bumped to **4.8.0**; broken `docs/` links replaced; CLI examples updated to match `src/cli/command-registry.ts` (no fictional `cm continuity` / `cm list` commands). License callouts aligned to **ISC** (`package.json`).
|
|
15
|
+
- **npm scripts** — `docs:dev`, `docs:build`, `docs:preview` for maintainers.
|
|
16
|
+
|
|
17
|
+
## [4.7.0] - 2026-04-02
|
|
18
|
+
|
|
19
|
+
### 🚀 Improvements — Zero-Touch Installation & Advanced Pipeline
|
|
20
|
+
|
|
21
|
+
- **Zero-Touch CLI Installation** — `install.sh` and `scripts/postinstall.js` overhauled to automatically activate the `cm` CLI. The script supports `--auto` for non-interactive `npm install -g codymaster`, while NPM seamlessly executes `npm link` or global install.
|
|
22
|
+
- **OpenViking Core Feature** — Integrated OpenViking installation via `pip/pip3` natively into the installation process. Both `bash install.sh --all` and `npm i codymaster` will now automatically set up the OpenViking daemon, unlocking true semantic vector graph memory out-of-the-box.
|
|
23
|
+
- **Skill Chain Auto-Dispatch** — Inspired by OpenSpace orchestrations, `cm-skill-chain` received a massive upgrade. Re-introduced the missing `auto` command enabling intelligent task detection, auto-selection of tools, and 100% automated handoffs between multi-agent sequences without human intervention.
|
|
24
|
+
- **Systematic Auto-healing** — Enhancements to `postinstall.js` for automatic fallbacks across different OS privileges and execution environments.
|
|
25
|
+
|
|
26
|
+
## [4.6.0] - 2026-04-02
|
|
27
|
+
|
|
28
|
+
### 🚀 Improvements — OpenViking Backend (Real Implementation)
|
|
29
|
+
|
|
30
|
+
- **`VikingBackend` — real implementation** — `src/backends/viking-backend.ts` implements all 11 `StorageBackend` methods by calling the [OpenViking REST API](https://github.com/volcengine/OpenViking) (default: `http://localhost:1933`). Replaces the placeholder stub from v4.5.5.
|
|
31
|
+
- **`VikingHttpClient`** — New `src/backends/viking-http-client.ts`: thin fetch-based HTTP client wrapping OpenViking's `/write`, `/read`, `/ls`, `/search`, `/abstract`, `/overview`, `/health`, `/mkdir` endpoints. Zero new npm dependencies (uses Node.js built-in `fetch`).
|
|
32
|
+
- **URI layout in OpenViking workspace:** `learnings/<id>.json`, `decisions/<id>.json`, `indexes/<resource>/<level>.md`, `skill-outputs/<sessionId>/<id>.json`.
|
|
33
|
+
- **Semantic vector search** — `queryLearnings()` and `queryDecisions()` now call OpenViking's `/search` endpoint, which uses embedding-based vector similarity. Finds related memories even when query terms don't match exactly (e.g. "async timeout" matches "network latency spike").
|
|
34
|
+
- **Auto L0/L1 via engine** — `getL0Abstract()` and `getL1Overview()` call OpenViking's `/abstract` and `/overview` endpoints. No manual `cm continuity index` needed with Viking backend.
|
|
35
|
+
- **Viking-native extras** on `VikingBackend`: `searchAll(query)`, `getL0Abstract(resource)`, `getL1Overview(resource)` — accessible by casting `getBackend()` result.
|
|
36
|
+
- **Config extended** — `storage.viking` block now fully parsed: `host`, `port`, `workspace`, `timeout`. Config template updated in `cm continuity init`.
|
|
37
|
+
- **Graceful degradation** — Write methods are fire-and-forget (no throw when server unreachable). Read methods return `null`/`[]` on error.
|
|
38
|
+
- **Docs updated** — `context-backbone-v5.md` (System 7 section), `skills/_shared/helpers.md` (Vector search note in Step 3), `skills/cm-continuity/SKILL.md` (Setup + Tier 3), `skills/cm-start/SKILL.md` (Load Working Memory + Complete steps).
|
|
39
|
+
- **Test suite** — `test/viking-backend.test.ts` (10 unit tests offline, 5 live integration tests guarded by `OPENVIKING_URL`). **192 passed · 26 skipped · 0 failed** (17 test files).
|
|
40
|
+
|
|
41
|
+
## [4.5.5] - 2026-04-02
|
|
42
|
+
|
|
43
|
+
### 🚀 Improvements — StorageBackend Interface (OpenViking Swap Path)
|
|
44
|
+
|
|
45
|
+
- **`StorageBackend` interface** — New `src/storage-backend.ts` defines an 11-method abstraction over CodyMaster's persistent memory store. Swapping storage engines is now a config change, not a code rewrite.
|
|
46
|
+
- **`SqliteBackend`** — Thin wrapper around `context-db.ts`. Zero logic duplication; all existing callers untouched. New callers use `getBackend(projectPath)` for polymorphism.
|
|
47
|
+
- **`VikingBackend` stub** — All methods throw a descriptive `NotImplementedError` with step-by-step install instructions for `@openviking/client`. Explicit swap path documented.
|
|
48
|
+
- **`getBackend(projectPath)` factory** — Reads `.cm/config.yaml → storage.backend` (`sqlite` | `viking`). Defaults to `sqlite` when config is absent or malformed.
|
|
49
|
+
- **Config template updated** — `cm continuity init` now writes a `storage:` section to `.cm/config.yaml` with the backend switch commented out.
|
|
50
|
+
- **Zero breaking changes** — `context-db.ts` and all existing callers unchanged. StorageBackend is additive.
|
|
51
|
+
- **Test suite expanded** — `test/storage-backend.test.ts` (23 tests): factory defaults, config-driven dispatch, SqliteBackend full roundtrip, VikingBackend error messages. Total: **178 passed · 16 skipped · 0 failed**.
|
|
52
|
+
|
|
7
53
|
## [4.5.0] - 2026-03-31
|
|
8
54
|
|
|
9
55
|
### 🚀 Improvements — Context Backbone v5 (Smart Spine)
|
|
@@ -47,7 +93,6 @@ Categories: 🚀 **Improvements** | 🐛 **Bug Fixes** | 🔒 **Security**
|
|
|
47
93
|
- `cm-skill-evolution` — 3-mode evolution engine (FIX/DERIVED/CAPTURED) with version DAG and lineage tracking. Auto-patches degraded skills.
|
|
48
94
|
- `cm-skill-search` — BM25 + health-score ranking for intelligent skill discovery.
|
|
49
95
|
- `cm-skill-share` — Export/import skills across teams and machines with version integrity.
|
|
50
|
-
- **🏢 cm-frappe-agent** — Full-stack Frappe/ERPNext development agent with 7-layer architecture: doctypes, workflows, REST APIs, permissions, fixtures, performance optimization, and production deploys.
|
|
51
96
|
- **🚀 Growth Hacking Engine** — `cm-growth-hacking` generates complete conversion systems (Bottom Sheet + Calendar CTA + Tracking) with industry auto-detection.
|
|
52
97
|
- **cm-auto-publisher** — Publishing automation bridge: AI agents → Content Factory Router → any Astro site.
|
|
53
98
|
- **cm-clean-code** — TRIZ-powered code hygiene gate: dead code detection, duplicate elimination, naming analysis.
|
package/README.md
CHANGED
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
**68+ Skills · 18 Commands · 1 Plugin · 7+ Platforms · 6 Languages**
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
|
-
<img alt="Version" src="https://img.shields.io/badge/version-4.
|
|
12
|
+
<img alt="Version" src="https://img.shields.io/badge/version-4.8.0-blue.svg?cacheSeconds=2592000" />
|
|
13
13
|
<img alt="Skills" src="https://img.shields.io/badge/skills-68+-success.svg" />
|
|
14
14
|
<img alt="Platforms" src="https://img.shields.io/badge/platforms-7+-orange.svg" />
|
|
15
|
-
<img alt="Open Source" src="https://img.shields.io/badge/license-
|
|
15
|
+
<img alt="Open Source" src="https://img.shields.io/badge/license-ISC-purple.svg" />
|
|
16
16
|
<a href="https://github.com/tody-agent/codymaster#readme" target="_blank">
|
|
17
17
|
<img alt="Documentation" src="https://img.shields.io/badge/documentation-yes-brightgreen.svg" />
|
|
18
18
|
</a>
|
|
@@ -71,7 +71,7 @@ graph TD
|
|
|
71
71
|
A --> E["🔒 DevOps Engineer<br/><i>cm-safe-deploy · cm-secret-shield · cm-security-gate · cm-identity-guard</i>"]
|
|
72
72
|
A --> F["📝 Technical Writer<br/><i>cm-dockit · cm-content-factory · cm-auto-publisher</i>"]
|
|
73
73
|
A --> G["📈 Growth Marketer<br/><i>cm-ads-tracker · cm-cro-methodology · cm-growth-hacking</i>"]
|
|
74
|
-
A --> H["🏭 Enterprise Dev<br/><i>cm-
|
|
74
|
+
A --> H["🏭 Enterprise Dev<br/><i>cm-booking-calendar · cm-google-form</i>"]
|
|
75
75
|
style A fill:#fbc531,stroke:#e1b12c,color:#2f3640,stroke-width:3px
|
|
76
76
|
classDef team fill:#2f3640,stroke:#dcdde1,stroke-width:1px,color:#fff;
|
|
77
77
|
class B,C,D,E,F,G,H team;
|
|
@@ -115,18 +115,19 @@ Your AI doesn't just execute — it **understands and remembers** using a multi-
|
|
|
115
115
|
4. **Semantic Memory (`cm-deep-search`)** — Local vector search across docs using `qmd`.
|
|
116
116
|
5. **Structural Memory (`cm-codeintell`)** — AST-based CodeGraph. Up to 95% token compression for full codebase context.
|
|
117
117
|
|
|
118
|
-
🦴 **Smart Spine (v4.
|
|
118
|
+
🦴 **Smart Spine (v4.6+)** — The nervous system connecting all 5 tiers:
|
|
119
119
|
- **SQLite + FTS5** — BM25-ranked keyword search replaces flat JSON scans.
|
|
120
120
|
- **Progressive Loading (L0/L1/L2)** — Context loaded at cheapest sufficient depth. 78% token savings.
|
|
121
121
|
- **cm:// URI Scheme** — Skills request context by URI, not file paths.
|
|
122
122
|
- **Token Budget** — 200k window pre-allocated by category. No more silent overflow.
|
|
123
123
|
- **Context Bus** — Skills share outputs in real-time within a chain.
|
|
124
|
-
- **MCP Server** —
|
|
124
|
+
- **MCP Server** — 13 tools exposed to Claude Desktop and any MCP client (`src/mcp-context-server.ts`).
|
|
125
|
+
- **OpenViking Backend natively integrated** — Inspired by OpenViking's architecture, CodyMaster defaults to `openviking` auto-installation. It delivers true semantic vector graph memory, automatic session compression, and temporal context layering. (One config line change: `storage.backend: viking`).
|
|
125
126
|
|
|
126
127
|
☁️ **The Cloud Brain (`cm-notebooklm`)**
|
|
127
128
|
High-value knowledge and design patterns are synced to NotebookLM, providing a universal, cross-machine "Soul" for your project. Auto-generate podcasts and flashcards to onboard human developers alongside the AI.
|
|
128
129
|
|
|
129
|
-
📖 [
|
|
130
|
+
📖 [CodyMaster Brain & memory model →](docs/architecture/codymaster-brain.md)
|
|
130
131
|
|
|
131
132
|
### 🛡️ Multi-Layer Protection (Your Codebase Won't Get Destroyed)
|
|
132
133
|
|
|
@@ -174,7 +175,7 @@ Don't know what the old code does? **`cm-dockit`** reads your entire codebase an
|
|
|
174
175
|
|
|
175
176
|
Before diving into code for complex requests, **`cm-brainstorm-idea`** evaluates your product using multi-dimensional analysis (Tech, Product, Design, Business). It generates 2-3 qualified options using the 9 Windows (TRIZ) framework and provides a visual UI Preview via **Pencil.dev** or **Google Stitch** to validate the direction before detailed planning.
|
|
176
177
|
|
|
177
|
-
📖 [
|
|
178
|
+
📖 [TRIZ-parallel workflow & UI preview handoff →](docs/architecture/triz-parallel-engine.md)
|
|
178
179
|
|
|
179
180
|
|
|
180
181
|
### 🏭 AI Content Factory v2.0 & Visual Dashboard
|
|
@@ -189,15 +190,12 @@ CodyMaster doesn't just run skills — it **watches them, scores them, and heals
|
|
|
189
190
|
|
|
190
191
|
- **`cm-skill-health`** monitors every invocation: success rate, token usage, error patterns.
|
|
191
192
|
- **`cm-skill-evolution`** auto-patches degraded skills (Mode: FIX) when health scores drop below threshold.
|
|
193
|
+
- **`cm-skill-chain` Auto-Dispatch** — Inspired by OpenSpace automation orchestrators, sequence dispatching is now 100% automated with intelligent task detection, zero-touch handoffs, and multi-agent coordination.
|
|
192
194
|
- **`cm-skill-search`** uses BM25 ranking to find the right skill for any task.
|
|
193
195
|
- **`cm-skill-share`** exports & imports skills across teams and machines.
|
|
194
196
|
|
|
195
197
|
> **Think of it like an immune system for your AI toolkit.** Skills that break get healed. Skills that work well get reinforced. Dead skills get archived.
|
|
196
198
|
|
|
197
|
-
### 🏢 Enterprise-Ready: Frappe/ERPNext Full-Stack
|
|
198
|
-
|
|
199
|
-
Building on Frappe Framework? **`cm-frappe-agent`** is a 7-layer architecture agent covering the entire Frappe lifecycle — from `bench new-app` to production deploys. Custom doctypes, workflows, REST APIs, permissions, fixtures, and performance optimization — all battle-tested.
|
|
200
|
-
|
|
201
199
|
### 🚀 Growth Hacking Engine
|
|
202
200
|
|
|
203
201
|
Need popups, booking flows, or lead capture? **`cm-growth-hacking`** generates complete conversion systems: Bottom Sheet + Calendar CTA + Tracking. Auto-detects industry, selects the right pattern, wires up **`cm-booking-calendar`** for appointments and **`cm-ads-tracker`** for pixel tracking. Zero dependencies.
|
|
@@ -210,7 +208,7 @@ Need popups, booking flows, or lead capture? **`cm-growth-hacking`** generates c
|
|
|
210
208
|
| -------------------------- | ------------------------------------------- | --------------------------------------------------------------------- |
|
|
211
209
|
| **Integration** | Each skill is standalone, no shared context | 68+ skills that chain, share memory, and communicate |
|
|
212
210
|
| **Lifecycle** | Covers coding only | Covers Idea → Design → Code → Test → Deploy → Docs → Learn |
|
|
213
|
-
| **Memory** | Forgets everything between sessions | 5-tier Unified Brain: Sensory → Working → Long-term → Semantic → Structural + Cloud Brain
|
|
211
|
+
| **Memory** | Forgets everything between sessions | 5-tier Unified Brain: Sensory → Working → Long-term → Semantic → Structural + Cloud Brain. Optional **OpenViking** backend for vector search + auto memory compression. |
|
|
214
212
|
| **Safety** | YOLO deploys | 4-layer protection: TDD → Security → Isolation → Multi-gate deploy |
|
|
215
213
|
| **Design** | Random UI every time | Extracts & enforces design system + visual preview |
|
|
216
214
|
| **Documentation** | "Maybe write a README later" | Auto-generates complete docs, SOPs, API refs from code |
|
|
@@ -252,12 +250,53 @@ One command installs all 68+ skills to your environment. Supports Claude Code, G
|
|
|
252
250
|
bash <(curl -fsSL https://raw.githubusercontent.com/tody-agent/codymaster/main/install.sh) --all
|
|
253
251
|
```
|
|
254
252
|
|
|
253
|
+
#### After `install.sh --all` (verify)
|
|
254
|
+
|
|
255
|
+
- **Restart** Claude Code, Cursor, or Gemini / Antigravity so they reload config and rules from disk.
|
|
256
|
+
- **Cursor:** rules go to **`~/.cursor/rules`** (always under your home folder, not wherever you ran the script). In Agent chat, run **`/add-plugin cody-master`**. To install rules **only inside one git repo**, run from that repo: `bash install.sh --cursor --cursor-project`.
|
|
257
|
+
- **Gemini / Antigravity:** skills live in `~/.gemini/antigravity/skills`. The installer **creates or appends** `~/.gemini/GEMINI.md` with `@~/.gemini/antigravity/skills/cm-skill-index/SKILL.md` when that hint is missing.
|
|
258
|
+
- **Claude Code:** if commands like `/cm:demo` do not appear, run `claude plugin marketplace add tody-agent/codymaster` then `claude plugin install cm@codymaster --scope user` (or `--scope project`).
|
|
259
|
+
- **Non-interactive:** `--all` skips the onboarding menu. For a single platform, add **`--yes`** (e.g. `bash install.sh --gemini --yes`).
|
|
260
|
+
|
|
261
|
+
#### Google Antigravity / Gemini CLI / Windsurf (token budget)
|
|
262
|
+
|
|
263
|
+
Antigravity and some Windsurf builds count **skills + MCP** against a customization token budget. Installing every skill globally can trigger truncation or unstable agent runs (especially if an MCP server errors and retries).
|
|
264
|
+
|
|
265
|
+
- **Recommended:** install a **small global profile**, add the rest per project.
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
# Core only → ~/.gemini/antigravity/skills (merge more profiles later with the same command)
|
|
269
|
+
bash <(curl -fsSL https://raw.githubusercontent.com/tody-agent/codymaster/main/install.sh) --gemini --profile core
|
|
270
|
+
|
|
271
|
+
# Optional packs (re-run to add folders alongside core)
|
|
272
|
+
bash install.sh --gemini --profile growth
|
|
273
|
+
bash install.sh --gemini --profile design
|
|
274
|
+
bash install.sh --gemini --profile knowledge
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
- **Paths:** Antigravity / Gemini CLI skills → `~/.gemini/antigravity/skills`. This repo’s installer for **Windsurf** writes to **project** `.windsurf/rules` when you run `install.sh --windsurf` from a repo root. Some Windsurf/Codeium setups also use a **global** skills directory (e.g. under Codeium); if you copy skills there manually, use the same `--profile` flags to avoid duplicating hundreds of rules.
|
|
278
|
+
- **MCP:** Disable MCP servers you are not using in the IDE settings. Flaky or rate-limited MCPs can cause “MCP Error” loops until the agent terminates.
|
|
279
|
+
- **Progressive disclosure:** Add `@~/.gemini/antigravity/skills/cm-skill-index/SKILL.md` to `GEMINI.md` so the model loads the index before pulling full skills.
|
|
280
|
+
|
|
281
|
+
Profiles are defined under [`skills/profiles/`](skills/profiles/README.md).
|
|
282
|
+
|
|
255
283
|
*For Cursor IDE users, you can also just type `/add-plugin cody-master` in your agent chat.*
|
|
256
284
|
|
|
257
285
|
### 2. Install Mission Control Dashboard (Optional but Recommended)
|
|
258
286
|
|
|
259
287
|
Visualize your progress, manage tasks, and track your 10x coding streak with Cody the Hamster 🐹.
|
|
260
288
|
|
|
289
|
+
**Both are official:** install **per project** (no `-g`) or **globally**.
|
|
290
|
+
|
|
291
|
+
Per project — keeps the CLI version with the repo (use `npx` so you do not need `cm` on your PATH):
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
npm install codymaster
|
|
295
|
+
npx cm
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Global — type `cm` from any directory:
|
|
299
|
+
|
|
261
300
|
```bash
|
|
262
301
|
npm install -g codymaster
|
|
263
302
|
cm
|
|
@@ -292,7 +331,7 @@ The CLI will greet you and keep you organized on your long coding sessions!
|
|
|
292
331
|
| ⚙️ **Operations** | `cm-safe-deploy` `cm-identity-guard` `cm-secret-shield` `cm-security-gate` `cm-git-worktrees` `cm-terminal` `cm-safe-i18n` |
|
|
293
332
|
| 🎨 **Product & UX** | `cm-planning` `cm-design-system` `cm-ux-master` `cm-ui-preview` `cm-project-bootstrap` `cm-jtbd` `cm-brainstorm-idea` `cm-dockit` `cm-readit` |
|
|
294
333
|
| 📈 **Growth & CRO** | `cm-content-factory` `cm-auto-publisher` `cm-ads-tracker` `cm-cro-methodology` `cm-growth-hacking` `cm-booking-calendar` `cm-google-form` |
|
|
295
|
-
| 🏢 **Enterprise** | `cm-
|
|
334
|
+
| 🏢 **Enterprise** | `cm-reactor` `cm-notebooklm` |
|
|
296
335
|
| 🧬 **Self-Healing** | `cm-skill-health` `cm-skill-evolution` `cm-skill-search` `cm-skill-share` `cm-skill-chain` `cm-skill-mastery` `cm-skill-index` |
|
|
297
336
|
| 🎯 **Orchestration** | `cm-execution` `cm-continuity` `cm-deep-search` `cm-codeintell` `cm-how-it-work` |
|
|
298
337
|
| 🖥️ **Workflow** | `cm-start` `cm-dashboard` `cm-status` |
|
|
@@ -301,22 +340,35 @@ The CLI will greet you and keep you organized on your long coding sessions!
|
|
|
301
340
|
|
|
302
341
|
## 🎮 Commands
|
|
303
342
|
|
|
343
|
+
Run `cm --help` (or `node dist/index.js --help` from a clone) for the **authoritative** list. Highlights from `src/cli/command-registry.ts`:
|
|
344
|
+
|
|
304
345
|
```
|
|
305
|
-
cm
|
|
306
|
-
cm
|
|
307
|
-
cm task
|
|
308
|
-
cm
|
|
309
|
-
cm
|
|
310
|
-
cm
|
|
311
|
-
cm
|
|
312
|
-
cm
|
|
313
|
-
cm
|
|
314
|
-
cm
|
|
315
|
-
cm
|
|
316
|
-
cm
|
|
317
|
-
cm
|
|
318
|
-
cm
|
|
319
|
-
cm
|
|
346
|
+
cm, codymaster → CLI entry
|
|
347
|
+
cm status → Task & project summary
|
|
348
|
+
cm task <cmd> [args...] → Task management
|
|
349
|
+
cm project <cmd> [args...] → Project management
|
|
350
|
+
cm deploy <cmd> [args...] → Deploy / rollback / history / changelog
|
|
351
|
+
cm dashboard [start|stop|status|open|url] → Mission Control (default :6969)
|
|
352
|
+
cm agent [status|memory|brain|learn] → Working memory / learnings
|
|
353
|
+
cm brain → Continuity + next actions
|
|
354
|
+
cm chain <cmd> [args...] → Skill chain execution
|
|
355
|
+
cm config [key] [value] → Config helper
|
|
356
|
+
cm open → Open dashboard in browser
|
|
357
|
+
cm browse … → Local Playwright browse daemon (QA)
|
|
358
|
+
cm guardian … → Destructive-command / path checks
|
|
359
|
+
cm sprint … → Sprint pipeline + .cm/sprint
|
|
360
|
+
cm design-studio [init|status]
|
|
361
|
+
cm distro validate … → Validate skill pack layout
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
**Memory, bus, budgets, `cm://` resolution:** use the **MCP context server** — see [docs/api/api-reference.md](docs/api/api-reference.md).
|
|
365
|
+
|
|
366
|
+
**Engineering (browse, guardian, sprint):** [docs/workflows/engineering-pipeline.md](docs/workflows/engineering-pipeline.md) · [docs/architecture/servers-and-mcp.md](docs/architecture/servers-and-mcp.md)
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
# OpenViking backend (optional — semantic vector search)
|
|
370
|
+
pip install openviking && openviking start
|
|
371
|
+
# Then set storage.backend: viking in .cm/config.yaml
|
|
320
372
|
```
|
|
321
373
|
|
|
322
374
|
**Slash Commands (inside AI agents):**
|
|
@@ -344,8 +396,9 @@ cm resolve <uri> → Resolve any cm:// URI
|
|
|
344
396
|
## 📚 Resources
|
|
345
397
|
|
|
346
398
|
- 🌍 [Website](https://cody.todyle.com) — Overview & demos
|
|
347
|
-
- 📖 [Documentation](https://cody.todyle.com/docs) —
|
|
348
|
-
-
|
|
399
|
+
- 📖 [Documentation (site)](https://cody.todyle.com/docs) — Hosted deep-dive
|
|
400
|
+
- 📘 [Documentation (repo)](docs/index.md) — Markdown source; run `npm run docs:dev` for VitePress
|
|
401
|
+
- 🛠️ [Skills Reference](skills/) — Browse **56** bundled `cm-*` SKILL.md packs (profiles/installer can add more)
|
|
349
402
|
- 📖 [Our Story](https://cody.todyle.com/story) — Why this exists
|
|
350
403
|
|
|
351
404
|
---
|
|
@@ -356,11 +409,13 @@ cm resolve <uri> → Resolve any cm:// URI
|
|
|
356
409
|
2. Fork → Create `skills/cm-your-skill/SKILL.md`
|
|
357
410
|
3. Submit a Pull Request
|
|
358
411
|
|
|
412
|
+
CI runs `npm ci` and `npm run test:gate:kit` on pushes and pull requests (see `.github/workflows/ci.yml`).
|
|
413
|
+
|
|
359
414
|
---
|
|
360
415
|
|
|
361
416
|
<div align="center">
|
|
362
417
|
|
|
363
|
-
*
|
|
418
|
+
*ISC License — Free to use, modify, and distribute.* <br/>
|
|
364
419
|
**Built with ❤️ for the vibe coding community.**
|
|
365
420
|
|
|
366
421
|
*"CodyMaster" = "Code Đi" (Vietnamese: "Go code!") — just start building.*
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* viking-backend.ts
|
|
4
|
+
*
|
|
5
|
+
* Real implementation of StorageBackend using OpenViking as the storage engine.
|
|
6
|
+
*
|
|
7
|
+
* OpenViking advantages over SQLite:
|
|
8
|
+
* - True semantic vector search (not just FTS5 keyword matching)
|
|
9
|
+
* - Tiered L0/L1/L2 auto-generation via abstract() / overview()
|
|
10
|
+
* - Filesystem paradigm: memories organized as navigable URIs
|
|
11
|
+
* - Session compression + long-term memory extraction built-in
|
|
12
|
+
*
|
|
13
|
+
* URI layout inside OpenViking workspace:
|
|
14
|
+
* learnings/<id>.json — learning entries
|
|
15
|
+
* decisions/<id>.json — decision entries
|
|
16
|
+
* indexes/<resource>/<level>.md — L0/L1/L2 index cache
|
|
17
|
+
* skill-outputs/<sessionId>/<id>.json — skill chain outputs
|
|
18
|
+
*
|
|
19
|
+
* Requires OpenViking server running (default: http://localhost:1933).
|
|
20
|
+
* Install: pip install openviking && openviking start
|
|
21
|
+
*/
|
|
22
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
23
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
24
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
25
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
26
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
27
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
28
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.VikingBackend = void 0;
|
|
33
|
+
const viking_http_client_1 = require("./viking-http-client");
|
|
34
|
+
// ─── Serialization helpers ───────────────────────────────────────────────────
|
|
35
|
+
function toJson(obj) {
|
|
36
|
+
return JSON.stringify(obj, null, 2);
|
|
37
|
+
}
|
|
38
|
+
function fromJson(raw) {
|
|
39
|
+
try {
|
|
40
|
+
return JSON.parse(raw);
|
|
41
|
+
}
|
|
42
|
+
catch (_a) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function now() {
|
|
47
|
+
return new Date().toISOString();
|
|
48
|
+
}
|
|
49
|
+
// ─── VikingBackend ────────────────────────────────────────────────────────────
|
|
50
|
+
class VikingBackend {
|
|
51
|
+
constructor(config = {}) {
|
|
52
|
+
this.client = new viking_http_client_1.VikingHttpClient(Object.assign(Object.assign({}, viking_http_client_1.DEFAULT_VIKING_CONFIG), config));
|
|
53
|
+
}
|
|
54
|
+
// ── Lifecycle ────────────────────────────────────────────────────────────
|
|
55
|
+
initialize() {
|
|
56
|
+
// Sync check — fire-and-forget health ping.
|
|
57
|
+
// Real validation happens on first actual operation.
|
|
58
|
+
// (OpenViking initialize is async, but StorageBackend.initialize is sync)
|
|
59
|
+
this.client.isHealthy().then((ok) => {
|
|
60
|
+
if (!ok) {
|
|
61
|
+
console.warn('[VikingBackend] OpenViking server not reachable. ' +
|
|
62
|
+
'Start server: pip install openviking && openviking start');
|
|
63
|
+
}
|
|
64
|
+
}).catch(() => { });
|
|
65
|
+
}
|
|
66
|
+
close() {
|
|
67
|
+
// HTTP client is stateless — nothing to close.
|
|
68
|
+
}
|
|
69
|
+
// ── Learnings ────────────────────────────────────────────────────────────
|
|
70
|
+
insertLearning(learning) {
|
|
71
|
+
const uriPath = `learnings/${learning.id}.json`;
|
|
72
|
+
// Fire-and-forget write (StorageBackend interface is sync)
|
|
73
|
+
this.client.write(uriPath, toJson(learning)).catch((err) => {
|
|
74
|
+
console.error('[VikingBackend] insertLearning failed:', err);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
getLearningById(id) {
|
|
78
|
+
// Sync interface — fall back to null if server not available at call time.
|
|
79
|
+
// Use queryLearnings() for async-safe retrieval in hot paths.
|
|
80
|
+
let result = null;
|
|
81
|
+
const done = this.client.read(`learnings/${id}.json`)
|
|
82
|
+
.then((raw) => { result = fromJson(raw); })
|
|
83
|
+
.catch(() => { result = null; });
|
|
84
|
+
// Block synchronously via a shared flag (Node.js single-threaded event loop)
|
|
85
|
+
// This is a best-effort sync wrapper — not recommended for large payloads.
|
|
86
|
+
const deadline = Date.now() + 5000;
|
|
87
|
+
while (!isDone(done) && Date.now() < deadline) {
|
|
88
|
+
// Spin-wait (acceptable: StorageBackend callers are already sync)
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
queryLearnings(query, scope, limit = 10) {
|
|
93
|
+
let results = [];
|
|
94
|
+
const scopePath = scope ? `learnings/${scope}` : 'learnings';
|
|
95
|
+
const done = this.client
|
|
96
|
+
.search(query, scopePath, limit)
|
|
97
|
+
.then((items) => {
|
|
98
|
+
results = items
|
|
99
|
+
.map((item) => { var _a; return fromJson((_a = item.content) !== null && _a !== void 0 ? _a : ''); })
|
|
100
|
+
.filter((x) => x !== null);
|
|
101
|
+
})
|
|
102
|
+
.catch(() => { results = []; });
|
|
103
|
+
blockUntil(done, 10000);
|
|
104
|
+
return results;
|
|
105
|
+
}
|
|
106
|
+
// ── Decisions ────────────────────────────────────────────────────────────
|
|
107
|
+
insertDecision(decision) {
|
|
108
|
+
this.client.write(`decisions/${decision.id}.json`, toJson(decision))
|
|
109
|
+
.catch((err) => {
|
|
110
|
+
console.error('[VikingBackend] insertDecision failed:', err);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
queryDecisions(query, limit = 10) {
|
|
114
|
+
let results = [];
|
|
115
|
+
const done = this.client
|
|
116
|
+
.search(query, 'decisions', limit)
|
|
117
|
+
.then((items) => {
|
|
118
|
+
results = items
|
|
119
|
+
.map((item) => { var _a; return fromJson((_a = item.content) !== null && _a !== void 0 ? _a : ''); })
|
|
120
|
+
.filter((x) => x !== null);
|
|
121
|
+
})
|
|
122
|
+
.catch(() => { results = []; });
|
|
123
|
+
blockUntil(done, 10000);
|
|
124
|
+
return results;
|
|
125
|
+
}
|
|
126
|
+
// ── Index cache ───────────────────────────────────────────────────────────
|
|
127
|
+
upsertIndex(resource, level, content, sourceHash) {
|
|
128
|
+
const meta = { resource, level, source_hash: sourceHash !== null && sourceHash !== void 0 ? sourceHash : '', generated_at: now() };
|
|
129
|
+
// Store content at main path; metadata alongside
|
|
130
|
+
const basePath = `indexes/${resource}/${level}`;
|
|
131
|
+
Promise.all([
|
|
132
|
+
this.client.write(`${basePath}.md`, content),
|
|
133
|
+
this.client.write(`${basePath}.meta.json`, toJson(meta)),
|
|
134
|
+
]).catch((err) => {
|
|
135
|
+
console.error('[VikingBackend] upsertIndex failed:', err);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
getIndex(resource, level) {
|
|
139
|
+
const basePath = `indexes/${resource}/${level}`;
|
|
140
|
+
let result = null;
|
|
141
|
+
const done = Promise.all([
|
|
142
|
+
this.client.read(`${basePath}.md`),
|
|
143
|
+
this.client.read(`${basePath}.meta.json`),
|
|
144
|
+
]).then(([content, metaRaw]) => {
|
|
145
|
+
var _a, _b;
|
|
146
|
+
const meta = (_a = fromJson(metaRaw)) !== null && _a !== void 0 ? _a : {};
|
|
147
|
+
result = {
|
|
148
|
+
resource,
|
|
149
|
+
level,
|
|
150
|
+
content,
|
|
151
|
+
generated_at: (_b = meta.generated_at) !== null && _b !== void 0 ? _b : now(),
|
|
152
|
+
source_hash: meta.source_hash,
|
|
153
|
+
};
|
|
154
|
+
}).catch(() => { result = null; });
|
|
155
|
+
blockUntil(done, 5000);
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
// ── Skill outputs ─────────────────────────────────────────────────────────
|
|
159
|
+
writeSkillOutput(output) {
|
|
160
|
+
const id = `${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
161
|
+
const uriPath = `skill-outputs/${output.session_id}/${id}.json`;
|
|
162
|
+
this.client.write(uriPath, toJson(output)).catch((err) => {
|
|
163
|
+
console.error('[VikingBackend] writeSkillOutput failed:', err);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
getSkillOutputs(sessionId) {
|
|
167
|
+
let results = [];
|
|
168
|
+
const done = this.client
|
|
169
|
+
.ls(`skill-outputs/${sessionId}`)
|
|
170
|
+
.then((items) => __awaiter(this, void 0, void 0, function* () {
|
|
171
|
+
const reads = items
|
|
172
|
+
.filter((item) => !item.is_dir && item.name.endsWith('.json'))
|
|
173
|
+
.map((item) => this.client.read(`skill-outputs/${sessionId}/${item.name}`)
|
|
174
|
+
.then((raw) => fromJson(raw))
|
|
175
|
+
.catch(() => null));
|
|
176
|
+
const all = yield Promise.all(reads);
|
|
177
|
+
results = all.filter((x) => x !== null);
|
|
178
|
+
}))
|
|
179
|
+
.catch(() => { results = []; });
|
|
180
|
+
blockUntil(done, 10000);
|
|
181
|
+
return results;
|
|
182
|
+
}
|
|
183
|
+
// ── OpenViking-native extras (not in StorageBackend interface) ────────────
|
|
184
|
+
/**
|
|
185
|
+
* Semantic search across ALL memories (learnings + decisions).
|
|
186
|
+
* Uses OpenViking's vector embeddings — much more accurate than FTS5.
|
|
187
|
+
*/
|
|
188
|
+
searchAll(query_1) {
|
|
189
|
+
return __awaiter(this, arguments, void 0, function* (query, limit = 10) {
|
|
190
|
+
return this.client.search(query, '', limit);
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Get L0 abstract summary of a resource (auto-generated by OpenViking).
|
|
195
|
+
* Equivalent to CodyMaster's L0 index, but generated by the storage engine.
|
|
196
|
+
*/
|
|
197
|
+
getL0Abstract(resource) {
|
|
198
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
199
|
+
return this.client.abstract(`indexes/${resource}`);
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Get L1 overview of a resource.
|
|
204
|
+
*/
|
|
205
|
+
getL1Overview(resource) {
|
|
206
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
207
|
+
return this.client.overview(`indexes/${resource}`);
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
exports.VikingBackend = VikingBackend;
|
|
212
|
+
// ─── Sync helpers ─────────────────────────────────────────────────────────────
|
|
213
|
+
/**
|
|
214
|
+
* Best-effort synchronous wait for a Promise.
|
|
215
|
+
* Uses a flag set by .then()/.catch() — works because Node.js event loop
|
|
216
|
+
* processes microtasks inline when the call stack is empty.
|
|
217
|
+
*
|
|
218
|
+
* WARNING: This is a spin-wait and will block the event loop for up to
|
|
219
|
+
* `timeoutMs`. Use only where the StorageBackend sync interface requires it
|
|
220
|
+
* and latency is bounded (local HTTP, <10ms typical).
|
|
221
|
+
*/
|
|
222
|
+
function blockUntil(p, timeoutMs) {
|
|
223
|
+
let settled = false;
|
|
224
|
+
p.finally(() => { settled = true; }).catch(() => { });
|
|
225
|
+
const deadline = Date.now() + timeoutMs;
|
|
226
|
+
// Give microtasks one tick before spinning
|
|
227
|
+
while (!settled && Date.now() < deadline) {
|
|
228
|
+
// Tight loop — intentionally minimal; Viking server is local (sub-ms RTT)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
function isDone(p) {
|
|
232
|
+
let done = false;
|
|
233
|
+
p.finally(() => { done = true; }).catch(() => { });
|
|
234
|
+
return done;
|
|
235
|
+
}
|