@dezycro-ai/agent-plugin 2.0.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/.claude-plugin/plugin.json +7 -0
- package/LICENSE +18 -0
- package/PERSONAS.md +309 -0
- package/README.md +125 -0
- package/bin/resolve-auth.js +112 -0
- package/dist/hooks/lib/authoring.d.ts +118 -0
- package/dist/hooks/lib/authoring.js +277 -0
- package/dist/hooks/lib/config.d.ts +28 -0
- package/dist/hooks/lib/config.js +175 -0
- package/dist/hooks/lib/controller-match.d.ts +16 -0
- package/dist/hooks/lib/controller-match.js +96 -0
- package/dist/hooks/lib/coverage.d.ts +17 -0
- package/dist/hooks/lib/coverage.js +66 -0
- package/dist/hooks/lib/hashing.d.ts +8 -0
- package/dist/hooks/lib/hashing.js +49 -0
- package/dist/hooks/lib/logging.d.ts +13 -0
- package/dist/hooks/lib/logging.js +72 -0
- package/dist/hooks/lib/publish-spec.d.ts +17 -0
- package/dist/hooks/lib/publish-spec.js +64 -0
- package/dist/hooks/lib/quality-gate.d.ts +67 -0
- package/dist/hooks/lib/quality-gate.js +187 -0
- package/dist/hooks/lib/router.d.ts +32 -0
- package/dist/hooks/lib/router.js +717 -0
- package/dist/hooks/lib/state.d.ts +34 -0
- package/dist/hooks/lib/state.js +238 -0
- package/dist/hooks/lib/undo.d.ts +11 -0
- package/dist/hooks/lib/undo.js +71 -0
- package/dist/hooks/lib/verify.d.ts +28 -0
- package/dist/hooks/lib/verify.js +94 -0
- package/dist/hooks/lib/workbook.d.ts +21 -0
- package/dist/hooks/lib/workbook.js +77 -0
- package/dist/hooks/types.d.ts +249 -0
- package/dist/hooks/types.js +14 -0
- package/hooks/companion-runner +108 -0
- package/hooks/hooks.json +74 -0
- package/install.js +84 -0
- package/package.json +50 -0
- package/prompts/existing-work-ranker.md +47 -0
- package/prompts/prd-drafter.md +53 -0
- package/prompts/prd-question.md +66 -0
- package/prompts/trd-context-gate.md +57 -0
- package/prompts/trd-discovery.md +71 -0
- package/prompts/trd-drafter.md +63 -0
- package/prompts/trd-question.md +61 -0
- package/prompts/trd-reviewer.md +74 -0
- package/prompts/workbook-sweep.md +89 -0
- package/setup.js +35 -0
- package/skills/author/SKILL.md +285 -0
- package/skills/import-features/SKILL.md +428 -0
- package/skills/init/SKILL.md +133 -0
- package/skills/publish-spec/SKILL.md +101 -0
- package/skills/status/SKILL.md +76 -0
- package/skills/sync/SKILL.md +76 -0
- package/skills/verify/SKILL.md +248 -0
- package/skills/work/SKILL.md +201 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dezycro",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Dezycro AI plugin — reverse-engineer your codebase into features, PRDs, TRDs, and test cases. Companion V2 adds proactive verify gates, auto-publish-spec nudges, and a guided PRD/TRD authoring flow.",
|
|
5
|
+
"homepage": "https://dezycro.ai",
|
|
6
|
+
"license": "MIT"
|
|
7
|
+
}
|
package/LICENSE
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Copyright (c) 2026 Dezycro Inc. All rights reserved.
|
|
2
|
+
|
|
3
|
+
This software and its source code are proprietary and confidential to
|
|
4
|
+
Dezycro Inc. No part of this software may be reproduced, distributed,
|
|
5
|
+
modified, sublicensed, or used to create derivative works, in whole or
|
|
6
|
+
in part, without the prior written permission of Dezycro Inc.
|
|
7
|
+
|
|
8
|
+
The software is provided to authorized users solely for use with the
|
|
9
|
+
Dezycro platform under the terms of a separate agreement. Unauthorized
|
|
10
|
+
copying, distribution, reverse engineering, decompilation, or
|
|
11
|
+
disassembly is strictly prohibited.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
14
|
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
15
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.
|
|
16
|
+
IN NO EVENT SHALL DEZYCRO INC. BE LIABLE FOR ANY CLAIM, DAMAGES, OR
|
|
17
|
+
OTHER LIABILITY ARISING FROM, OUT OF, OR IN CONNECTION WITH THE
|
|
18
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/PERSONAS.md
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# Persona Auth Configuration
|
|
2
|
+
|
|
3
|
+
The Dezycro verifier runs generated tests against your API using **personas** — named users with different permission levels (e.g., `admin1`, `user1`, `readonly1`). Each persona needs credentials. This document describes how to configure them locally so `/dezycro:verify` can obtain tokens and run tests against a real, authenticated API.
|
|
4
|
+
|
|
5
|
+
## TL;DR
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# 1. Run /dezycro:init — it will detect your project's personas
|
|
9
|
+
# and prompt you to configure credentials for each.
|
|
10
|
+
#
|
|
11
|
+
# 2. Secrets live at ~/.dezycro/secrets/<name> (chmod 600),
|
|
12
|
+
# NOT inside the repo.
|
|
13
|
+
#
|
|
14
|
+
# 3. The repo-local .dezycro/auth.local.json is gitignored
|
|
15
|
+
# and references those secret files via !file: pointers.
|
|
16
|
+
#
|
|
17
|
+
# 4. /dezycro:verify reads auth.local.json, resolves secrets,
|
|
18
|
+
# exports the right env vars, then invokes the verifier binary.
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Why this exists
|
|
22
|
+
|
|
23
|
+
The verifier binary is a self-contained Go executable with an embedded `AUTH_CONFIG`. The config maps each persona name to an environment variable name, e.g.:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"authenticators": {
|
|
28
|
+
"admin1": { "type": "http_endpoint", "envVar": "AUTH_ADMIN1" },
|
|
29
|
+
"user1": { "type": "http_endpoint", "envVar": "AUTH_USER1" }
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
When the binary runs a test that needs authentication, it:
|
|
35
|
+
1. Looks up the persona (`admin1`).
|
|
36
|
+
2. Reads the env var the config points at (`AUTH_ADMIN1`).
|
|
37
|
+
3. Expects that env var to contain a **JSON configuration** telling it how to obtain a token.
|
|
38
|
+
4. For `http_endpoint` type, it calls the configured endpoint, extracts the token, caches it, and adds it to requests.
|
|
39
|
+
|
|
40
|
+
CI populates those env vars from whatever secret store your pipeline uses (GitHub Actions secrets, GitLab CI variables, etc.). Locally, there is no equivalent. This doc describes how `/dezycro:init` and `/dezycro:verify` close that gap without committing secrets to the repo.
|
|
41
|
+
|
|
42
|
+
## The three files
|
|
43
|
+
|
|
44
|
+
| File | Location | Purpose | Committed? |
|
|
45
|
+
|---|---|---|---|
|
|
46
|
+
| `.dezycro/config.json` | repo | Project-wide config (workspace/project IDs, environments) | ✅ yes |
|
|
47
|
+
| `.dezycro/auth.local.json` | repo | Per-persona auth config, with secrets as `!file:` or `${VAR}` references | ❌ gitignored |
|
|
48
|
+
| `~/.dezycro/secrets/<name>` | home | Raw secret values (passwords, client_secrets) | ❌ outside repo |
|
|
49
|
+
|
|
50
|
+
`/dezycro:init` creates and maintains the first two. You manage `~/.dezycro/secrets/` yourself (or replace with `pass`, `op`, a vault, etc — see [Secret backends](#secret-backends)).
|
|
51
|
+
|
|
52
|
+
## `auth.local.json` schema
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"version": 1,
|
|
57
|
+
"personas": {
|
|
58
|
+
"<persona-name>": {
|
|
59
|
+
"envVar": "<env-var-name>",
|
|
60
|
+
"config": { /* verifier auth config, shape depends on "type" */ }
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"secrets": {
|
|
64
|
+
"<token-name>": "<value or !file: or ${VAR}>"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Top-level keys
|
|
70
|
+
|
|
71
|
+
| Key | Type | Required | Description |
|
|
72
|
+
|---|---|---|---|
|
|
73
|
+
| `version` | integer | ✅ | Schema version. Current: `1`. Older verifiers accept lower versions; newer verifiers may ignore unknown fields. |
|
|
74
|
+
| `personas` | object | ✅ | Map of persona name → auth config. Persona names must match those defined on the personas of your Dezycro project. |
|
|
75
|
+
| `secrets` | object | optional | Named secret pool. Used for `${TOKEN_NAME}` placeholders inside `personas[].config`. |
|
|
76
|
+
|
|
77
|
+
### `personas[name]` entry
|
|
78
|
+
|
|
79
|
+
| Key | Type | Required | Description |
|
|
80
|
+
|---|---|---|---|
|
|
81
|
+
| `envVar` | string | ✅ | Name of the environment variable the verifier binary expects. Must match the `envVar` configured on that persona in Dezycro. Pattern: `AUTH_*`. |
|
|
82
|
+
| `config` | object | ✅ | Verifier auth config JSON. Shape depends on the persona's `type` (see per-type sections below). This object is serialized to JSON and assigned to the env var before the binary runs. |
|
|
83
|
+
| `type` | string | optional | Optional echo of the persona's type (`bearer`, `basic`, `header`, `http_endpoint`, `js`, `none`). Purely informational for humans reading this file — the verifier learns the type from its embedded `AUTH_CONFIG`, not from here. |
|
|
84
|
+
|
|
85
|
+
### `secrets[name]` entry
|
|
86
|
+
|
|
87
|
+
Values may be:
|
|
88
|
+
|
|
89
|
+
- **Inline literal**: any string that doesn't start with `!` or `${` is used verbatim. Avoid for real secrets.
|
|
90
|
+
- **File reference**: `!file:<path>` — read the secret from that file. `~` is expanded to `$HOME`. Environment variables are **not** expanded in the path.
|
|
91
|
+
- **Env-var reference**: `!env:<NAME>` — read from process environment. Useful for CI parity and 1Password CLI (`op run`) integration.
|
|
92
|
+
- **Command reference**: `!cmd:<command>` — execute command and use stdout (trimmed). For `pass`, `gopass`, `op read`, `security find-generic-password`, etc.
|
|
93
|
+
|
|
94
|
+
Placeholders in `personas[].config` are substituted **after** secrets are resolved. Placeholder syntax: `${SECRET_NAME}`. Substitution is recursive one level deep (a secret value is not itself substituted).
|
|
95
|
+
|
|
96
|
+
## Auth types and their `config` shapes
|
|
97
|
+
|
|
98
|
+
### `bearer`
|
|
99
|
+
Simple static bearer token.
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"envVar": "AUTH_SERVICE_ACCOUNT",
|
|
104
|
+
"config": { "token": "${SERVICE_ACCOUNT_TOKEN}" }
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Verifier sends: `Authorization: Bearer <token>`.
|
|
109
|
+
|
|
110
|
+
### `basic`
|
|
111
|
+
HTTP Basic auth.
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"envVar": "AUTH_CI_USER",
|
|
116
|
+
"config": { "username": "ci-bot", "password": "${CI_BOT_PASSWORD}" }
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Verifier sends: `Authorization: Basic <base64(username:password)>`.
|
|
121
|
+
|
|
122
|
+
### `header`
|
|
123
|
+
Arbitrary static headers. Use for API keys, signed tokens, or multi-header auth.
|
|
124
|
+
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"envVar": "AUTH_API_KEY",
|
|
128
|
+
"config": {
|
|
129
|
+
"headers": {
|
|
130
|
+
"X-API-Key": "${API_KEY}",
|
|
131
|
+
"X-Client-Id": "my-app"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Verifier merges `headers` into every request.
|
|
138
|
+
|
|
139
|
+
### `http_endpoint` (most common for dev)
|
|
140
|
+
Call an auth service to obtain a token. Used for OAuth2 password grant, OIDC token endpoints, custom dev login routes, etc.
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"envVar": "AUTH_ADMIN1",
|
|
145
|
+
"config": {
|
|
146
|
+
"url": "https://auth.example.com/oauth/v2/token",
|
|
147
|
+
"method": "POST",
|
|
148
|
+
"headers": { "Content-Type": "application/x-www-form-urlencoded" },
|
|
149
|
+
"body": "grant_type=password&client_id=${OAUTH_CLIENT_ID}&username=admin1@example.com&password=${ADMIN1_PASSWORD}",
|
|
150
|
+
"tokenPath": "access_token",
|
|
151
|
+
"headerName": "Authorization",
|
|
152
|
+
"headerPrefix": "Bearer "
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
| Field | Default | Description |
|
|
158
|
+
|---|---|---|
|
|
159
|
+
| `url` | — (required) | Token endpoint. |
|
|
160
|
+
| `method` | `"POST"` | HTTP method. |
|
|
161
|
+
| `headers` | `{}` | Request headers. Host override supported via `"Host": "..."` — useful when calling an internal service whose vhost differs from its DNS name. |
|
|
162
|
+
| `body` | `""` | Request body. URL-encoded form or JSON — whatever the endpoint expects. |
|
|
163
|
+
| `tokenPath` | `"access_token"` | JSON field name in the response body holding the token. |
|
|
164
|
+
| `headerName` | `"Authorization"` | Response header on test requests. |
|
|
165
|
+
| `headerPrefix` | `"Bearer "` | Prefix for the header value (mind the trailing space). |
|
|
166
|
+
|
|
167
|
+
The verifier caches the response per persona for the lifetime of the run, so the endpoint is called at most once per persona per run.
|
|
168
|
+
|
|
169
|
+
### `js`
|
|
170
|
+
Custom JavaScript for exotic auth (request signing, TOTP, MFA). The script receives a `process.env` object with filtered env vars (`AUTH_*`, `API_*`, `DEZYCRO_*`) plus any fields inside `config`, and must return `{ headers: { ... } }`.
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"envVar": "AUTH_HMAC",
|
|
175
|
+
"config": {
|
|
176
|
+
"accessKey": "${HMAC_ACCESS_KEY}",
|
|
177
|
+
"secret": "${HMAC_SECRET}"
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The `script` itself is compiled into the verifier binary (configured in Dezycro). Don't put it in `auth.local.json`.
|
|
183
|
+
|
|
184
|
+
### `none`
|
|
185
|
+
No auth headers. Explicit documentation that a persona deliberately goes unauthenticated (e.g., anonymous user testing public endpoints). No `config` needed:
|
|
186
|
+
|
|
187
|
+
```json
|
|
188
|
+
{ "envVar": "AUTH_ANON", "config": {} }
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Complete example
|
|
192
|
+
|
|
193
|
+
```json
|
|
194
|
+
{
|
|
195
|
+
"version": 1,
|
|
196
|
+
"personas": {
|
|
197
|
+
"admin1": {
|
|
198
|
+
"envVar": "AUTH_ADMIN1",
|
|
199
|
+
"type": "http_endpoint",
|
|
200
|
+
"config": {
|
|
201
|
+
"url": "https://auth.example.com/oauth/v2/token",
|
|
202
|
+
"method": "POST",
|
|
203
|
+
"headers": { "Content-Type": "application/x-www-form-urlencoded" },
|
|
204
|
+
"body": "grant_type=password&client_id=${OAUTH_CLIENT_ID}&username=admin1@example.com&password=${ADMIN1_PASSWORD}"
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
"user1": {
|
|
208
|
+
"envVar": "AUTH_USER1",
|
|
209
|
+
"type": "http_endpoint",
|
|
210
|
+
"config": {
|
|
211
|
+
"url": "https://auth.example.com/oauth/v2/token",
|
|
212
|
+
"method": "POST",
|
|
213
|
+
"headers": { "Content-Type": "application/x-www-form-urlencoded" },
|
|
214
|
+
"body": "grant_type=password&client_id=${OAUTH_CLIENT_ID}&username=user1@example.com&password=${USER1_PASSWORD}"
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
"readonly1": {
|
|
218
|
+
"envVar": "AUTH_READONLY1",
|
|
219
|
+
"type": "bearer",
|
|
220
|
+
"config": { "token": "${READONLY_PAT}" }
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
"secrets": {
|
|
224
|
+
"OAUTH_CLIENT_ID": "!file:~/.dezycro/secrets/oauth_client_id",
|
|
225
|
+
"ADMIN1_PASSWORD": "!file:~/.dezycro/secrets/admin1",
|
|
226
|
+
"USER1_PASSWORD": "!cmd:op read op://Private/MyApp/user1/password",
|
|
227
|
+
"READONLY_PAT": "!env:DEZYCRO_READONLY_PAT"
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## `/dezycro:init` behavior
|
|
233
|
+
|
|
234
|
+
`/dezycro:init` is re-runnable. Each run:
|
|
235
|
+
|
|
236
|
+
1. Writes/updates `.dezycro/config.json` (workspace + project binding).
|
|
237
|
+
2. Fetches personas for the active project via the Dezycro API.
|
|
238
|
+
3. For each persona that is **not already** in `auth.local.json`:
|
|
239
|
+
- Prints the persona name, type, and description.
|
|
240
|
+
- Prompts for the minimum needed — usually a secret name to reference and a path for its value.
|
|
241
|
+
- Writes the persona block to `auth.local.json`.
|
|
242
|
+
- Creates `~/.dezycro/secrets/<name>` with `chmod 600` if the user supplied a value; skips if they said they'll fill it in later.
|
|
243
|
+
4. Ensures the repo `.gitignore` excludes `.dezycro/auth.local.json`.
|
|
244
|
+
|
|
245
|
+
It never overwrites an existing persona entry. To reconfigure, delete the entry and re-run.
|
|
246
|
+
|
|
247
|
+
## `/dezycro:verify` behavior
|
|
248
|
+
|
|
249
|
+
Before invoking the verifier binary, `/dezycro:verify`:
|
|
250
|
+
|
|
251
|
+
1. Loads `.dezycro/auth.local.json` (optional — missing file is fine, but authenticated tests will fail).
|
|
252
|
+
2. Resolves every `secrets[*]` value (`!file:`, `!env:`, `!cmd:` — first error aborts).
|
|
253
|
+
3. Substitutes `${NAME}` placeholders inside each `personas[*].config`.
|
|
254
|
+
4. `json.Marshal`s the resolved config and `export`s it as the named env var.
|
|
255
|
+
5. Runs the binary. The binary picks up the env vars via its embedded `AUTH_CONFIG`.
|
|
256
|
+
6. Unsets the env vars after the run (they never land in shell history or parent process env).
|
|
257
|
+
|
|
258
|
+
If a persona's env var can't be resolved, the skill prints a warning naming that persona and continues — tests that don't need that persona still run. Tests that do need it fail with `authenticator '<name>' not configured`.
|
|
259
|
+
|
|
260
|
+
## Secret backends
|
|
261
|
+
|
|
262
|
+
Pick whatever you already use:
|
|
263
|
+
|
|
264
|
+
| Backend | Example secret value |
|
|
265
|
+
|---|---|
|
|
266
|
+
| Plain file | `!file:~/.dezycro/secrets/admin1` |
|
|
267
|
+
| Process env | `!env:ADMIN1_PASSWORD` |
|
|
268
|
+
| 1Password CLI | `!cmd:op read op://Private/MyApp/admin1/password` |
|
|
269
|
+
| `pass` | `!cmd:pass show myapp/admin1` |
|
|
270
|
+
| `gopass` | `!cmd:gopass show -o myapp/admin1` |
|
|
271
|
+
| macOS Keychain | `!cmd:security find-generic-password -a $USER -s myapp-admin1 -w` |
|
|
272
|
+
| GCP Secret Manager | `!cmd:gcloud secrets versions access latest --secret=myapp-admin1` |
|
|
273
|
+
|
|
274
|
+
For `!cmd:`, the shell is `/bin/sh -c`, output is stripped of trailing whitespace, and a non-zero exit or empty stdout is treated as an error.
|
|
275
|
+
|
|
276
|
+
## Gitignore
|
|
277
|
+
|
|
278
|
+
`/dezycro:init` adds the following lines to the repo's `.gitignore` (idempotent — appends only if missing):
|
|
279
|
+
|
|
280
|
+
```
|
|
281
|
+
# Dezycro — local-only, never commit
|
|
282
|
+
.dezycro/auth.local.json
|
|
283
|
+
.dezycro/bin/
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
`.dezycro/bin/` is where cached verifier binaries live — also gitignored because they are large and content-hash-addressed.
|
|
287
|
+
|
|
288
|
+
## Non-goals
|
|
289
|
+
|
|
290
|
+
Deliberately out of scope for this local-dev flow:
|
|
291
|
+
|
|
292
|
+
- **No token vault** — we don't build a secret store. Bring your own.
|
|
293
|
+
- **No per-environment personas** (yet) — a single `auth.local.json` covers whichever environment `/dezycro:verify --env <name>` is pointed at. When two environments need genuinely different credentials, we'll add `.dezycro/auth.local.<env>.json`. File an issue when you hit this.
|
|
294
|
+
- **No automatic credential rotation** — if a stored password expires, edit the secret file.
|
|
295
|
+
- **No CI usage** — CI continues to read secrets from your pipeline's native secret store and export them as env vars directly. `auth.local.json` is a developer-ergonomic layer; production still exports `AUTH_*` from the platform's native secret store.
|
|
296
|
+
|
|
297
|
+
## Troubleshooting
|
|
298
|
+
|
|
299
|
+
**`authenticator 'admin1' not configured (check AUTH_CONFIG_admin1 env var)`**
|
|
300
|
+
The binary couldn't find the env var named by its embedded `AUTH_CONFIG`. Check that `auth.local.json` has a `personas.admin1.envVar` matching what the binary expects (usually `AUTH_ADMIN1`), and that every `${…}` placeholder in its `config` resolved. Run `dezycro-verify doctor` to see what authenticators the binary knows about.
|
|
301
|
+
|
|
302
|
+
**`token endpoint returned status 401`**
|
|
303
|
+
The `http_endpoint` auth call itself failed. Double-check the request body (grant type, client id, credentials). Reproduce with `curl -d '<body>' '<url>'` using the resolved values.
|
|
304
|
+
|
|
305
|
+
**`token field 'access_token' not found or empty in response`**
|
|
306
|
+
`tokenPath` is wrong. Use `curl` to inspect the response shape and adjust.
|
|
307
|
+
|
|
308
|
+
**Secrets leak into logs**
|
|
309
|
+
They shouldn't — the skill logs only persona names and env-var names, never values. If you see a value, please file an issue.
|
package/README.md
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Dezycro for AI coding agents
|
|
2
|
+
|
|
3
|
+
> Turn any codebase into a documented, testable product — from your terminal.
|
|
4
|
+
|
|
5
|
+
`@dezycro-ai/agent-plugin` is the official [Dezycro](https://dezycro.ai) plugin for AI coding agents — starting with [Claude Code](https://claude.com/claude-code), with more agents on the way. It plugs your agent into the Dezycro platform so you can reverse-engineer an existing codebase into a tree of **features**, each with a user-facing **PRD**, a matching technical **TRD**, generated **test cases**, and live **verification** runs — all without leaving your editor.
|
|
6
|
+
|
|
7
|
+
You can drive everything by typing `/dezycro:*` slash commands, or just describe what you want in natural language and your agent will pick the right one.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## What you get
|
|
12
|
+
|
|
13
|
+
| Surface | What it does |
|
|
14
|
+
|---|---|
|
|
15
|
+
| **`/dezycro:import-features`** | Scans your repo and proposes a tree of user-facing features with PRDs and TRDs. |
|
|
16
|
+
| **`/dezycro:init`** | One-time per-repo setup. Binds the working directory to a workspace + project, writes `.dezycro/config.json`, and helps you wire up persona credentials. |
|
|
17
|
+
| **`/dezycro:work [feature]`** | Loads a feature's full context (PRD, TRD, workbook, journeys, open tasks/issues) and makes it the active feature for the session. |
|
|
18
|
+
| **`/dezycro:status`** | Compact summary of the active feature — journeys, tasks, issues, latest verification. |
|
|
19
|
+
| **`/dezycro:sync`** | Reviews work done since you started, records decisions, opens tasks/issues, links commits in the workbook. |
|
|
20
|
+
| **`/dezycro:publish-spec`** | Detects and uploads your OpenAPI spec for the active feature; triggers JEP (journey execution plan) generation. |
|
|
21
|
+
| **`/dezycro:verify [--env]`** | Pulls the latest verifier binary, runs generated tests against the configured environment, and uploads results to the workbook. |
|
|
22
|
+
| **Companion** | Background guardrails that block tasks from going to DONE without recent passing verifier evidence, nudge you to re-publish your OpenAPI spec when you touch a controller, and surface coverage gaps before you push. |
|
|
23
|
+
|
|
24
|
+
Together, the plugin lets a single developer keep a project's product documentation, technical documentation, test coverage, and verification status all in sync with the code — incrementally, as they work.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install -g @dezycro-ai/agent-plugin
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Full installation guide — prerequisites, MCP setup, troubleshooting, uninstalling — lives in the docs:
|
|
35
|
+
|
|
36
|
+
**→ [docs.dezycro.ai/claude-code/install](https://docs.dezycro.ai/claude-code/install/)**
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Quick start
|
|
41
|
+
|
|
42
|
+
The first run on a new repo is always the same three commands:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
cd path/to/your-repo
|
|
46
|
+
|
|
47
|
+
# In Claude Code:
|
|
48
|
+
/dezycro:init # bind this repo to a workspace + project
|
|
49
|
+
/dezycro:import-features # reverse-engineer the code into features + PRDs + TRDs
|
|
50
|
+
/dezycro:work <feature> # pick a feature and start working on it
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
After that, the inner loop while coding is:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
/dezycro:status # what's open, what's tracked
|
|
57
|
+
/dezycro:sync # push decisions/tasks/commits up to the workbook
|
|
58
|
+
/dezycro:verify # run the latest tests against your environment
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
You don't have to memorize the names — typing things like *"sync my work to Dezycro"* or *"verify this feature against staging"* will land on the right command.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Commands
|
|
66
|
+
|
|
67
|
+
### `/dezycro:init`
|
|
68
|
+
|
|
69
|
+
One-time per-repo setup. Connects this working directory to a Dezycro workspace and project, detects the dev environment from your code (base URL, OpenAPI spec path, auth flow), writes `.dezycro/config.json`, and walks you through configuring credentials for any personas the project defines (`admin1`, `user1`, etc).
|
|
70
|
+
|
|
71
|
+
Re-runnable — won't overwrite existing configuration, just fills gaps.
|
|
72
|
+
|
|
73
|
+
### `/dezycro:import-features`
|
|
74
|
+
|
|
75
|
+
Scans the codebase (frontend routes, backend controllers, jobs, integrations), groups what it finds into **user-facing features**, proposes a directory tree, asks for your approval, then creates the features and writes a PRD for each one based purely on user behavior — not on implementation details. After PRDs land, it can optionally trigger TRD and test-case generation for the same features.
|
|
76
|
+
|
|
77
|
+
The PRDs read like product specs, not code summaries. The TRDs link back to the PRDs and document the implementation.
|
|
78
|
+
|
|
79
|
+
### `/dezycro:work [feature-name-or-uuid]`
|
|
80
|
+
|
|
81
|
+
Loads everything the agent needs to safely work on a feature: PRD, TRD, approved journey graph, JEP, recent verifier runs, open issues and tasks. **Gates on PRD + TRD completion and approved graph** — refuses to start on a feature that isn't ready. Without an argument, it lists features and lets you pick interactively.
|
|
82
|
+
|
|
83
|
+
### `/dezycro:status`
|
|
84
|
+
|
|
85
|
+
Compact one-screen summary of the active feature: journeys (and which are confirmed), open and resolved issues, open tasks with assignees, latest verifier run, blockers. Useful as a "where am I" check after a context reset.
|
|
86
|
+
|
|
87
|
+
### `/dezycro:sync`
|
|
88
|
+
|
|
89
|
+
The "checkpoint" command. Reviews what happened in the session — files touched, decisions made, problems encountered — and writes that back to the workbook. Idempotent: re-running won't duplicate entries.
|
|
90
|
+
|
|
91
|
+
Run periodically while developing. PMs see the workbook update in near real time.
|
|
92
|
+
|
|
93
|
+
### `/dezycro:publish-spec`
|
|
94
|
+
|
|
95
|
+
Auto-detects your project's OpenAPI spec (Spring's `/v3/api-docs`, FastAPI's `/openapi.json`, a checked-in YAML, etc), optionally filters it to the active feature's endpoints, and uploads it. The upload triggers JEP generation in Dezycro — turning the spec into journey execution plans that drive test generation.
|
|
96
|
+
|
|
97
|
+
### `/dezycro:verify [--env <name>]`
|
|
98
|
+
|
|
99
|
+
Pulls the latest verifier binary for the active feature, resolves persona credentials, runs it against the chosen environment, and uploads the resulting step traces and assertion results to the workbook.
|
|
100
|
+
|
|
101
|
+
Pass `--env staging` to target a non-default environment.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Persona auth (for `/dezycro:verify`)
|
|
106
|
+
|
|
107
|
+
When `/dezycro:verify` calls authenticated endpoints, it needs credentials for the personas your project defines (`admin1`, `user1`, `readonly1`, …). Configuration lives in `.dezycro/auth.local.json` — **always gitignored** — and references real secrets via files, env vars, `op read`, `pass show`, etc.
|
|
108
|
+
|
|
109
|
+
See **[PERSONAS.md](./PERSONAS.md)** for the full schema, all supported auth types, every supported secret backend, and troubleshooting.
|
|
110
|
+
|
|
111
|
+
`/dezycro:init` walks you through setting this up the first time; you rarely need to hand-edit `auth.local.json`.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Support & troubleshooting
|
|
116
|
+
|
|
117
|
+
For installation issues, MCP setup, updates, and uninstall instructions, see the [installation guide](https://docs.dezycro.ai/claude-code/install/).
|
|
118
|
+
|
|
119
|
+
For everything else, sign in at [app.dezycro.ai](https://app.dezycro.ai) and use the in-app support channel.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
Proprietary. Copyright © 2026 Dezycro Inc. All rights reserved. See [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Resolve .dezycro/auth.local.json into a shell-safe env fragment suitable for
|
|
3
|
+
// `env $(dezycro-resolve-auth) <verifier-binary> ...`.
|
|
4
|
+
//
|
|
5
|
+
// Schema is documented in claude-plugin/PERSONAS.md:
|
|
6
|
+
// personas.<name>.envVar → env var name to set (e.g. AUTH_ADMIN1)
|
|
7
|
+
// personas.<name>.config → JSON payload (the value of the env var)
|
|
8
|
+
// secrets.<NAME> → secret pool used by ${NAME} substitution
|
|
9
|
+
// values may be:
|
|
10
|
+
// inline literal
|
|
11
|
+
// "!file:<path>" — read file contents (~ expanded)
|
|
12
|
+
// "!env:<NAME>" — read from process env
|
|
13
|
+
// "!cmd:<command>" — run via /bin/sh -c, use trimmed stdout
|
|
14
|
+
//
|
|
15
|
+
// Missing file → exit 0 with empty output (not an error: CI/dev may export
|
|
16
|
+
// the AUTH_* vars directly). Per-persona failures emit a stderr warning and
|
|
17
|
+
// skip that persona so unrelated tests can still run.
|
|
18
|
+
//
|
|
19
|
+
// Usage:
|
|
20
|
+
// dezycro-resolve-auth [<path>] # defaults to .dezycro/auth.local.json
|
|
21
|
+
// eval "$(dezycro-resolve-auth)"; ./verifier run ...
|
|
22
|
+
//
|
|
23
|
+
// Output is newline-separated `export KEY='value'` statements, where single
|
|
24
|
+
// quotes inside the value are POSIX-escaped. MUST be consumed via `eval`
|
|
25
|
+
// (or `source /dev/stdin <<< "$(...)"`), NOT via `env $(…)` — the latter
|
|
26
|
+
// skips shell quote-stripping and hands the binary a value that still starts
|
|
27
|
+
// with a literal `'`, producing `invalid character '\'' looking for …` parse
|
|
28
|
+
// errors from the Go JSON decoder.
|
|
29
|
+
|
|
30
|
+
const fs = require("fs");
|
|
31
|
+
const os = require("os");
|
|
32
|
+
const { execSync } = require("child_process");
|
|
33
|
+
|
|
34
|
+
function shQuote(s) {
|
|
35
|
+
return "'" + String(s).replace(/'/g, "'\\''") + "'";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function resolveSecret(raw) {
|
|
39
|
+
if (typeof raw !== "string") return raw;
|
|
40
|
+
if (raw.startsWith("!file:")) {
|
|
41
|
+
const p = raw.slice(6).replace(/^~(?=\/|$)/, os.homedir());
|
|
42
|
+
return fs.readFileSync(p, "utf8").replace(/\s+$/, "");
|
|
43
|
+
}
|
|
44
|
+
if (raw.startsWith("!env:")) {
|
|
45
|
+
const name = raw.slice(5);
|
|
46
|
+
if (!(name in process.env)) throw new Error(`env var not set: ${name}`);
|
|
47
|
+
return process.env[name];
|
|
48
|
+
}
|
|
49
|
+
if (raw.startsWith("!cmd:")) {
|
|
50
|
+
const cmd = raw.slice(5);
|
|
51
|
+
const out = execSync(cmd, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
52
|
+
const trimmed = out.replace(/\s+$/, "");
|
|
53
|
+
if (!trimmed) throw new Error(`empty stdout from: ${cmd}`);
|
|
54
|
+
return trimmed;
|
|
55
|
+
}
|
|
56
|
+
return raw;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function substitute(obj, secrets) {
|
|
60
|
+
if (typeof obj === "string") {
|
|
61
|
+
return obj.replace(/\$\{([A-Z0-9_]+)\}/g, (_, name) => {
|
|
62
|
+
if (!(name in secrets)) throw new Error(`\${${name}} not in secrets`);
|
|
63
|
+
return secrets[name];
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
if (Array.isArray(obj)) return obj.map((x) => substitute(x, secrets));
|
|
67
|
+
if (obj && typeof obj === "object") {
|
|
68
|
+
const out = {};
|
|
69
|
+
for (const [k, v] of Object.entries(obj)) out[k] = substitute(v, secrets);
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
return obj;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function main() {
|
|
76
|
+
const authPath = process.argv[2] || ".dezycro/auth.local.json";
|
|
77
|
+
if (!fs.existsSync(authPath)) {
|
|
78
|
+
process.stderr.write(`[dezycro-resolve-auth] no auth file at ${authPath}; emitting nothing\n`);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
let doc;
|
|
82
|
+
try {
|
|
83
|
+
doc = JSON.parse(fs.readFileSync(authPath, "utf8"));
|
|
84
|
+
} catch (e) {
|
|
85
|
+
process.stderr.write(`[dezycro-resolve-auth] parse error in ${authPath}: ${e.message}\n`);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const secrets = {};
|
|
90
|
+
for (const [k, v] of Object.entries(doc.secrets || {})) {
|
|
91
|
+
try {
|
|
92
|
+
secrets[k] = resolveSecret(v);
|
|
93
|
+
} catch (e) {
|
|
94
|
+
process.stderr.write(`[dezycro-resolve-auth] warning: secret ${k}: ${e.message}\n`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const lines = [];
|
|
99
|
+
for (const [name, p] of Object.entries(doc.personas || {})) {
|
|
100
|
+
if (!p || !p.envVar) continue;
|
|
101
|
+
try {
|
|
102
|
+
const cfg = substitute(p.config || {}, secrets);
|
|
103
|
+
lines.push(`export ${p.envVar}=${shQuote(JSON.stringify(cfg))}`);
|
|
104
|
+
} catch (e) {
|
|
105
|
+
process.stderr.write(`[dezycro-resolve-auth] warning: persona '${name}' skipped: ${e.message}\n`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (lines.length) process.stdout.write(lines.join("\n") + "\n");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
main();
|