opencode-workflow-guard 1.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.
@@ -0,0 +1,23 @@
1
+ # Acknowledgements & Ecosystem Inspirations
2
+
3
+ `opencode-workflow-guard` is built on original, clean-room TypeScript code, but draws design inspiration, best practices, and workflow ideas from the broader [OpenCode](https://opencode.ai) community and ecosystem:
4
+
5
+ ## Community Projects & Inspirations
6
+
7
+ * **[`opencode-shell-strategy`](https://github.com/JRedeker/opencode-shell-strategy)** by [@JRedeker](https://github.com/JRedeker)
8
+ * Inspired the interactive TTY detection patterns in **Policy 22** (Non-Interactive Shell & TTY Hang Guard) to prevent subshell freezes on interactive prompts.
9
+
10
+ * **[`envsitter-guard`](https://github.com/boxpositron/envsitter-guard)** by [@boxpositron](https://github.com/boxpositron)
11
+ * Inspired the safe variable schema masking approach in **Policy 17** (Secret-File Read Block & Schema Masking) so agents can discover environment variable names without exposing live secret values.
12
+
13
+ * **[`opencode-snip`](https://github.com/VincentHardouin/opencode-snip)** by [@VincentHardouin](https://github.com/VincentHardouin)
14
+ * Inspired the token-efficient test output truncation and failure prioritization in **Policy 10** (Evidence-Based Verification).
15
+
16
+ * **[`opencode-worktree`](https://github.com/kdcokenny/opencode-worktree)** by [@kdcokenny](https://github.com/kdcokenny)
17
+ * Inspired the isolated-worktree development workflow behind the **`guard_worktree_create` / `guard_worktree_cleanup`** tools (snapshot-commit before removal, `node_modules` sharing, storage outside the repository), re-implemented here as native in-process tools with zero external dependencies.
18
+
19
+ * **[`changesets`](https://github.com/changesets/changesets)** by the [Changesets Team](https://github.com/changesets/changesets)
20
+ * For the fragment-based changelog and versioning model that prevents merge conflicts across parallel feature PRs.
21
+
22
+ * **[OpenCode Team at Anomaly](https://github.com/anomalyco/opencode)**
23
+ * For building the OpenCode terminal AI coding agent and its extensible plugin architecture (`@opencode-ai/plugin`).
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ultus-net
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # opencode-workflow-guard
2
+
3
+ OpenCode plugin enforcing workflow discipline, agent focus, and deterministic safety boundaries through **hard plugin hooks** — not prompt instructions that LLMs can ignore.
4
+
5
+ Integrates with OpenCode's native todo system (`todowrite`), prevents accidental destructive actions, gates protected branches, enforces testing evidence before task finalization, and stops secret leakage.
6
+
7
+ ---
8
+
9
+ ## Quick Start
10
+
11
+ ### 1. Installation
12
+
13
+ Add to your project's `opencode.json` or global `~/.config/opencode/opencode.json`:
14
+
15
+ ```json
16
+ {
17
+ "$schema": "https://opencode.ai/config.json",
18
+ "plugin": [
19
+ "opencode-workflow-guard"
20
+ ]
21
+ }
22
+ ```
23
+
24
+ *Requires OpenCode >= 1.18.* See [docs/installation.md](docs/installation.md) for local manual installation and TUI companion badge setup.
25
+
26
+ ### 2. Verification
27
+
28
+ ```bash
29
+ npm run typecheck # Strict TypeScript check (0 errors)
30
+ npm test # Run 320+ unit and adversarial tests
31
+ npm run test:all # Run full verification suite (typecheck + unit + live e2e)
32
+ ```
33
+
34
+ ---
35
+
36
+ ## Repository Structure
37
+
38
+ ```
39
+ opencode-workflow-guard/
40
+ ├── src/ # Production plugin sources
41
+ │ ├── workflow-guard.ts # Core server hooks & 23 deterministic policies
42
+ │ └── workflow-guard-ui.ts # TUI companion prompt badge
43
+ ├── test/ # Test suites
44
+ │ ├── test.mts # 320+ in-memory unit & adversarial tests
45
+ │ └── test-e2e.mts # Live runtime OpenCode loader tests
46
+ ├── docs/ # In-depth documentation & guides
47
+ │ ├── installation.md # Full setup options, worktrees & permissions
48
+ │ ├── policies.md # Detailed 23-policy reference & overrides
49
+ │ ├── troubleshooting.md # Error diagnosis & bypass explanations
50
+ │ └── testing.md # Test architecture & coverage matrix
51
+ ├── .changeset/ # Fragment-based versioning & release changelogs
52
+ ├── ACKNOWLEDGEMENTS.md # Open-source community credits & inspirations
53
+ ├── CONTRIBUTING.md # Development guide, test patterns & PR rules
54
+ ├── CHANGELOG.md # Version history
55
+ └── SECURITY.md # Vulnerability disclosure policy
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Summary of Enforced Policies
61
+
62
+ | # | Policy Group | Summary |
63
+ |---|---|---|
64
+ | **1** | **Task Gate & Lifecycle** | Gates file mutations on active `todowrite` tasks. Prevents silent task deletion; allows flexible completion order. |
65
+ | **2 & 7** | **Branch Protection** | Blocks direct edits & commits on `main`/`master`. Hard-blocks `git push ... main` and forced refspecs. |
66
+ | **3** | **PR Changelog & Changesets** | Requires PRs to include changesets (`.changeset/*.md`), `CHANGELOG.md` updates, or a `Changelog:` body section. |
67
+ | **4 & 9** | **Destructive CLI & Laundering** | Blocks destructive infrastructure, database, and system mutations unless overridden by user environment (`WORKFLOW_GUARD_ALLOW_LIVE=1`). Scans script payloads for smuggled commands. |
68
+ | **5** | **MCP Mutation Guard** | Blocks mutating GitHub & Azure DevOps MCP tools while allowing read-only inspection tools. |
69
+ | **6** | **Settings Tamper Guard** | Blocks agent modification of `opencode.json`, `.opencode/*`, or the guard's own plugin files. |
70
+ | **8** | **Workspace Boundary Guard** | Confines file mutations and shell redirects strictly within the project workspace root (symlink & `../` escape safe). |
71
+ | **10** | **Evidence-Based Verification** | Runs test verification before final task completion. Binds freshness to git state with token-efficient output snipping. |
72
+ | **11, 12, 17** | **Secret Protection & Masking** | Scans file payloads for API keys, scrubs sensitive env vars in agent subshells, and provides safe redacted `.env` variable schema masks (`KEY=********`). |
73
+ | **13 & 14** | **Audit Trail & Attribution** | Durable JSONL audit logging (`~/.local/state/opencode/workflow-guard/workflow-guard.jsonl`) with subagent hierarchy breadcrumbs. |
74
+ | **15 & 16** | **Compaction & TUI Feedback** | Preserves active task plans across context compactions; emits real-time TUI warning toasts and native desktop alerts. |
75
+ | **18** | **Interpreter Inline Evasion** | Scans inline scripts (`python -c`, `node -e`, `base64 | sh`) for smuggled live commands or config tampering. |
76
+ | **19 & 20** | **Pre-Flight Conflicts & Freshness** | Verifies clean `git merge-tree` mergeability and checks local base branch freshness before opening PRs. |
77
+ | **21** | **Documentation Synchronization** | Verifies documentation is updated when introducing new public features or policies. |
78
+ | **22** | **TTY Hang Guard** | Blocks interactive editors (`vim`, `nano`), pagers (`less`), and commands missing non-interactive flags (`npm init` without `-y`). |
79
+ | **23** | **Package Supply-Chain Hygiene** | Blocks destructive `npm audit fix --force`, global unversioned installs (`npm i -g`), and direct CLI `npm publish`. |
80
+
81
+ 👉 **For complete policy specifications and override rules, see [docs/policies.md](docs/policies.md).**
82
+
83
+ ---
84
+
85
+ ## Custom Tools Registered in OpenCode
86
+
87
+ * `guard_status`: Inspect active guardrails, current branch protection, and verification/review status.
88
+ * `guard_audit`: View recent audit log entries recorded in `workflow-guard.jsonl`.
89
+ * `guard_why`: Simulate and explain whether a specific tool call or command would be blocked.
90
+ * `record_review`: Record secondary reviewer subagent approval or critique across the 5 core review axes.
91
+ * `guard_worktree_create`: Create an isolated git worktree (with shared `node_modules` symlink) for concurrent subagent execution; rejects invalid and protected branch names.
92
+ * `guard_worktree_cleanup`: Snapshot-commit remaining changes and remove an isolated worktree directory.
93
+
94
+ ---
95
+
96
+ ## Documentation & Community
97
+
98
+ * [Installation Guide](docs/installation.md)
99
+ * [Policies & Overrides Reference](docs/policies.md)
100
+ * [Troubleshooting Guide](docs/troubleshooting.md)
101
+ * [Testing Guide](docs/testing.md)
102
+ * [Contributing Guide](CONTRIBUTING.md)
103
+ * [Acknowledgements & Ecosystem Credits](ACKNOWLEDGEMENTS.md)
104
+ * [Security Policy](SECURITY.md)
105
+
106
+ ---
107
+
108
+ ## License
109
+
110
+ [MIT](LICENSE)
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "opencode-workflow-guard",
3
+ "version": "1.1.0",
4
+ "description": "OpenCode plugin enforcing workflow discipline through deterministic tool.execute.before hooks",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "src/workflow-guard.ts",
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/ultus-net/opencode-workflow-guard.git"
14
+ },
15
+ "files": [
16
+ "src/",
17
+ "README.md",
18
+ "LICENSE",
19
+ "ACKNOWLEDGEMENTS.md"
20
+ ],
21
+ "keywords": [
22
+ "opencode",
23
+ "opencode-plugin",
24
+ "guard",
25
+ "workflow"
26
+ ],
27
+ "scripts": {
28
+ "test": "node test/test.mts",
29
+ "test:install": "node test/test-e2e.mts",
30
+ "test:all": "npm run typecheck && npm test && npm run test:install",
31
+ "typecheck": "tsc --noEmit -p tsconfig.json",
32
+ "build": "tsc --noEmit -p tsconfig.json",
33
+ "changeset": "changeset",
34
+ "version-packages": "changeset version",
35
+ "prepublishOnly": "npm run typecheck"
36
+ },
37
+ "dependencies": {
38
+ "@opencode-ai/plugin": "^1.18.21"
39
+ },
40
+ "devDependencies": {
41
+ "@changesets/cli": "^3.0.1",
42
+ "@opentui/solid": "^0.5.6",
43
+ "@types/node": "^26.2.0",
44
+ "typescript": "^7.0.2"
45
+ }
46
+ }
@@ -0,0 +1,48 @@
1
+ import type { TuiPlugin, TuiPluginModule } from "@opencode-ai/plugin/tui";
2
+ import type { JSX } from "@opentui/solid";
3
+ import { createElement, insert, setProp } from "@opentui/solid";
4
+
5
+ type Child = JSX.Element | string | number | null | undefined | false;
6
+
7
+ function element(
8
+ tag: string,
9
+ props: Record<string, unknown>,
10
+ children: Child[] = [],
11
+ ) {
12
+ const node = createElement(tag);
13
+ for (const [key, value] of Object.entries(props)) {
14
+ if (value !== undefined) setProp(node, key, value);
15
+ }
16
+ for (const child of children) {
17
+ if (child === null || child === undefined || child === false) continue;
18
+ insert(node, child);
19
+ }
20
+ return node as unknown as JSX.Element;
21
+ }
22
+
23
+ function text(props: Record<string, unknown>, children: Child[]) {
24
+ return element("text", props, children);
25
+ }
26
+
27
+ const BADGE = "🛡️ [Workflow Guard: Active]";
28
+
29
+ export const WorkflowGuardTui: TuiPlugin = async (api) => {
30
+ api.slots.register({
31
+ order: 1,
32
+ slots: {
33
+ home_prompt_right() {
34
+ const theme = api.theme.current;
35
+ return text({ fg: theme.success }, [BADGE]);
36
+ },
37
+ session_prompt_right() {
38
+ const theme = api.theme.current;
39
+ return text({ fg: theme.success }, [BADGE]);
40
+ },
41
+ },
42
+ });
43
+ };
44
+
45
+ export default {
46
+ id: "workflow-guard-ui",
47
+ tui: WorkflowGuardTui,
48
+ } satisfies TuiPluginModule;