speexor 0.1.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/API-REFERENCE.md +201 -0
- package/ARCHITECTURE.md +548 -0
- package/CHANGELOG.md +52 -0
- package/CODE-OF-CONDUCT.md +83 -0
- package/CONTRIBUTING.md +98 -0
- package/FAQ.md +105 -0
- package/LICENSE.md +21 -0
- package/PUBLISH.md +77 -0
- package/README.md +179 -0
- package/REFACTOR-LOG.md +40 -0
- package/ROADMAP.md +78 -0
- package/SECURITY.md +79 -0
- package/SUMMARY.md +46 -0
- package/TESTING.md +140 -0
- package/dist/agent-5D3BVWNK.js +37 -0
- package/dist/agent-5D3BVWNK.js.map +1 -0
- package/dist/chunk-2F66BZYJ.js +212 -0
- package/dist/chunk-2F66BZYJ.js.map +1 -0
- package/dist/chunk-5NA2TFPG.js +3 -0
- package/dist/chunk-5NA2TFPG.js.map +1 -0
- package/dist/chunk-B7WLHC4W.js +666 -0
- package/dist/chunk-B7WLHC4W.js.map +1 -0
- package/dist/chunk-SXALZEOJ.js +345 -0
- package/dist/chunk-SXALZEOJ.js.map +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +287 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/index.d.ts +31 -0
- package/dist/core/index.js +4 -0
- package/dist/core/index.js.map +1 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.js +205 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/index.d.ts +6 -0
- package/dist/plugins/index.js +3 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/types-0q_okI2g.d.ts +205 -0
- package/docs/PRD01.md +264 -0
- package/docs/PRD02.md +299 -0
- package/docs/PRD03.md +0 -0
- package/docs/PRD04.md +349 -0
- package/docs/PRD05.md +312 -0
- package/docs/SETUP.md +94 -0
- package/docs/TROUBLESHOOTING.md +113 -0
- package/examples/basic.yaml +61 -0
- package/package.json +102 -0
- package/schema/config.schema.json +119 -0
- package/speexor.config.yaml.example +30 -0
package/docs/PRD05.md
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# PRD v5: Speexor — Gap Analysis & Hardening Pass
|
|
2
|
+
|
|
3
|
+
**Product Name (official, final):** **Speexor** (Speex Orchestrator)
|
|
4
|
+
**Version:** 5.0 — Gap Analysis & Correction Layer on top of v1–v4
|
|
5
|
+
**Author:** Aditya (drafted with Claude)
|
|
6
|
+
**Date:** June 30, 2026
|
|
7
|
+
**Status:** Draft — this PRD does not add new product surface area; it **audits, corrects, and disambiguates** v1–v4 before further build-out.
|
|
8
|
+
|
|
9
|
+
> This document is different in kind from v1–v4. It does not introduce new features. It performs a structured audit of the previous four PRDs — looking for contradictions, undefined behavior, naming collisions, technically incorrect assumptions, and unresolved ambiguity — and converts each finding into a concrete fix, owned requirement, or explicit decision. **All references to "Konduktor" across v1–v4 are retroactively renamed to Speexor as of this version.**
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. Rebrand: Konduktor → Speexor
|
|
14
|
+
|
|
15
|
+
This is the first and most concrete gap: the product had no final name through four PRDs. From v5 onward, the following naming convention is canonical and supersedes every prior document:
|
|
16
|
+
|
|
17
|
+
| Item | Old (v1–v4) | New (v5, canonical) |
|
|
18
|
+
| --------------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------- |
|
|
19
|
+
| Product name | Konduktor | **Speexor** |
|
|
20
|
+
| Tagline | "The Orchestration Layer for Parallel AI Agents" | **"Speexor — The Autonomous Agent Orchestrator"** |
|
|
21
|
+
| CLI binary | `konduktor` (implied) | `speexor` (full) / `sx` (short alias) |
|
|
22
|
+
| Config file | `konduktor.config.yaml` | `speexor.config.yaml` |
|
|
23
|
+
| Env var prefix | unspecified | `SPEEXOR_*` (e.g., `SPEEXOR_LOG_LEVEL`) |
|
|
24
|
+
| npm scope | `@konduktor/*` | `@speexor/*` (e.g., `@speexor/sdk`, `@speexor/core`) |
|
|
25
|
+
| Local data directory | unspecified | `~/.speexor/{hash}-{projectId}/` (mirrors AO's pattern, made explicit per FR-83) |
|
|
26
|
+
| Glossary file | `GLOSSARY.md` | unchanged, now references Speexor terms |
|
|
27
|
+
| Extension manifest filename | `konduktor.extension.json` | `speexor.extension.json` |
|
|
28
|
+
| Marketplace command | `konduktor ext ...` | `speexor ext ...` (alias `sx ext ...`) |
|
|
29
|
+
|
|
30
|
+
- **FR-83 (new):** All local state (Task Graph Store, Checkpoint data, Decision Journal, Extension cache, Secrets Vault references) lives under `~/.speexor/`, with one subdirectory per project hash, exactly as previously implied but never formally specified in v1–v4 (this was itself a gap — see §3.6).
|
|
31
|
+
- **FR-84 (new):** A one-time migration script (`speexor migrate-from-konduktor`) is provided **only if** any pre-v5 prototype code/config already exists locally (relevant since Aditya may have scaffolded early code under the old name) — renames config keys, directories, and npm package references automatically.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 2. Methodology of This Gap Analysis
|
|
36
|
+
|
|
37
|
+
Each of the four prior PRDs was reviewed against four lenses:
|
|
38
|
+
|
|
39
|
+
1. **Internal contradiction** — does a later PRD silently conflict with an earlier one without acknowledging the change?
|
|
40
|
+
2. **Undefined behavior** — does a requirement reference a mechanism (e.g., "checkpoint," "rollback," "skip") without specifying _exactly_ what happens, step by step?
|
|
41
|
+
3. **Technical correctness** — does a stated architecture choice actually work the way the document implies (e.g., Node.js concurrency primitives, git worktree semantics, SQLite concurrency)?
|
|
42
|
+
4. **Terminology/UX duplication** — do multiple PRDs introduce near-identical concepts (e.g., multiple "approval inbox" panels) under different names, creating redundant or confusing surface area?
|
|
43
|
+
|
|
44
|
+
Findings are grouped below by severity: **Critical** (must fix before any further implementation), **Major** (must fix before public/Marketplace launch), and **Minor** (should fix, low risk if deferred).
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 3. Critical Findings
|
|
49
|
+
|
|
50
|
+
### 3.1 Sandboxing extensions via `worker_threads` is not actually secure (Technical Error)
|
|
51
|
+
|
|
52
|
+
**Where:** v4 §7.3, FR-72 — "Extensions run in a sandboxed child process (Node.js `worker_threads`/`child_process` with restricted `fs`/`net` access via a permission-enforcing wrapper)."
|
|
53
|
+
**Problem:** `worker_threads` share the same process memory space and the same OS-level permissions as the main Node.js process. They do **not** provide a security boundary — a malicious extension running in a `worker_thread` can still access anything the host Node process can access unless additional isolation (Node's experimental Permission Model, a true V8 isolate sandbox like `isolated-vm`, or OS-level isolation such as a container/VM) is used. Citing `worker_threads` as a security mechanism in the same breath as `child_process` (which _can_ be meaningfully restricted via OS user/permissions) conflates a **performance** primitive with a **security** primitive.
|
|
54
|
+
**Fix (FR-85, new):** Redefine extension execution model explicitly:
|
|
55
|
+
|
|
56
|
+
- Extensions with `shell: none` and `network: none` declared → run in `isolated-vm` (true V8 isolate, no access to Node built-ins unless explicitly bridged) for skill-type extensions that are pure prompt/logic bundles.
|
|
57
|
+
- Extensions requiring `fileSystem`/`shell`/`network` access → run as a separate OS **process** (`child_process`, not `worker_threads`) launched with the minimum OS-level privileges possible, with a permission-enforcing proxy layer intercepting `fs`/`net`/`child_process` calls via a controlled require/import shim.
|
|
58
|
+
- `worker_threads` is reclassified in v5 as a **performance-only** primitive (§8 of v4, orchestrator-internal CPU-bound work), explicitly never used as a security boundary for third-party extension code.
|
|
59
|
+
|
|
60
|
+
### 3.2 Two unreconciled approval/governance systems (Internal Contradiction)
|
|
61
|
+
|
|
62
|
+
**Where:** v2 §5.3 (Governance Engine: `pending_approval` for proposed tasks) vs. v3 §4.4 (Risk Tier approval for high-stakes actions).
|
|
63
|
+
**Problem:** v2 introduced an approval gate for _new tasks created by agents_ (task-proposal governance). v3 introduced a _separate_ approval gate for _high-stakes actions within a task's execution_ (risk-tier governance). Neither PRD states how these two systems relate: is a newly proposed task that is also classified as high-stakes subject to **one** approval or **two sequential** approvals? Is "approve a proposed task" the same UI action as "approve a high-stakes action," or are they genuinely different decisions a user must make at different times for the same piece of work?
|
|
64
|
+
**Fix (FR-86, new):** Unify into a single **Approval Model** with two independent axes, both surfaced in one inbox (see §3.3 below for the related UX duplication fix):
|
|
65
|
+
|
|
66
|
+
- **Axis 1 — Task Origin Gate** (from v2): applies once, when a task is first created by an agent (not the user). Governed by `governance.autoApproveProposedTasks`/`autoApproveCategories`.
|
|
67
|
+
- **Axis 2 — Action Risk Gate** (from v3): applies every time _any_ task (user-given or agent-proposed) is about to execute a high-stakes action. Governed by `riskPolicy`.
|
|
68
|
+
- A task can require zero, one, or both gates. Both gates' pending items render in the **same** unified inbox view (§3.3), tagged by which axis triggered them, so the user never has to reconcile two mental models.
|
|
69
|
+
|
|
70
|
+
### 3.3 Three differently-named "approval inbox" UI panels (Terminology/UX Duplication)
|
|
71
|
+
|
|
72
|
+
**Where:** v2 FR-39 "Pending Approval Inbox," v3 §4.4/§7.2 "Approval Inbox" + "Review Queue," v4 §10.2 "Decision Journal / Review Queue" and "Approval Inbox" listed as two separate dashboard panels.
|
|
73
|
+
**Problem:** Across three PRDs, at least three distinct names are used for what is functionally 1–2 panels, with inconsistent scope (is "Review Queue" for low-confidence decisions only, or also for proposed tasks?).
|
|
74
|
+
**Fix (FR-87, new):** Canonical dashboard panel names, final:
|
|
75
|
+
|
|
76
|
+
- **"Approvals"** — single panel, surfaces both Axis 1 (proposed tasks) and Axis 2 (high-stakes actions) per the unified model in §3.2, each item tagged with its gate type, countdown timer (if Axis 2), and default action.
|
|
77
|
+
- **"Decision Log"** — renamed from "Decision Journal"/"Review Queue," a read-only, searchable history of _all_ autonomous decisions (both auto-executed and approved/rejected ones), including the confidence score and reasoning. This panel never blocks anything — it is purely observational, distinct from the actionable "Approvals" panel.
|
|
78
|
+
- All prior references to "Review Queue," "Pending Approval Inbox," and "Decision Journal" as separate UI elements are deprecated in favor of these two.
|
|
79
|
+
|
|
80
|
+
### 3.4 Subagent worktree/branch model is underspecified and may not work as described (Technical Gap)
|
|
81
|
+
|
|
82
|
+
**Where:** v2 §4.2 — "subagent dari agent yang sama berbagi branch parent... commit ke sub-branch yang nanti di-merge ke branch agent induk."
|
|
83
|
+
**Problem:** Git worktrees require a linked working directory checked out from a specific commit/branch in the _same_ repository. The PRD never specifies: (a) at what point in time the subagent's sub-branch is forked from the parent agent's branch — if the parent agent continues committing after the subagent's worktree is created, the subagent's base goes stale, and the PRD has no defined re-sync/rebase protocol; (b) how concurrent writes to the parent's branch ref are serialized when the parent agent merges multiple subagent sub-branches sequentially; (c) what happens if a subagent's sub-branch and the parent's own concurrent work touch the same file.
|
|
84
|
+
**Fix (FR-88, new):** Formal **Worktree Hierarchy Protocol**:
|
|
85
|
+
|
|
86
|
+
1. A subagent's worktree is always forked from the parent agent's branch **at the exact commit hash** the parent had at spawn time (pinned, not floating to `HEAD`).
|
|
87
|
+
2. The parent agent **pauses its own commits** (but not its reasoning/file-editing in its own worktree) while a merge of a subagent's sub-branch is in progress — merges are serialized, never concurrent, even if multiple subagents finish around the same time (queued merge, not parallel merge).
|
|
88
|
+
3. If a merge conflict occurs, the parent agent attempts an automated resolution using the same Never-Ask Decision Ladder (v3 §4.1); if confidence is below threshold, the conflict is escalated as an Axis-2 high-stakes approval item (since an incorrect automated merge resolution is effectively irreversible once the parent agent proceeds).
|
|
89
|
+
4. This protocol is implemented in the new `worktree-hierarchy` module (added to the v2 architecture table) rather than left implicit in the Workspace plugin.
|
|
90
|
+
|
|
91
|
+
### 3.5 "maxDepth" is ambiguous between two different depth concepts (Internal Ambiguity)
|
|
92
|
+
|
|
93
|
+
**Where:** v2 §4.2 defines **Agent hierarchy depth** (Orchestrator → Agent → Subagent → Sub-subagent); v2 §4.1/Task Node schema defines **Task Graph depth** (`depth` field on a Task Node, 0 = root). v2 `decomposition.maxDepth` config key (§7) is used without specifying which of the two it constrains.
|
|
94
|
+
**Problem:** A Task Node's depth in the graph and the depth of the _agent_ assigned to execute it are related but not identical — a single agent could, in principle, be assigned to execute a task node while still being at "Agent" level (depth 1 in the agent hierarchy) even if that task node is deep in the graph (depth 4), if no further subagent spawning occurred for it. Conflating the two leads to incorrect enforcement of the safety limit the config key is supposed to provide.
|
|
95
|
+
**Fix (FR-89, new):** Split into two explicit, independently configured limits:
|
|
96
|
+
|
|
97
|
+
- `decomposition.maxTaskGraphDepth` — limits how deep the _Task Graph_ itself can be decomposed (Task Node depth field).
|
|
98
|
+
- `decomposition.maxAgentSpawnDepth` — limits how many levels of Subagent-spawns-Subagent are permitted (Agent hierarchy depth), independent of how deep the underlying task graph is.
|
|
99
|
+
- Both default to 3, but are tracked, logged, and enforced as separate counters in the Scheduler.
|
|
100
|
+
|
|
101
|
+
### 3.6 No formal local data directory/storage layout was ever specified (Gap)
|
|
102
|
+
|
|
103
|
+
**Where:** Implied throughout v1–v4 ("Task Graph Store," "Checkpoint data," "Decision Journal," "Secrets Vault") but never given an explicit on-disk layout.
|
|
104
|
+
**Fix:** Resolved by FR-83 (§1) — `~/.speexor/{hash}-{projectId}/` as the canonical root, with documented subpaths (`task-graph.sqlite`, `checkpoints/`, `decision-log.sqlite`, `extensions/`, `vault-refs.json` — the latter holding only _references_ into the OS keychain, never actual secret values).
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 4. Major Findings
|
|
109
|
+
|
|
110
|
+
### 4.1 No config schema migration strategy across v1→v4 `$schema` versions
|
|
111
|
+
|
|
112
|
+
**Where:** Every PRD introduces a new `$schema` URL (`config.schema.json`, `.v2.json`, `.v3.json`, `.v4.json`) without any migration tooling.
|
|
113
|
+
**Problem:** A user with a working `speexor.config.yaml` written against an earlier schema will silently break (or silently ignore new fields) when they upgrade the package — no validation error path was defined for "this config is for an older schema version."
|
|
114
|
+
**Fix (FR-90, new):** `speexor config validate` command detects schema version mismatch and runs an automatic, reversible migration (writes a `.bak` file first) with a diff preview before applying. CI for the core package includes a schema-migration test for every released schema version going forward.
|
|
115
|
+
|
|
116
|
+
### 4.2 Decision quality itself is never evaluated — only execution performance is benchmarked
|
|
117
|
+
|
|
118
|
+
**Where:** v4 §8.3 benchmarks latency/throughput; v3's Never-Ask Engine introduces confidence scoring and the Decision Ladder, but no PRD defines how we know the _confidence scores are actually well-calibrated_ (i.e., does a 0.8-confidence decision turn out correct ~80% of the time?).
|
|
119
|
+
**Problem:** Without this, "Never-Ask, Always-Decide" is a leap of faith — a miscalibrated agent could be highly confident and frequently wrong, which is worse than asking, not better.
|
|
120
|
+
**Fix (FR-91, new):** Add a **Decision Quality Eval Harness** (`speexor eval decisions`): periodically samples completed Decision Log entries, surfaces them to the user (or, optionally, a stronger "judge" LLM call) for a lightweight correct/incorrect/partial label, and computes a **calibration report** (confidence bucket vs. actual-correctness rate) surfaced in the dashboard's Decision Log view. This does not block execution (preserving the never-ask guarantee) — it is a continuous feedback loop for _tuning_ `confidenceThreshold` per project over time.
|
|
121
|
+
|
|
122
|
+
### 4.3 `rollback()` is defined in the `ActionPlugin` interface but never invoked by any defined flow
|
|
123
|
+
|
|
124
|
+
**Where:** v3 §4.3/§6.1 — `ActionPlugin` interface includes `rollback()`, but no FR in v1–v4 specifies _when_ the orchestrator actually calls it.
|
|
125
|
+
**Fix (FR-92, new):** Define explicit rollback triggers: (a) a high-stakes action's approval is later _rejected retroactively_ within a configurable grace window before an irreversible side effect actually lands (e.g., approved-but-not-yet-merged PR gets a last-second "actually no" — rollback closes/reverts it); (b) a Decision Quality Eval (§4.2) retroactively labels a low-confidence auto-executed decision as incorrect _and_ the action is still reversible — rollback is offered as a one-click dashboard action, never automatic.
|
|
126
|
+
|
|
127
|
+
### 4.4 Budget/cost guard is mentioned as an NFR but has no defined enforcement mechanism
|
|
128
|
+
|
|
129
|
+
**Where:** v2 §8 NFR table — "Cost Guard... agar runaway recursive decomposition tidak membengkakkan biaya API" — no FR anywhere defines what happens when a budget limit is hit.
|
|
130
|
+
**Fix (FR-93, new):** `riskPolicy.budgetLimitUSD` (per task graph, optional) — when projected/actual spend crosses 80% of the limit, new agent/subagent spawning is paused (in-flight agents finish their current atomic unit of work, per the Graceful Handoff pattern from v3 §5.2) and an Axis-1-style approval item appears asking the user to raise the limit, let it stop, or convert remaining queued nodes to manual/no-LLM-cost handling.
|
|
131
|
+
|
|
132
|
+
### 4.5 Extension permission defaults vs. action risk-tier defaults are two separate "default to safe" systems
|
|
133
|
+
|
|
134
|
+
**Where:** v4 `permissionsMode: strict` (extension capability gating) vs. v3 `defaultRiskTierForUnknownActions: high-stakes` (action-level gating). Both exist to "default to safe when unsure," but a developer reading only one PRD would not realize there are two independent safety defaults operating at different layers (install-time capability vs. runtime action).
|
|
135
|
+
**Fix (FR-94, new):** Document explicitly, in one consolidated **Security & Safety Defaults** reference table (new `SECURITY-DEFAULTS.md`), that these are intentionally two different layers — _Extension Permissions_ gate what an extension _can ever do_ (set once, at install), while _Action Risk Tiers_ gate what _any_ action (from any already-permitted extension or core agent) _does right now_ (evaluated every time). No config or behavior change required — this finding is a **documentation gap**, not a logic bug, but it was never written down anywhere in v1–v4 and would confuse contributors.
|
|
136
|
+
|
|
137
|
+
### 4.6 Retry/backoff behavior for LLM provider failures (rate limits, downtime) is entirely unspecified
|
|
138
|
+
|
|
139
|
+
**Where:** Multi-provider routing is described as a feature (v2 §5.1 FR-22, config example in v2 §7) but no PRD defines what happens when, e.g., OpenCode Go returns a rate-limit error mid-task.
|
|
140
|
+
**Fix (FR-95, new):** Agent Backend adapters implement a standard `onProviderError(error)` contract with exponential backoff and automatic fallback to the next configured provider in `agentDefaults` (e.g., Zen → DeepSeek → GLM, matching Aditya's actual existing fallback strategy) — this failure is logged to the Decision Log as a non-blocking, low-confidence-irrelevant system event (distinct from an autonomous _reasoning_ decision).
|
|
141
|
+
|
|
142
|
+
### 4.7 `maxAfkDurationHours` safety-valve behavior is vague
|
|
143
|
+
|
|
144
|
+
**Where:** v3 §9 config + risk table — "sesi otomatis pause & lapor" without specifying scope of the pause.
|
|
145
|
+
**Fix (FR-96, new):** Clarify precisely: at the `maxAfkDurationHours` boundary, the Scheduler **stops spawning new Agents/Subagents** (queued nodes wait) but does **not** kill already-running agents (they finish their current atomic unit of work and checkpoint normally, per Graceful Handoff). A digest notification is sent immediately (not waiting for the next scheduled daily digest). The session resumes spawning automatically once the user acknowledges the notification (a single tap/click, not a full review requirement) — preserving AFK-friendliness while still guaranteeing a human checkpoint exists.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 5. Minor Findings
|
|
150
|
+
|
|
151
|
+
| # | Finding | Fix |
|
|
152
|
+
| --- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
153
|
+
| 5.1 | No defined CLI binary alias (`speexor` vs. short form) — repeated typing burden for a CLI-heavy tool | `sx` adopted as the canonical short alias alongside full `speexor` (FR per §1 table) |
|
|
154
|
+
| 5.2 | v4 Marketplace index format ("simple Git-based index") never specifies a concrete schema | Define `registry-index.schema.json` (flat JSON array of manifest pointers + checksums) as part of M25, not left to implementation time |
|
|
155
|
+
| 5.3 | No defined behavior for what the dashboard shows when **zero** agents are running (empty state) | Add explicit "Empty State" requirement to Mission Control view: show a one-line call to action (submit a task) rather than a blank screen |
|
|
156
|
+
| 5.4 | "Simple Mode" (v3/v4) toggles UI complexity, but no FR defines whether Simple Mode users can still install/manage Extensions (a Power-Mode-coded concept) | Clarify: Simple Mode hides the Extension Manager's permission-matrix detail but still allows install/enable via a simplified one-line description per extension |
|
|
157
|
+
| 5.5 | No explicit log level / debug verbosity convention defined despite `SPEEXOR_LOG_LEVEL` env var now existing (§1) | Standard levels: `error`, `warn`, `info`, `debug`, `trace` — `info` default, documented in `SETUP.md` |
|
|
158
|
+
| 5.6 | The relationship between Aditya's existing CEO Orchestrator skill system (261+ skills, ECC/affaan-m repo pattern) and the v4 Skill extension format was left as an open question (v4 §17 Q5) without a decision | **Resolved here:** the v5 Skill manifest format (`speexor.extension.json`, `type: "skill"`) is designed as a **superset-compatible wrapper** — an existing ECC/affaan-m-style skill folder can be referenced via a thin manifest that points to the existing folder structure unchanged, rather than requiring Aditya to rewrite 261+ skills. This becomes an explicit FR-97 for the Extension Manager build phase. |
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 6. Updated Glossary Additions (v5)
|
|
163
|
+
|
|
164
|
+
The v4 glossary (§4 of v4) remains canonical; v5 adds the following terms that were used implicitly but never defined:
|
|
165
|
+
|
|
166
|
+
| Term | Definition |
|
|
167
|
+
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
168
|
+
| **Approvals** (capitalized, panel name) | The single unified dashboard panel per FR-87, covering both Task Origin Gate and Action Risk Gate items |
|
|
169
|
+
| **Decision Log** | The read-only observational history of all autonomous decisions, replacing "Decision Journal"/"Review Queue" naming |
|
|
170
|
+
| **Atomic Unit of Work** | The smallest in-progress chunk of an agent's current action (e.g., finishing one function, one file edit, one paragraph) that must complete before a Graceful Handoff (pause/redirect/interrupt) takes effect — referenced repeatedly since v3 but never formally named as a term until now |
|
|
171
|
+
| **Worktree Hierarchy Protocol** | The formal merge/sync protocol for subagent sub-branches into a parent agent's branch (FR-88) |
|
|
172
|
+
| **Task Origin Gate / Action Risk Gate** | The two independent axes of the unified Approval Model (FR-86) |
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## 7. Updated Configuration Example (`speexor.config.yaml`, v5, fully renamed and reconciled)
|
|
177
|
+
|
|
178
|
+
```yaml
|
|
179
|
+
$schema: https://registry.speexor.dev/schema/config.schema.v5.json
|
|
180
|
+
|
|
181
|
+
language:
|
|
182
|
+
default: en
|
|
183
|
+
ui: en
|
|
184
|
+
|
|
185
|
+
license: MIT
|
|
186
|
+
telemetry:
|
|
187
|
+
enabled: false
|
|
188
|
+
|
|
189
|
+
dataDir: "~/.speexor" # FR-83
|
|
190
|
+
|
|
191
|
+
decomposition:
|
|
192
|
+
maxTaskGraphDepth: 3 # FR-89 — was ambiguous "maxDepth" in v2
|
|
193
|
+
maxAgentSpawnDepth: 3 # FR-89 — split from the above
|
|
194
|
+
maxNodesPerGraph: 50
|
|
195
|
+
plannerProvider: opencode
|
|
196
|
+
plannerModel: deepseek-reasoner
|
|
197
|
+
|
|
198
|
+
scheduler:
|
|
199
|
+
maxConcurrentAgents: "auto"
|
|
200
|
+
retryOnFailure: 2
|
|
201
|
+
providerFallbackChain: ["opencode-zen", "deepseek-direct", "glm"] # FR-95
|
|
202
|
+
|
|
203
|
+
worktreeHierarchy: # FR-88, new module
|
|
204
|
+
pinToCommitHash: true
|
|
205
|
+
serializeMerges: true
|
|
206
|
+
conflictEscalatesToApproval: true
|
|
207
|
+
|
|
208
|
+
governance: # Axis 1 — Task Origin Gate (FR-86)
|
|
209
|
+
autoApproveProposedTasks: false
|
|
210
|
+
autoApproveCategories: ["lint-fix", "test-only"]
|
|
211
|
+
duplicateSimilarityThreshold: 0.85
|
|
212
|
+
|
|
213
|
+
riskPolicy: # Axis 2 — Action Risk Gate (FR-86)
|
|
214
|
+
autoApprove: ["reversible-low", "reversible-medium"]
|
|
215
|
+
requireApproval: ["irreversible-high-stakes"]
|
|
216
|
+
approvalTimeout: 4h
|
|
217
|
+
approvalDefaultAction: "skip"
|
|
218
|
+
budgetLimitUSD: 25 # FR-93, new
|
|
219
|
+
defaultRiskTierForUnknownActions: "high-stakes"
|
|
220
|
+
|
|
221
|
+
session:
|
|
222
|
+
mode: "background-daemon"
|
|
223
|
+
autoRestartOnCrash: true
|
|
224
|
+
maxAfkDurationHours: 12 # behavior clarified per FR-96
|
|
225
|
+
|
|
226
|
+
extensions:
|
|
227
|
+
marketplaceIndex: "https://registry.speexor.dev/index.json"
|
|
228
|
+
enabled: ["speexor-agent-opencode", "speexor-skill-test-writer"]
|
|
229
|
+
permissionsMode: "strict" # FR-94 — distinct layer from riskPolicy above
|
|
230
|
+
|
|
231
|
+
security:
|
|
232
|
+
secretsBackend: "os-keychain"
|
|
233
|
+
encryptAtRest: true
|
|
234
|
+
sandboxModel: "isolated-vm-or-process" # FR-85, replaces incorrect worker_threads claim
|
|
235
|
+
|
|
236
|
+
performance:
|
|
237
|
+
maxConcurrentAgents: "auto"
|
|
238
|
+
workerThreadPoolSize: 4 # explicitly performance-only, never security (FR-85)
|
|
239
|
+
|
|
240
|
+
ui:
|
|
241
|
+
defaultMode: "power"
|
|
242
|
+
panels:
|
|
243
|
+
approvals: "Approvals" # FR-87
|
|
244
|
+
decisionLog: "Decision Log" # FR-87
|
|
245
|
+
locales: ["en", "id"]
|
|
246
|
+
|
|
247
|
+
logging:
|
|
248
|
+
level: "info" # FR §5.5
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## 8. New/Revised Requirements Summary (Consolidated)
|
|
254
|
+
|
|
255
|
+
| FR | Title | Severity addressed |
|
|
256
|
+
| ----- | -------------------------------------------------------------------------------------- | ------------------ |
|
|
257
|
+
| FR-83 | Canonical local data directory (`~/.speexor/`) | Critical (3.6) |
|
|
258
|
+
| FR-84 | Migration script from any pre-rebrand prototype | Critical (rebrand) |
|
|
259
|
+
| FR-85 | Correct sandboxing model (`isolated-vm`/restricted process, not `worker_threads`) | Critical (3.1) |
|
|
260
|
+
| FR-86 | Unified two-axis Approval Model | Critical (3.2) |
|
|
261
|
+
| FR-87 | Canonical dashboard panel names (Approvals, Decision Log) | Critical (3.3) |
|
|
262
|
+
| FR-88 | Worktree Hierarchy Protocol (pinning, serialized merges, conflict escalation) | Critical (3.4) |
|
|
263
|
+
| FR-89 | Split `maxTaskGraphDepth` / `maxAgentSpawnDepth` | Critical (3.5) |
|
|
264
|
+
| FR-90 | Config schema migration tooling | Major (4.1) |
|
|
265
|
+
| FR-91 | Decision Quality Eval Harness & calibration reporting | Major (4.2) |
|
|
266
|
+
| FR-92 | Explicit rollback trigger conditions | Major (4.3) |
|
|
267
|
+
| FR-93 | Budget guard enforcement mechanism | Major (4.4) |
|
|
268
|
+
| FR-94 | Documented Security & Safety Defaults reference (no logic change) | Major (4.5) |
|
|
269
|
+
| FR-95 | Provider error retry/backoff/fallback contract | Major (4.6) |
|
|
270
|
+
| FR-96 | Clarified `maxAfkDurationHours` pause semantics | Major (4.7) |
|
|
271
|
+
| FR-97 | Skill manifest as superset-compatible wrapper over existing ECC/affaan-m skill folders | Minor (5.6) |
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## 9. Risks of _Not_ Fixing These Before Further Build
|
|
276
|
+
|
|
277
|
+
| If unfixed | Consequence |
|
|
278
|
+
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
279
|
+
| 3.1 (sandboxing) | False sense of security — a "sandboxed" extension could still read secrets/files, defeating the entire Security Model promise of v4 |
|
|
280
|
+
| 3.2/3.3 (approval duplication) | Confusing UX ships at launch, eroding trust ("why are there three different approval screens?") and requiring a breaking UI rework post-launch |
|
|
281
|
+
| 3.4 (worktree protocol) | Silent data loss or corrupted merges under real parallel load — the exact opposite of the "autonomous and reliable" promise |
|
|
282
|
+
| 3.5 (depth ambiguity) | Safety limit (`maxDepth`) is enforced incorrectly, potentially allowing runaway agent spawning despite the config appearing to cap it |
|
|
283
|
+
| 4.2 (no decision eval) | "Never-Ask" autonomy is unverifiable — no way to know if confidence scores are trustworthy until something goes visibly wrong in production |
|
|
284
|
+
| 4.4 (no budget enforcement) | Real financial risk — exactly the "biaya membludak" scenario already flagged as a risk in v2/v3 but never actually mitigated with a mechanism |
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## 10. Roadmap Impact
|
|
289
|
+
|
|
290
|
+
These fixes are **inserted before** the M22+ roadmap items from v4, as a new phase:
|
|
291
|
+
|
|
292
|
+
| Phase | Scope | Estimate |
|
|
293
|
+
| -------------------------------------- | ------------------------------------------------------------------------------------------------------- | -------- |
|
|
294
|
+
| **M0.5 — Rebrand Pass** | Rename all code/docs/config from Konduktor → Speexor, ship `speexor migrate-from-konduktor` | 2-3 days |
|
|
295
|
+
| **M22a — Critical Fixes** | FR-85, FR-86, FR-87, FR-88, FR-89 implemented and tested before any Marketplace/Extension work proceeds | 2 weeks |
|
|
296
|
+
| **M22b — Major Fixes** | FR-90 through FR-96 | 2 weeks |
|
|
297
|
+
| **M22c — Documentation Consolidation** | `SECURITY-DEFAULTS.md`, glossary additions (§6), `GLOSSARY.md` update | 3-4 days |
|
|
298
|
+
|
|
299
|
+
This adds roughly **4-5 weeks** ahead of the previously planned M22 (v4 roadmap), but is treated as non-negotiable: building the Extension Marketplace (M23+) on top of an insecure sandboxing model (3.1) or an unreconciled approval system (3.2/3.3) would require a breaking rework later, at far higher cost than fixing it now.
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## 11. Remaining Open Questions (after this audit)
|
|
304
|
+
|
|
305
|
+
1. Should `isolated-vm` (native dependency, can complicate cross-platform installs) be the default sandbox, or should v5 ship a process-isolation-only model first (simpler, fully JS-native) and add `isolated-vm` as an opt-in "stricter sandbox" mode later?
|
|
306
|
+
2. For the Decision Quality Eval Harness (FR-91), is it acceptable to occasionally use a paid LLM call as the "judge" for calibration sampling, given the project's free/local-first goal — or should judging always default to the user's own manual labeling to avoid any implied cost?
|
|
307
|
+
3. Should the Worktree Hierarchy Protocol's "serialize merges" rule (FR-88) become a throughput bottleneck for very wide graphs (many subagents finishing simultaneously) — is a smarter conflict-free merge strategy (e.g., per-file ownership assignment at decomposition time, preventing overlapping file edits in the first place) worth exploring as a v6 follow-up?
|
|
308
|
+
4. Is the rebrand (`Konduktor` → `Speexor`) purely cosmetic, or does "Speex" carry an intended meaning/brand story (e.g., relation to "speech," "speed," or something domain-specific) that should be reflected in the tagline, logo direction, or even product positioning beyond a name swap?
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
_PRD v5 is a correction layer, not a feature layer. No implementation work on v1–v4's planned features (M0–M30) should proceed past M22a until the Critical findings in §3 are resolved — they affect the integrity of the security model, the data layer, and the core execution protocol that every later feature depends on._
|
package/docs/SETUP.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Speexor Setup Guide
|
|
2
|
+
|
|
3
|
+
## Prerequisites
|
|
4
|
+
|
|
5
|
+
- **Node.js** >= 18.0.0
|
|
6
|
+
- **pnpm** (recommended) or npm
|
|
7
|
+
- **Git** >= 2.30 (for `git worktree` support)
|
|
8
|
+
- **GitHub CLI** (`gh`) — for tracker & SCM plugins (optional for local-only mode)
|
|
9
|
+
- **tmux** >= 3.0 — for tmux runtime (macOS/Linux, optional with process fallback)
|
|
10
|
+
- One or more AI coding agent CLIs:
|
|
11
|
+
- [OpenCode CLI](https://github.com/superdevids/opencode)
|
|
12
|
+
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code)
|
|
13
|
+
- [Aider](https://aider.chat/)
|
|
14
|
+
- [Codex CLI](https://github.com/openai/codex)
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Via npm
|
|
20
|
+
npm install -g @speexjs/speexor
|
|
21
|
+
|
|
22
|
+
# Or via pnpm
|
|
23
|
+
pnpm add -g @speexjs/speexor
|
|
24
|
+
|
|
25
|
+
# Or run from the monorepo
|
|
26
|
+
cd speexjs
|
|
27
|
+
pnpm install
|
|
28
|
+
pnpm --filter @speexjs/speexor build
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
### 1. Initialize a project
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
cd /path/to/your/project
|
|
37
|
+
speexor start https://github.com/username/repo.git
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This will:
|
|
41
|
+
- Create `speexor.config.yaml` with default configuration
|
|
42
|
+
- Create `.speexor/` directory for worktrees and logs
|
|
43
|
+
- Start the dashboard at `http://localhost:3000`
|
|
44
|
+
|
|
45
|
+
### 2. Spawn an agent for a task
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Using a GitHub issue ID
|
|
49
|
+
speexor agent spawn --task 42 --agent opencode
|
|
50
|
+
|
|
51
|
+
# Using a custom task ID
|
|
52
|
+
speexor agent spawn --task "feature-auth" --agent claude-code
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 3. Monitor progress
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Open dashboard in browser
|
|
59
|
+
open http://localhost:3000
|
|
60
|
+
|
|
61
|
+
# List active sessions
|
|
62
|
+
speexor list
|
|
63
|
+
|
|
64
|
+
# View agent logs
|
|
65
|
+
speexor logs <session-id>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 4. Stop a session
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
speexor stop <session-id>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Configuration
|
|
75
|
+
|
|
76
|
+
See `speexor config-help` for full schema reference, or refer to `examples/basic.yaml` in the package.
|
|
77
|
+
|
|
78
|
+
## Plugin Architecture
|
|
79
|
+
|
|
80
|
+
Speexor uses a 7-slot plugin architecture:
|
|
81
|
+
|
|
82
|
+
| Slot | Purpose | Default Plugin |
|
|
83
|
+
|------|---------|---------------|
|
|
84
|
+
| **Agent** | AI coding agent adapter | OpenCode, Claude Code, Aider, Codex |
|
|
85
|
+
| **Runtime** | Process execution environment | tmux (Unix), Process (Windows) |
|
|
86
|
+
| **Workspace** | Code isolation strategy | Git Worktree |
|
|
87
|
+
| **Tracker** | Task/issue source | GitHub Issues |
|
|
88
|
+
| **SCM** | Git/PR operations | GitHub (gh CLI) |
|
|
89
|
+
| **Notifier** | Alert channel | Desktop notifications |
|
|
90
|
+
| **Terminal** | Live session viewer | Web (dashboard) |
|
|
91
|
+
|
|
92
|
+
## Troubleshooting
|
|
93
|
+
|
|
94
|
+
See [TROUBLESHOOTING.md](./TROUBLESHOOTING.md) for common issues.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Speexor Troubleshooting Guide
|
|
2
|
+
|
|
3
|
+
## Common Issues
|
|
4
|
+
|
|
5
|
+
### "speexor.config.yaml not found"
|
|
6
|
+
|
|
7
|
+
**Cause:** You ran `speexor list` or `speexor agent spawn` without initializing a project first.
|
|
8
|
+
|
|
9
|
+
**Fix:** Run `speexor start <repo-url>` to create the config file, or manually create `speexor.config.yaml` in your project root.
|
|
10
|
+
|
|
11
|
+
### "Not a git repository"
|
|
12
|
+
|
|
13
|
+
**Cause:** You're running `speexor` outside a git repository.
|
|
14
|
+
|
|
15
|
+
**Fix:** Navigate to a git repository or run `git init` first.
|
|
16
|
+
|
|
17
|
+
### "tmux not available"
|
|
18
|
+
|
|
19
|
+
**Cause:** tmux is not installed on your system.
|
|
20
|
+
|
|
21
|
+
**Fix (macOS):**
|
|
22
|
+
```bash
|
|
23
|
+
brew install tmux
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Fix (Linux):**
|
|
27
|
+
```bash
|
|
28
|
+
sudo apt install tmux # Debian/Ubuntu
|
|
29
|
+
sudo dnf install tmux # Fedora
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Fix (Windows):** Speexor will automatically fall back to the Process runtime on Windows.
|
|
33
|
+
|
|
34
|
+
### "GitHub CLI (gh) not found"
|
|
35
|
+
|
|
36
|
+
**Cause:** The `gh` CLI is not installed but required for GitHub tracker/SCM plugins.
|
|
37
|
+
|
|
38
|
+
**Fix:**
|
|
39
|
+
```bash
|
|
40
|
+
# macOS
|
|
41
|
+
brew install gh
|
|
42
|
+
|
|
43
|
+
# Linux (Debian/Ubuntu)
|
|
44
|
+
sudo apt install gh
|
|
45
|
+
|
|
46
|
+
# Windows (winget)
|
|
47
|
+
winget install GitHub.cli
|
|
48
|
+
|
|
49
|
+
# Or manual: https://cli.github.com/
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Agent spawn fails
|
|
53
|
+
|
|
54
|
+
**Cause:** The specified agent CLI is not installed or not in PATH.
|
|
55
|
+
|
|
56
|
+
**Fix:** Ensure the agent CLI is installed and accessible:
|
|
57
|
+
```bash
|
|
58
|
+
# Verify
|
|
59
|
+
opencode --version
|
|
60
|
+
claude --version
|
|
61
|
+
aider --version
|
|
62
|
+
codex --version
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### "Worktree already exists"
|
|
66
|
+
|
|
67
|
+
**Cause:** A worktree for the same branch already exists, possibly from a previous interrupted session.
|
|
68
|
+
|
|
69
|
+
**Fix:**
|
|
70
|
+
```bash
|
|
71
|
+
# List worktrees
|
|
72
|
+
git worktree list
|
|
73
|
+
|
|
74
|
+
# Remove stale worktree
|
|
75
|
+
speexor stop <session-id>
|
|
76
|
+
# Or manually:
|
|
77
|
+
git worktree remove --force .speexor/worktrees/<task-id>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Dashboard not showing
|
|
81
|
+
|
|
82
|
+
**Cause:** Port 3000 might be in use, or the dashboard was not started.
|
|
83
|
+
|
|
84
|
+
**Fix:**
|
|
85
|
+
```bash
|
|
86
|
+
# Specify a different port
|
|
87
|
+
speexor start --port 4000
|
|
88
|
+
|
|
89
|
+
# Or start dashboard only (if already initialized)
|
|
90
|
+
speexor start
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Windows-Specific Issues
|
|
94
|
+
|
|
95
|
+
### ConPTY Fallback
|
|
96
|
+
|
|
97
|
+
On Windows, tmux is not available. Speexor automatically uses the Process runtime instead. This works for most cases but lacks live terminal streaming.
|
|
98
|
+
|
|
99
|
+
### Shell Path
|
|
100
|
+
|
|
101
|
+
If you use PowerShell, the default shell path detection should work. To customize:
|
|
102
|
+
|
|
103
|
+
```yaml
|
|
104
|
+
# In speexor.config.yaml
|
|
105
|
+
plugins:
|
|
106
|
+
runtime: process
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Getting Help
|
|
110
|
+
|
|
111
|
+
- Open an issue: https://github.com/superdevids/speexjs/issues
|
|
112
|
+
- Check the PRD: [PRD01.md](./PRD01.md)
|
|
113
|
+
- Ask in the SpeexJS community
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Speexor Configuration — Basic Example
|
|
2
|
+
# Agent Orchestrator for multi-AI coding agent orchestration
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# 1. Save this file as speexor.config.yaml in your project root
|
|
6
|
+
# 2. Run `speexor start` to initialize and open the dashboard
|
|
7
|
+
# 3. Run `speexor agent spawn --task <issue-id>` to spawn an agent
|
|
8
|
+
|
|
9
|
+
version: "1"
|
|
10
|
+
|
|
11
|
+
projects:
|
|
12
|
+
# --- Single project, single agent ---
|
|
13
|
+
- name: brainclash
|
|
14
|
+
repository: https://github.com/superdevids/brainclash
|
|
15
|
+
provider:
|
|
16
|
+
primary: opencode
|
|
17
|
+
fallback:
|
|
18
|
+
- claude-code
|
|
19
|
+
- aider
|
|
20
|
+
concurrentLimit: 3
|
|
21
|
+
|
|
22
|
+
# Automated reactions to CI and PR events
|
|
23
|
+
reactions:
|
|
24
|
+
ci-failed:
|
|
25
|
+
auto: true
|
|
26
|
+
action: fix
|
|
27
|
+
retries: 3
|
|
28
|
+
escalateAfter: 30
|
|
29
|
+
changes-requested:
|
|
30
|
+
auto: true
|
|
31
|
+
action: fix
|
|
32
|
+
retries: 2
|
|
33
|
+
escalateAfter: 60
|
|
34
|
+
approved-and-green:
|
|
35
|
+
auto: false
|
|
36
|
+
action: notify
|
|
37
|
+
retries: 0
|
|
38
|
+
escalateAfter: 0
|
|
39
|
+
|
|
40
|
+
# --- Second project with different provider ---
|
|
41
|
+
- name: kata-netizen
|
|
42
|
+
repository: https://github.com/superdevids/kata-netizen
|
|
43
|
+
provider:
|
|
44
|
+
primary: claude-code
|
|
45
|
+
concurrentLimit: 2
|
|
46
|
+
reactions:
|
|
47
|
+
ci-failed:
|
|
48
|
+
auto: true
|
|
49
|
+
action: fix
|
|
50
|
+
retries: 3
|
|
51
|
+
escalateAfter: 30
|
|
52
|
+
changes-requested:
|
|
53
|
+
auto: true
|
|
54
|
+
action: fix
|
|
55
|
+
retries: 2
|
|
56
|
+
escalateAfter: 45
|
|
57
|
+
approved-and-green:
|
|
58
|
+
auto: false
|
|
59
|
+
action: notify
|
|
60
|
+
retries: 0
|
|
61
|
+
escalateAfter: 0
|