nono-skills 0.1.0 → 0.2.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/README.md +32 -14
- package/package.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/references/workspaces.md +61 -0
- package/plugin/skills/api-design/SKILL.md +5 -1
- package/plugin/skills/architecture-review/SKILL.md +5 -1
- package/plugin/skills/brainstorm/SKILL.md +5 -1
- package/plugin/skills/database-design/SKILL.md +5 -1
- package/plugin/skills/debug/SKILL.md +5 -1
- package/plugin/skills/estimate/SKILL.md +5 -1
- package/plugin/skills/fix-findings/SKILL.md +5 -1
- package/plugin/skills/implement/SKILL.md +5 -1
- package/plugin/skills/migration/SKILL.md +5 -1
- package/plugin/skills/plan/SKILL.md +7 -3
- package/plugin/skills/refactor/SKILL.md +5 -1
- package/plugin/skills/release-readiness/SKILL.md +6 -1
- package/plugin/skills/review/SKILL.md +6 -2
- package/plugin/skills/security-review/SKILL.md +6 -2
- package/plugin/skills/test/SKILL.md +5 -1
- package/scripts/validate.mjs +17 -2
- package/src/cli.js +7 -2
- package/src/plugin-contract.js +89 -0
- package/src/skill-contract.js +249 -0
- package/src/uninstall.js +154 -8
- package/templates/AGENTS.md +3 -11
- package/templates/docs/agent/decision-log.md +0 -15
- package/templates/docs/agent/findings.md +0 -13
- package/templates/docs/agent/handoff.md +0 -20
- package/templates/docs/agent/plan.md +0 -14
- package/templates/docs/agent/spec.md +0 -20
package/README.md
CHANGED
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
A lightweight, reasoning-first engineering workflow pack for Codex. It provides 15 namespaced skills built around outcomes, evidence, verification, material decisions, and human escalation.
|
|
4
4
|
|
|
5
|
-
The pack is designed for capable reasoning models such as GPT-5.6 Sol. Skills define intent and guardrails while leaving implementation strategy to the model. They do not impose mandatory approval gates, worktrees, test-first development, or subagent orchestration.
|
|
5
|
+
The pack is designed for capable reasoning models such as GPT-5.6 Sol. Skills define intent and guardrails while leaving implementation strategy to the model. They do not impose mandatory design or implementation approval gates, worktrees, test-first development, or subagent orchestration. The only built-in gate is consent before Codex creates a durable workspace that the user did not explicitly request.
|
|
6
6
|
|
|
7
7
|
## How it works
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
9
|
+
- Install once, start a new Codex task, and ask for engineering work naturally. Explicit `$engineering:<skill>` invocation remains optional.
|
|
10
|
+
- Small tasks stay artifact-free.
|
|
11
|
+
- For work worth resuming or tracking, Codex proposes an isolated `docs/agent/work/<work-id>/` workspace and asks once before creating it.
|
|
12
|
+
- An explicit request for a spec, plan, log, findings tracker, handoff, or named existing work item already grants artifact consent for that scope.
|
|
13
|
+
- After approval, Codex maintains that work item's spec, plan, material decisions, findings, and handoff as needed without asking for every file update.
|
|
14
|
+
- Codex asks again only for an ambiguous work-item match, material scope expansion, or an action that needs new authority.
|
|
14
15
|
|
|
15
16
|
## Install
|
|
16
17
|
|
|
@@ -20,7 +21,23 @@ Requires Node.js 20 or newer and Codex CLI with plugin support.
|
|
|
20
21
|
npx nono-skills install
|
|
21
22
|
```
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
Then work normally:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
Implement user authentication and keep me updated.
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
For a durable task, Codex may propose:
|
|
31
|
+
|
|
32
|
+
```text
|
|
33
|
+
This work has multiple stages and should remain resumable. I propose
|
|
34
|
+
docs/agent/work/2026-07-16-user-auth/ for its spec, plan, and material
|
|
35
|
+
decisions. Approve this workspace?
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Declining keeps the work in the current conversation and creates no workflow files.
|
|
39
|
+
|
|
40
|
+
Skills appear under the `engineering` namespace when you want to invoke one explicitly:
|
|
24
41
|
|
|
25
42
|
```text
|
|
26
43
|
$engineering:plan
|
|
@@ -60,14 +77,16 @@ $engineering:database-design
|
|
|
60
77
|
| Design a stable consumer contract | `$engineering:api-design` |
|
|
61
78
|
| Design persistent data around invariants | `$engineering:database-design` |
|
|
62
79
|
|
|
63
|
-
##
|
|
80
|
+
## Optional repository guidance
|
|
64
81
|
|
|
65
|
-
|
|
82
|
+
`init` is optional. The plugin works without it. Run this only when the repository needs a starter `AGENTS.md` for its setup commands, architecture rules, verification commands, and local conventions:
|
|
66
83
|
|
|
67
84
|
```bash
|
|
68
85
|
npx nono-skills init
|
|
69
86
|
```
|
|
70
87
|
|
|
88
|
+
Initialization no longer creates task artifacts. Existing 0.1.0 singleton files under `docs/agent/` are preserved and new durable work uses per-work-item directories.
|
|
89
|
+
|
|
71
90
|
Preview changes or target another repository:
|
|
72
91
|
|
|
73
92
|
```bash
|
|
@@ -81,8 +100,6 @@ Existing differing files are reported as conflicts and no files are written. To
|
|
|
81
100
|
npx nono-skills init --force
|
|
82
101
|
```
|
|
83
102
|
|
|
84
|
-
Project artifacts include a repository-focused `AGENTS.md` and `docs/agent/` templates for specs, plans, decisions, findings, and handoffs. Without initialization, skills return the same material information in their final response instead of creating workflow files.
|
|
85
|
-
|
|
86
103
|
## Maintain the installation
|
|
87
104
|
|
|
88
105
|
```bash
|
|
@@ -93,13 +110,13 @@ npx nono-skills uninstall
|
|
|
93
110
|
|
|
94
111
|
Start a new Codex task after install or update so the refreshed skill definitions are loaded.
|
|
95
112
|
|
|
96
|
-
Uninstall preserves project files. Remove only project files that still match their installed checksums with:
|
|
113
|
+
Uninstall preserves project files. Remove only installer-owned project files that still match their installed checksums with:
|
|
97
114
|
|
|
98
115
|
```bash
|
|
99
116
|
npx nono-skills uninstall --purge-project /path/to/project
|
|
100
117
|
```
|
|
101
118
|
|
|
102
|
-
Modified project files are always preserved.
|
|
119
|
+
Modified project files are always preserved. Purge never removes user-owned `docs/agent/work/<work-id>/` directories.
|
|
103
120
|
|
|
104
121
|
## Moving away from Superpowers
|
|
105
122
|
|
|
@@ -113,7 +130,8 @@ This pack intentionally does not reproduce strict test-first enforcement, automa
|
|
|
113
130
|
- Marketplace edits preserve unrelated entries and metadata.
|
|
114
131
|
- Install and update roll back plugin source and marketplace changes when Codex registration fails.
|
|
115
132
|
- Project files are never overwritten without `--force` and a backup.
|
|
116
|
-
-
|
|
133
|
+
- Codex-proposed durable workspaces require one explicit approval before creation; explicit artifact requests already provide consent for their scope.
|
|
134
|
+
- Work-item directories are user-owned, and uninstall purge never removes them.
|
|
117
135
|
- The CLI never disables or removes Superpowers automatically.
|
|
118
136
|
|
|
119
137
|
## Development
|
package/package.json
CHANGED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Adaptive Workspaces
|
|
2
|
+
|
|
3
|
+
Use this protocol before deciding whether to create, select, or update workflow artifacts. The active skill still owns its task-specific behavior.
|
|
4
|
+
|
|
5
|
+
## 1. Classify persistence
|
|
6
|
+
|
|
7
|
+
Classify the task as transient or durable using judgment, not fixed size thresholds.
|
|
8
|
+
|
|
9
|
+
Durable state is justified when the user asks for it, work is likely to cross Codex tasks or owners, multiple outcomes need tracking, migration/security/release/compatibility risk is material, findings need a fix lifecycle, or decisions must survive the conversation. Keep localized one-shot work transient unless the user asks otherwise.
|
|
10
|
+
|
|
11
|
+
## 2. Establish consent
|
|
12
|
+
|
|
13
|
+
Explicit requests for a spec, plan, progress log, decision log, findings tracker, handoff, or named existing work item already grant artifact consent for that scope.
|
|
14
|
+
|
|
15
|
+
When Codex decides a new durable workspace would help, state why, the proposed path, scope, and initial files, then ask once before creating the workspace. Approval covers artifact maintenance inside that work-item scope; it does not authorize unrelated implementation, commits, pushes, deployments, production changes, destructive actions, external writes, or spend.
|
|
16
|
+
|
|
17
|
+
If the user declines, create no equivalent files elsewhere. Continue safely in chat and report material decisions and residual risk in the final response.
|
|
18
|
+
|
|
19
|
+
## 3. Resolve or create the work item
|
|
20
|
+
|
|
21
|
+
Resolve in this order:
|
|
22
|
+
|
|
23
|
+
1. the work item already approved in the current Codex task
|
|
24
|
+
2. an explicit work ID, path, issue, or ticket from the user
|
|
25
|
+
3. an exact issue or ticket metadata match
|
|
26
|
+
4. an exact current non-default branch match to one active item
|
|
27
|
+
5. one active item whose goal and scope clearly match
|
|
28
|
+
|
|
29
|
+
Recency alone is never sufficient. Ask the user when multiple items remain plausible.
|
|
30
|
+
|
|
31
|
+
For new work, prefer `issue-<number>-<slug>` when an issue exists; otherwise use `YYYY-MM-DD-<goal-slug>`. Add a numeric suffix on collision and never overwrite unrelated contents.
|
|
32
|
+
|
|
33
|
+
## 4. Maintain the workspace
|
|
34
|
+
|
|
35
|
+
The anchor is `docs/agent/work/<work-id>/spec.md` with YAML front matter containing `work_id`, `title`, `status`, optional `issue`, optional `branch`, `created`, and `updated`. Status is `active`, `blocked`, `completed`, or `superseded`.
|
|
36
|
+
|
|
37
|
+
Start every new approved work item with `status: active`; set both `created` and `updated` when creating its anchor. Refresh `updated` on every authoritative work-item artifact or status mutation. Keep the current status truthful so work-item resolution never relies on stale `active` metadata.
|
|
38
|
+
|
|
39
|
+
Use `blocked` only when in-scope progress cannot continue because of a concrete unresolved dependency, missing input or authority, or required external change. Record the blocker and resumption condition in `plan.md` or `handoff.md` as applicable; return the status to `active` and refresh `updated` when the blocker is resolved.
|
|
40
|
+
|
|
41
|
+
Use `completed` only when all in-scope acceptance criteria and tracked plan items are satisfied, required verification evidence is recorded, and no unresolved blocking findings or work remain. Set the status to `completed` and refresh `updated`; do not move or delete the work-item directory.
|
|
42
|
+
|
|
43
|
+
Use `superseded` only when the work is intentionally replaced. Record the reason and successor or reference as a material decision, set the status to `superseded`, and refresh `updated`; do not move or delete the work-item directory.
|
|
44
|
+
|
|
45
|
+
Reopening completed work changes its status to `active`, refreshes `updated`, and records the material reason.
|
|
46
|
+
|
|
47
|
+
Create files lazily:
|
|
48
|
+
|
|
49
|
+
- `spec.md` for every approved durable work item
|
|
50
|
+
- `plan.md` when outcomes, dependencies, or verification targets need tracking
|
|
51
|
+
- `decisions.md` on the first material decision
|
|
52
|
+
- `findings.md` when findings need lifecycle tracking
|
|
53
|
+
- `handoff.md` only when work remains or ownership changes
|
|
54
|
+
|
|
55
|
+
Do not create a global mutable index or move completed work-item directories. Log only contractual choices, meaningful ambiguity resolutions, accepted risks or tradeoffs, material re-plans, and assumptions future work must preserve.
|
|
56
|
+
|
|
57
|
+
## 5. Respect scope and failures
|
|
58
|
+
|
|
59
|
+
The original request controls implementation authority: an implementation request permits ordinary in-repository edits, while a planning request stops after planning. Ask again for material scope expansion, breaking or destructive behavior, production or external-system mutation, or significant spend.
|
|
60
|
+
|
|
61
|
+
Repository instructions override the default artifact location. If creation fails, report exactly what exists and continue in chat when safe. Never silently create artifacts at another path. Treat existing 0.1.0 singleton files as legacy user content: read them only when explicitly named or unambiguously relevant, and never move, merge, or delete them automatically.
|
|
@@ -9,6 +9,10 @@ description: Use when creating or changing an HTTP, RPC, event, webhook, library
|
|
|
9
9
|
|
|
10
10
|
Define a consumer-centered contract with precise semantics, failure behavior, authorization, compatibility, and operability before or alongside implementation.
|
|
11
11
|
|
|
12
|
+
## Workspace protocol
|
|
13
|
+
|
|
14
|
+
Read `../../references/workspaces.md` before selecting or creating workflow artifacts. Follow it for persistence, consent, work-item resolution, and lifecycle; this skill owns only the task-specific behavior below.
|
|
15
|
+
|
|
12
16
|
## Inputs
|
|
13
17
|
|
|
14
18
|
- Consumer use cases, domain language, invariants, and quality constraints
|
|
@@ -33,7 +37,7 @@ Define a consumer-centered contract with precise semantics, failure behavior, au
|
|
|
33
37
|
## Decision-log updates
|
|
34
38
|
|
|
35
39
|
Record public contract choices, compatibility policy, naming or semantic decisions likely to recur, idempotency and consistency guarantees, and rejected alternatives with consumer impact.
|
|
36
|
-
|
|
40
|
+
When durable state is approved, append contract choices and compatibility consequences to the selected work item's decisions.md; otherwise include them in the final response.
|
|
37
41
|
|
|
38
42
|
## Escalate to the human
|
|
39
43
|
|
|
@@ -9,6 +9,10 @@ description: Use when architecture is the primary review objective for boundarie
|
|
|
9
9
|
|
|
10
10
|
Evaluate whether system structure supports the stated product and operational needs, using repository evidence rather than generic pattern scoring.
|
|
11
11
|
|
|
12
|
+
## Workspace protocol
|
|
13
|
+
|
|
14
|
+
Read `../../references/workspaces.md` before selecting or creating workflow artifacts. Follow it for persistence, consent, work-item resolution, and lifecycle; this skill owns only the task-specific behavior below.
|
|
15
|
+
|
|
12
16
|
## Inputs
|
|
13
17
|
|
|
14
18
|
- Goals, constraints, quality attributes, diagrams or proposals
|
|
@@ -33,7 +37,7 @@ Evaluate whether system structure supports the stated product and operational ne
|
|
|
33
37
|
## Decision-log updates
|
|
34
38
|
|
|
35
39
|
Record accepted boundaries, ownership, technology choices, quality-attribute priorities, and deliberately accepted coupling or debt. Capture alternatives and migration consequences.
|
|
36
|
-
|
|
40
|
+
When durable state is approved, append structural tradeoffs or accepted architecture risk to the selected work item's decisions.md and track actionable defects in findings.md; otherwise report them in the final response.
|
|
37
41
|
|
|
38
42
|
## Escalate to the human
|
|
39
43
|
|
|
@@ -9,6 +9,10 @@ description: Use when a product, feature, technical approach, workflow, or probl
|
|
|
9
9
|
|
|
10
10
|
Turn an unclear opportunity into a small set of distinct, evidence-aware options and a recommended direction without prematurely implementing one.
|
|
11
11
|
|
|
12
|
+
## Workspace protocol
|
|
13
|
+
|
|
14
|
+
Read `../../references/workspaces.md` before selecting or creating workflow artifacts. Follow it for persistence, consent, work-item resolution, and lifecycle; this skill owns only the task-specific behavior below.
|
|
15
|
+
|
|
12
16
|
## Inputs
|
|
13
17
|
|
|
14
18
|
- Desired outcome, users, constraints, known pain, and prior attempts
|
|
@@ -34,7 +38,7 @@ Turn an unclear opportunity into a small set of distinct, evidence-aware options
|
|
|
34
38
|
## Decision-log updates
|
|
35
39
|
|
|
36
40
|
Record the selected direction, rejected alternatives when the tradeoff may recur, key assumptions to validate, and the next experiment. Keep unselected raw ideas out of the durable log unless they explain a decision.
|
|
37
|
-
|
|
41
|
+
When durable state is approved, append the accepted direction, recurring tradeoffs, assumptions, and next experiment to the selected work item's decisions.md; otherwise include them in the final response.
|
|
38
42
|
|
|
39
43
|
## Escalate to the human
|
|
40
44
|
|
|
@@ -9,6 +9,10 @@ description: Use when designing or changing persistent data models, schemas, con
|
|
|
9
9
|
|
|
10
10
|
Create a data model that enforces domain invariants, serves proven access patterns, evolves safely, and has explicit consistency and lifecycle semantics.
|
|
11
11
|
|
|
12
|
+
## Workspace protocol
|
|
13
|
+
|
|
14
|
+
Read `../../references/workspaces.md` before selecting or creating workflow artifacts. Follow it for persistence, consent, work-item resolution, and lifecycle; this skill owns only the task-specific behavior below.
|
|
15
|
+
|
|
12
16
|
## Inputs
|
|
13
17
|
|
|
14
18
|
- Domain concepts, invariants, lifecycle, ownership, and access patterns
|
|
@@ -33,7 +37,7 @@ Create a data model that enforces domain invariants, serves proven access patter
|
|
|
33
37
|
## Decision-log updates
|
|
34
38
|
|
|
35
39
|
Record data ownership, normalization tradeoffs, identifiers, consistency model, transaction boundaries, retention, tenant isolation, and irreversible schema choices. Link migration and rollback implications.
|
|
36
|
-
|
|
40
|
+
When durable state is approved, append invariant, consistency, migration, and operational choices to the selected work item's decisions.md; otherwise include them in the final response.
|
|
37
41
|
|
|
38
42
|
## Escalate to the human
|
|
39
43
|
|
|
@@ -9,6 +9,10 @@ description: Use when behavior is wrong, failing, flaky, slow, inconsistent, or
|
|
|
9
9
|
|
|
10
10
|
Reproduce the symptom, trace the failing path, falsify competing hypotheses, isolate root cause, and verify the requested resolution.
|
|
11
11
|
|
|
12
|
+
## Workspace protocol
|
|
13
|
+
|
|
14
|
+
Read `../../references/workspaces.md` before selecting or creating workflow artifacts. Follow it for persistence, consent, work-item resolution, and lifecycle; this skill owns only the task-specific behavior below.
|
|
15
|
+
|
|
12
16
|
## Inputs
|
|
13
17
|
|
|
14
18
|
- Exact symptom, error, payload, timing, environment, and expected behavior
|
|
@@ -33,7 +37,7 @@ Reproduce the symptom, trace the failing path, falsify competing hypotheses, iso
|
|
|
33
37
|
## Decision-log updates
|
|
34
38
|
|
|
35
39
|
Record confirmed root cause, discarded high-likelihood hypotheses, material diagnostic pivots, chosen remediation tradeoffs, and remaining uncertainty. Avoid logging every command.
|
|
36
|
-
|
|
40
|
+
When durable state is approved, append the validated root cause, rejected material hypotheses, and consequential fix choices to the selected work item's decisions.md and create handoff.md only when work remains; for a selected approved durable work item with an existing plan.md, update only relevant plan-item status and verification evidence for the performed debugging scope, never invent unrelated work, and do not mark the work completed unless the workspace lifecycle criteria are satisfied; otherwise include material decisions and performed-scope verification in the final response.
|
|
37
41
|
|
|
38
42
|
## Escalate to the human
|
|
39
43
|
|
|
@@ -9,6 +9,10 @@ description: Use when software work needs an evidence-based range for effort, du
|
|
|
9
9
|
|
|
10
10
|
Provide a transparent range derived from scope, dependencies, uncertainty, and comparable work rather than a false-precision point value.
|
|
11
11
|
|
|
12
|
+
## Workspace protocol
|
|
13
|
+
|
|
14
|
+
Read `../../references/workspaces.md` before selecting or creating workflow artifacts. Follow it for persistence, consent, work-item resolution, and lifecycle; this skill owns only the task-specific behavior below.
|
|
15
|
+
|
|
12
16
|
## Inputs
|
|
13
17
|
|
|
14
18
|
- Goal, acceptance criteria, proposed plan, and definition of done
|
|
@@ -33,7 +37,7 @@ Provide a transparent range derived from scope, dependencies, uncertainty, and c
|
|
|
33
37
|
## Decision-log updates
|
|
34
38
|
|
|
35
39
|
Record the committed estimation basis, major assumptions, exclusions, selected scenario, and later changes that materially move the range. Do not log exploratory arithmetic.
|
|
36
|
-
|
|
40
|
+
When durable state is approved, append scope interpretations, estimation model changes, and accepted schedule tradeoffs to the selected work item's decisions.md; otherwise include them in the final response.
|
|
37
41
|
|
|
38
42
|
## Escalate to the human
|
|
39
43
|
|
|
@@ -9,6 +9,10 @@ description: Use when validated review, audit, QA, or security findings must be
|
|
|
9
9
|
|
|
10
10
|
Resolve accepted findings at their root cause, preserve intended behavior, and produce evidence that each fix closes the reported failure.
|
|
11
11
|
|
|
12
|
+
## Workspace protocol
|
|
13
|
+
|
|
14
|
+
Read `../../references/workspaces.md` before selecting or creating workflow artifacts. Follow it for persistence, consent, work-item resolution, and lifecycle; this skill owns only the task-specific behavior below.
|
|
15
|
+
|
|
12
16
|
## Inputs
|
|
13
17
|
|
|
14
18
|
- Findings with evidence, severity, and expected outcome
|
|
@@ -33,7 +37,7 @@ Resolve accepted findings at their root cause, preserve intended behavior, and p
|
|
|
33
37
|
## Decision-log updates
|
|
34
38
|
|
|
35
39
|
Record chosen remediations when alternatives have meaningful compatibility, security, performance, or operational tradeoffs. Link the decision to finding IDs and record any accepted residual risk.
|
|
36
|
-
|
|
40
|
+
When durable state is approved, update the selected work item's findings.md with status and verification evidence, and append material remediation tradeoffs to decisions.md; otherwise report state changes and decisions in the final response.
|
|
37
41
|
|
|
38
42
|
## Escalate to the human
|
|
39
43
|
|
|
@@ -9,6 +9,10 @@ description: Use for general software implementation from a requirement, spec, i
|
|
|
9
9
|
|
|
10
10
|
Deliver the smallest complete change that satisfies the contract, preserves unrelated behavior, and is verified in proportion to risk.
|
|
11
11
|
|
|
12
|
+
## Workspace protocol
|
|
13
|
+
|
|
14
|
+
Read `../../references/workspaces.md` before selecting or creating workflow artifacts. Follow it for persistence, consent, work-item resolution, and lifecycle; this skill owns only the task-specific behavior below.
|
|
15
|
+
|
|
12
16
|
## Inputs
|
|
13
17
|
|
|
14
18
|
- User request and acceptance criteria
|
|
@@ -33,7 +37,7 @@ Deliver the smallest complete change that satisfies the contract, preserves unre
|
|
|
33
37
|
## Decision-log updates
|
|
34
38
|
|
|
35
39
|
Record material implementation choices, deviations from the plan, assumptions that affect behavior, accepted tradeoffs, and why a simpler or established pattern was not used. Include verification or follow-up consequences.
|
|
36
|
-
|
|
40
|
+
When durable state is approved, append the decision to the selected work item's `decisions.md` and update its plan or handoff when applicable; otherwise include it in the final response.
|
|
37
41
|
|
|
38
42
|
## Escalate to the human
|
|
39
43
|
|
|
@@ -9,6 +9,10 @@ description: Use when data, schema, API, dependency, platform, infrastructure, o
|
|
|
9
9
|
|
|
10
10
|
Design or execute a staged, observable, reversible transition with explicit compatibility windows, validation, and cleanup.
|
|
11
11
|
|
|
12
|
+
## Workspace protocol
|
|
13
|
+
|
|
14
|
+
Read `../../references/workspaces.md` before selecting or creating workflow artifacts. Follow it for persistence, consent, work-item resolution, and lifecycle; this skill owns only the task-specific behavior below.
|
|
15
|
+
|
|
12
16
|
## Inputs
|
|
13
17
|
|
|
14
18
|
- Source and target states, invariants, data volume, traffic, and downtime tolerance
|
|
@@ -33,7 +37,7 @@ Design or execute a staged, observable, reversible transition with explicit comp
|
|
|
33
37
|
## Decision-log updates
|
|
34
38
|
|
|
35
39
|
Record compatibility windows, cutover criteria, data ownership, transformation rules, rollback limits, accepted downtime, and irreversible checkpoints. Link evidence for completing each phase.
|
|
36
|
-
|
|
40
|
+
When durable state is approved, append compatibility, sequencing, rollback, and point-of-no-return choices to the selected work item's decisions.md; otherwise include them in the final response.
|
|
37
41
|
|
|
38
42
|
## Escalate to the human
|
|
39
43
|
|
|
@@ -9,16 +9,20 @@ description: Use when a software direction is defined enough to map multi-step,
|
|
|
9
9
|
|
|
10
10
|
Turn the request and repository evidence into a decision-ready spec and a concise, verifiable execution map. Plan to the level warranted by risk; do not add ceremony to trivial work.
|
|
11
11
|
|
|
12
|
+
## Workspace protocol
|
|
13
|
+
|
|
14
|
+
Read `../../references/workspaces.md` before selecting or creating workflow artifacts. Follow it for persistence, consent, work-item resolution, and lifecycle; this skill owns only the task-specific behavior below.
|
|
15
|
+
|
|
12
16
|
## Inputs
|
|
13
17
|
|
|
14
18
|
- User goal, constraints, and expected behavior
|
|
15
19
|
- Applicable `AGENTS.md`, current code, tests, docs, issues, and runtime evidence
|
|
16
|
-
-
|
|
20
|
+
- The selected work item's spec, plan, and decisions when durable state is active
|
|
17
21
|
|
|
18
22
|
## Outputs
|
|
19
23
|
|
|
20
24
|
- A decision-ready spec and concise execution map with testable acceptance criteria
|
|
21
|
-
-
|
|
25
|
+
- For approved durable work, updated `spec.md` and `plan.md` in the selected work-item directory
|
|
22
26
|
- A short summary of assumptions and human decisions needed
|
|
23
27
|
|
|
24
28
|
## Rules
|
|
@@ -33,7 +37,7 @@ Turn the request and repository evidence into a decision-ready spec and a concis
|
|
|
33
37
|
## Decision-log updates
|
|
34
38
|
|
|
35
39
|
Record scope interpretations, contract choices, rejected approaches with non-obvious tradeoffs, and material re-plans. Link each entry to the affected plan item.
|
|
36
|
-
|
|
40
|
+
When durable state is approved, append the decision to the selected work item's `decisions.md`; otherwise include it in the final response.
|
|
37
41
|
|
|
38
42
|
## Escalate to the human
|
|
39
43
|
|
|
@@ -9,6 +9,10 @@ description: Use when internal code structure, naming, duplication, coupling, co
|
|
|
9
9
|
|
|
10
10
|
Improve changeability and clarity while preserving behavior and keeping the diff proportionate to a concrete maintenance problem.
|
|
11
11
|
|
|
12
|
+
## Workspace protocol
|
|
13
|
+
|
|
14
|
+
Read `../../references/workspaces.md` before selecting or creating workflow artifacts. Follow it for persistence, consent, work-item resolution, and lifecycle; this skill owns only the task-specific behavior below.
|
|
15
|
+
|
|
12
16
|
## Inputs
|
|
13
17
|
|
|
14
18
|
- Refactoring goal or documented code smell
|
|
@@ -33,7 +37,7 @@ Improve changeability and clarity while preserving behavior and keeping the diff
|
|
|
33
37
|
## Decision-log updates
|
|
34
38
|
|
|
35
39
|
Record new module boundaries, ownership changes, intentionally retained debt, compatibility constraints, and abstraction choices with long-term consequences. Routine renames and local cleanup do not need entries.
|
|
36
|
-
|
|
40
|
+
When durable state is approved, append boundary changes, compatibility assumptions, and accepted tradeoffs to the selected work item's decisions.md; for a selected approved durable work item with an existing plan.md, update only relevant plan-item status and verification evidence for the performed refactoring scope, never invent unrelated work, and do not mark the work completed unless the workspace lifecycle criteria are satisfied; otherwise include material decisions and performed-scope verification in the final response.
|
|
37
41
|
|
|
38
42
|
## Escalate to the human
|
|
39
43
|
|
|
@@ -9,6 +9,10 @@ description: Use when a change, branch, build, migration, or release candidate m
|
|
|
9
9
|
|
|
10
10
|
Produce an evidence-backed `ready`, `not ready`, or `ready with accepted risks` verdict. Assessment does not authorize release actions.
|
|
11
11
|
|
|
12
|
+
## Workspace protocol
|
|
13
|
+
|
|
14
|
+
Read `../../references/workspaces.md` before selecting or creating workflow artifacts. Follow it for persistence, consent, work-item resolution, and lifecycle; this skill owns only the task-specific behavior below.
|
|
15
|
+
|
|
12
16
|
## Inputs
|
|
13
17
|
|
|
14
18
|
- Release scope, target environment, acceptance criteria, and rollout expectations
|
|
@@ -23,6 +27,7 @@ Produce an evidence-backed `ready`, `not ready`, or `ready with accepted risks`
|
|
|
23
27
|
|
|
24
28
|
## Rules
|
|
25
29
|
|
|
30
|
+
- For a selected work item, read its acceptance criteria, current plan state, findings, and verification evidence when available before judging readiness; reading this state neither authorizes release nor by itself requires artifact mutation.
|
|
26
31
|
- Inspect current state; do not rely on stale claims that checks passed.
|
|
27
32
|
- Run the strongest safe local checks and distinguish local proof from CI, staging, and production proof.
|
|
28
33
|
- Treat code complete, merge ready, deploy ready, deployed, and verified in production as separate states.
|
|
@@ -32,7 +37,7 @@ Produce an evidence-backed `ready`, `not ready`, or `ready with accepted risks`
|
|
|
32
37
|
## Decision-log updates
|
|
33
38
|
|
|
34
39
|
Record risk acceptance, waived gates, rollout or rollback choices, and readiness verdict changes with evidence. Link unresolved findings and owners.
|
|
35
|
-
|
|
40
|
+
When durable state is approved, append only accepted release risk, waivers, rollback choices, and readiness-scope decisions to the selected work item's decisions.md; otherwise include them in the final response.
|
|
36
41
|
|
|
37
42
|
## Escalate to the human
|
|
38
43
|
|
|
@@ -9,6 +9,10 @@ description: Use for a general objective code, diff, PR, or fix review without e
|
|
|
9
9
|
|
|
10
10
|
Find actionable correctness, compatibility, security, reliability, and maintainability defects in the requested change or scope. Review is read-only.
|
|
11
11
|
|
|
12
|
+
## Workspace protocol
|
|
13
|
+
|
|
14
|
+
Read `../../references/workspaces.md` before selecting or creating workflow artifacts. Follow it for persistence, consent, work-item resolution, and lifecycle; this skill owns only the task-specific behavior below.
|
|
15
|
+
|
|
12
16
|
## Inputs
|
|
13
17
|
|
|
14
18
|
- Review baseline and target: diff, commit, branch, files, or stated behavior
|
|
@@ -31,8 +35,8 @@ Find actionable correctness, compatibility, security, reliability, and maintaina
|
|
|
31
35
|
|
|
32
36
|
## Decision-log updates
|
|
33
37
|
|
|
34
|
-
Record only review-scope interpretations or accepted risk decisions that future work must preserve.
|
|
35
|
-
|
|
38
|
+
Record only review-scope interpretations or accepted risk decisions that future work must preserve.
|
|
39
|
+
When durable state is approved, track defects and their lifecycle in the selected work item's findings.md and append only review-scope or accepted-risk decisions to decisions.md; otherwise report them in the final response.
|
|
36
40
|
|
|
37
41
|
## Escalate to the human
|
|
38
42
|
|
|
@@ -9,6 +9,10 @@ description: Use when security is the primary assessment objective for code, con
|
|
|
9
9
|
|
|
10
10
|
Identify plausible, evidence-backed security weaknesses across trust boundaries, attacker-controlled inputs, identities, secrets, data, and operational controls. Review is read-only.
|
|
11
11
|
|
|
12
|
+
## Workspace protocol
|
|
13
|
+
|
|
14
|
+
Read `../../references/workspaces.md` before selecting or creating workflow artifacts. Follow it for persistence, consent, work-item resolution, and lifecycle; this skill owns only the task-specific behavior below.
|
|
15
|
+
|
|
12
16
|
## Inputs
|
|
13
17
|
|
|
14
18
|
- Defined scope, threat assumptions, and deployment context
|
|
@@ -31,8 +35,8 @@ Identify plausible, evidence-backed security weaknesses across trust boundaries,
|
|
|
31
35
|
|
|
32
36
|
## Decision-log updates
|
|
33
37
|
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
Log only accepted security tradeoffs, threat-model assumptions, compensating controls, or risk acceptance decisions.
|
|
39
|
+
When durable state is approved, track sanitized vulnerabilities in the selected work item's findings.md and append accepted security tradeoffs, threat assumptions, compensating controls, or risk acceptance to decisions.md; otherwise report them in the final response.
|
|
36
40
|
|
|
37
41
|
## Escalate to the human
|
|
38
42
|
|
|
@@ -9,6 +9,10 @@ description: Use when software behavior needs new or improved unit, integration,
|
|
|
9
9
|
|
|
10
10
|
Create the smallest reliable test set that proves important behavior and failure modes through stable public seams.
|
|
11
11
|
|
|
12
|
+
## Workspace protocol
|
|
13
|
+
|
|
14
|
+
Read `../../references/workspaces.md` before selecting or creating workflow artifacts. Follow it for persistence, consent, work-item resolution, and lifecycle; this skill owns only the task-specific behavior below.
|
|
15
|
+
|
|
12
16
|
## Inputs
|
|
13
17
|
|
|
14
18
|
- Behavioral contract, bug report, acceptance criteria, or changed code
|
|
@@ -33,7 +37,7 @@ Create the smallest reliable test set that proves important behavior and failure
|
|
|
33
37
|
## Decision-log updates
|
|
34
38
|
|
|
35
39
|
Record material test-boundary choices, intentionally excluded coverage, chosen substitutes for unavailable dependencies, and risk accepted because a scenario cannot be automated. Routine test cases do not need entries.
|
|
36
|
-
|
|
40
|
+
When durable state is approved, append material test-boundary, fidelity, or coverage-risk decisions to the selected work item's decisions.md; for a selected approved durable work item with an existing plan.md, update only relevant plan-item status and verification evidence for the performed testing scope, never invent unrelated work, and do not mark the work completed unless the workspace lifecycle criteria are satisfied; otherwise include material decisions and performed-scope verification in the final response.
|
|
37
41
|
|
|
38
42
|
## Escalate to the human
|
|
39
43
|
|
package/scripts/validate.mjs
CHANGED
|
@@ -3,6 +3,14 @@ import { readFile } from 'node:fs/promises';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
|
|
5
5
|
import { listFiles } from '../src/fs-safe.js';
|
|
6
|
+
import {
|
|
7
|
+
assertCanonicalSkillInventory,
|
|
8
|
+
assertWorkspaceProtocolContract,
|
|
9
|
+
} from '../src/plugin-contract.js';
|
|
10
|
+
import {
|
|
11
|
+
assertSkillWorkspaceContract,
|
|
12
|
+
expectedDurableEndings,
|
|
13
|
+
} from '../src/skill-contract.js';
|
|
6
14
|
|
|
7
15
|
const root = path.resolve(import.meta.dirname, '..');
|
|
8
16
|
const packageJson = JSON.parse(await readFile(path.join(root, 'package.json'), 'utf8'));
|
|
@@ -12,7 +20,14 @@ assert.equal(plugin.version, packageJson.version);
|
|
|
12
20
|
|
|
13
21
|
const skillRoot = path.join(root, 'plugin', 'skills');
|
|
14
22
|
const skillFiles = (await listFiles(skillRoot)).filter((file) => file.endsWith('/SKILL.md'));
|
|
15
|
-
|
|
23
|
+
const skillNames = skillFiles.map((file) => file.split(path.sep)[0]);
|
|
24
|
+
assertCanonicalSkillInventory(skillNames);
|
|
25
|
+
assert.deepEqual(
|
|
26
|
+
skillNames.sort(),
|
|
27
|
+
Object.keys(expectedDurableEndings).sort(),
|
|
28
|
+
);
|
|
29
|
+
const workspaceProtocol = await readFile(path.join(root, 'plugin', 'references', 'workspaces.md'), 'utf8');
|
|
30
|
+
assertWorkspaceProtocolContract(workspaceProtocol);
|
|
16
31
|
for (const relative of skillFiles) {
|
|
17
32
|
const expectedName = relative.split(path.sep)[0];
|
|
18
33
|
const content = await readFile(path.join(skillRoot, relative), 'utf8');
|
|
@@ -20,7 +35,7 @@ for (const relative of skillFiles) {
|
|
|
20
35
|
const shortDescription = metadata.match(/short_description: "([^"]+)"/)?.[1];
|
|
21
36
|
assert.match(content, new RegExp(`^---\\nname: ${expectedName}\\ndescription: .+\\n---`, 's'));
|
|
22
37
|
assert.doesNotMatch(content, /TODO|Superpowers|\.codex\/skills/);
|
|
23
|
-
|
|
38
|
+
assertSkillWorkspaceContract(expectedName, content);
|
|
24
39
|
assert.ok(shortDescription && shortDescription.length >= 25 && shortDescription.length <= 64);
|
|
25
40
|
assert.doesNotMatch(metadata, /Reusable engineering workflow|for this task\./);
|
|
26
41
|
assert.match(metadata, new RegExp(`default_prompt: ".*\\$${expectedName.replaceAll('-', '\\-')}\\b`));
|
package/src/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ export const HELP = `nono-skills <command> [options]
|
|
|
4
4
|
|
|
5
5
|
Commands:
|
|
6
6
|
install Install the engineering Codex plugin
|
|
7
|
-
init [directory] Add
|
|
7
|
+
init [directory] Add optional repository guidance
|
|
8
8
|
update Update an owned plugin installation
|
|
9
9
|
doctor Diagnose the plugin installation
|
|
10
10
|
uninstall Remove the owned plugin installation
|
|
@@ -60,7 +60,12 @@ export async function run(argv, context) {
|
|
|
60
60
|
return 1;
|
|
61
61
|
}
|
|
62
62
|
if (options.version) {
|
|
63
|
-
|
|
63
|
+
const version = context.packageVersion ?? context.version;
|
|
64
|
+
if (version === undefined) {
|
|
65
|
+
stderr.write('Package version is unavailable\n');
|
|
66
|
+
return 1;
|
|
67
|
+
}
|
|
68
|
+
stdout.write(`${version}\n`);
|
|
64
69
|
return 0;
|
|
65
70
|
}
|
|
66
71
|
if (options.help) {
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
|
|
3
|
+
export const canonicalSkillNames = Object.freeze([
|
|
4
|
+
'api-design',
|
|
5
|
+
'architecture-review',
|
|
6
|
+
'brainstorm',
|
|
7
|
+
'database-design',
|
|
8
|
+
'debug',
|
|
9
|
+
'estimate',
|
|
10
|
+
'fix-findings',
|
|
11
|
+
'implement',
|
|
12
|
+
'migration',
|
|
13
|
+
'plan',
|
|
14
|
+
'refactor',
|
|
15
|
+
'release-readiness',
|
|
16
|
+
'review',
|
|
17
|
+
'security-review',
|
|
18
|
+
'test',
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
function protocolClause(id, text) {
|
|
22
|
+
return Object.freeze({ id, text });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const workspaceProtocolClauses = Object.freeze([
|
|
26
|
+
protocolClause('document.title', '# Adaptive Workspaces'),
|
|
27
|
+
protocolClause('document.purpose', 'Use this protocol before deciding whether to create, select, or update workflow artifacts. The active skill still owns its task-specific behavior.'),
|
|
28
|
+
protocolClause('classification.heading', '## 1. Classify persistence'),
|
|
29
|
+
protocolClause('classification.transient-durable', 'Classify the task as transient or durable using judgment, not fixed size thresholds.'),
|
|
30
|
+
protocolClause('classification.transient-default', 'Durable state is justified when the user asks for it, work is likely to cross Codex tasks or owners, multiple outcomes need tracking, migration/security/release/compatibility risk is material, findings need a fix lifecycle, or decisions must survive the conversation. Keep localized one-shot work transient unless the user asks otherwise.'),
|
|
31
|
+
protocolClause('consent.heading', '## 2. Establish consent'),
|
|
32
|
+
protocolClause('consent.explicit', 'Explicit requests for a spec, plan, progress log, decision log, findings tracker, handoff, or named existing work item already grant artifact consent for that scope.'),
|
|
33
|
+
protocolClause('consent.proposed', 'When Codex decides a new durable workspace would help, state why, the proposed path, scope, and initial files, then ask once before creating the workspace. Approval covers artifact maintenance inside that work-item scope; it does not authorize unrelated implementation, commits, pushes, deployments, production changes, destructive actions, external writes, or spend.'),
|
|
34
|
+
protocolClause('consent.decline', 'If the user declines, create no equivalent files elsewhere. Continue safely in chat and report material decisions and residual risk in the final response.'),
|
|
35
|
+
protocolClause('resolution.heading', '## 3. Resolve or create the work item'),
|
|
36
|
+
protocolClause('resolution.precedence', 'Resolve in this order:'),
|
|
37
|
+
protocolClause('resolution.current-task', '1. the work item already approved in the current Codex task'),
|
|
38
|
+
protocolClause('resolution.explicit-id', '2. an explicit work ID, path, issue, or ticket from the user'),
|
|
39
|
+
protocolClause('resolution.issue-match', '3. an exact issue or ticket metadata match'),
|
|
40
|
+
protocolClause('resolution.branch-match', '4. an exact current non-default branch match to one active item'),
|
|
41
|
+
protocolClause('resolution.scope-match', '5. one active item whose goal and scope clearly match'),
|
|
42
|
+
protocolClause('resolution.recency-ambiguity', 'Recency alone is never sufficient. Ask the user when multiple items remain plausible.'),
|
|
43
|
+
protocolClause('resolution.new-id', 'For new work, prefer `issue-<number>-<slug>` when an issue exists; otherwise use `YYYY-MM-DD-<goal-slug>`. Add a numeric suffix on collision and never overwrite unrelated contents.'),
|
|
44
|
+
protocolClause('workspace.heading', '## 4. Maintain the workspace'),
|
|
45
|
+
protocolClause('workspace.anchor', 'The anchor is `docs/agent/work/<work-id>/spec.md` with YAML front matter containing `work_id`, `title`, `status`, optional `issue`, optional `branch`, `created`, and `updated`. Status is `active`, `blocked`, `completed`, or `superseded`.'),
|
|
46
|
+
protocolClause('workspace.creation-updated', 'Start every new approved work item with `status: active`; set both `created` and `updated` when creating its anchor. Refresh `updated` on every authoritative work-item artifact or status mutation. Keep the current status truthful so work-item resolution never relies on stale `active` metadata.'),
|
|
47
|
+
protocolClause('lifecycle.blocked', 'Use `blocked` only when in-scope progress cannot continue because of a concrete unresolved dependency, missing input or authority, or required external change. Record the blocker and resumption condition in `plan.md` or `handoff.md` as applicable; return the status to `active` and refresh `updated` when the blocker is resolved.'),
|
|
48
|
+
protocolClause('lifecycle.completed', 'Use `completed` only when all in-scope acceptance criteria and tracked plan items are satisfied, required verification evidence is recorded, and no unresolved blocking findings or work remain. Set the status to `completed` and refresh `updated`; do not move or delete the work-item directory.'),
|
|
49
|
+
protocolClause('lifecycle.superseded', 'Use `superseded` only when the work is intentionally replaced. Record the reason and successor or reference as a material decision, set the status to `superseded`, and refresh `updated`; do not move or delete the work-item directory.'),
|
|
50
|
+
protocolClause('lifecycle.reopen', 'Reopening completed work changes its status to `active`, refreshes `updated`, and records the material reason.'),
|
|
51
|
+
protocolClause('artifacts.lazy', 'Create files lazily:'),
|
|
52
|
+
protocolClause('artifacts.spec', '- `spec.md` for every approved durable work item'),
|
|
53
|
+
protocolClause('artifacts.plan', '- `plan.md` when outcomes, dependencies, or verification targets need tracking'),
|
|
54
|
+
protocolClause('artifacts.decisions', '- `decisions.md` on the first material decision'),
|
|
55
|
+
protocolClause('artifacts.findings', '- `findings.md` when findings need lifecycle tracking'),
|
|
56
|
+
protocolClause('artifacts.handoff', '- `handoff.md` only when work remains or ownership changes'),
|
|
57
|
+
protocolClause('artifacts.no-global-index', 'Do not create a global mutable index or move completed work-item directories. Log only contractual choices, meaningful ambiguity resolutions, accepted risks or tradeoffs, material re-plans, and assumptions future work must preserve.'),
|
|
58
|
+
protocolClause('scope.heading', '## 5. Respect scope and failures'),
|
|
59
|
+
protocolClause('scope.authority', 'The original request controls implementation authority: an implementation request permits ordinary in-repository edits, while a planning request stops after planning. Ask again for material scope expansion, breaking or destructive behavior, production or external-system mutation, or significant spend.'),
|
|
60
|
+
protocolClause('legacy.preservation', 'Repository instructions override the default artifact location. If creation fails, report exactly what exists and continue in chat when safe. Never silently create artifacts at another path. Treat existing 0.1.0 singleton files as legacy user content: read them only when explicitly named or unambiguously relevant, and never move, merge, or delete them automatically.'),
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
export function assertCanonicalSkillInventory(actualNames) {
|
|
64
|
+
assert.deepEqual(
|
|
65
|
+
[...actualNames].sort(),
|
|
66
|
+
[...canonicalSkillNames].sort(),
|
|
67
|
+
'plugin skill inventory must contain exactly the 15 canonical skills',
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function assertWorkspaceProtocolContract(content) {
|
|
72
|
+
const authoritativeLines = content
|
|
73
|
+
.split(/\r?\n/)
|
|
74
|
+
.filter((line) => line.trim() !== '');
|
|
75
|
+
|
|
76
|
+
for (const clause of workspaceProtocolClauses) {
|
|
77
|
+
assert.equal(
|
|
78
|
+
authoritativeLines.filter((line) => line === clause.text).length,
|
|
79
|
+
1,
|
|
80
|
+
`workspace protocol must include ${clause.id} exactly once`,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
assert.deepEqual(
|
|
85
|
+
authoritativeLines,
|
|
86
|
+
workspaceProtocolClauses.map((clause) => clause.text),
|
|
87
|
+
'workspace protocol must contain only canonical authoritative clauses in order',
|
|
88
|
+
);
|
|
89
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
|
|
3
|
+
export const workspaceSection = `## Workspace protocol
|
|
4
|
+
|
|
5
|
+
Read \`../../references/workspaces.md\` before selecting or creating workflow artifacts. Follow it for persistence, consent, work-item resolution, and lifecycle; this skill owns only the task-specific behavior below.`;
|
|
6
|
+
|
|
7
|
+
export const expectedDurableEndings = Object.freeze({
|
|
8
|
+
'api-design': "When durable state is approved, append contract choices and compatibility consequences to the selected work item's decisions.md; otherwise include them in the final response.",
|
|
9
|
+
'architecture-review': "When durable state is approved, append structural tradeoffs or accepted architecture risk to the selected work item's decisions.md and track actionable defects in findings.md; otherwise report them in the final response.",
|
|
10
|
+
brainstorm: "When durable state is approved, append the accepted direction, recurring tradeoffs, assumptions, and next experiment to the selected work item's decisions.md; otherwise include them in the final response.",
|
|
11
|
+
'database-design': "When durable state is approved, append invariant, consistency, migration, and operational choices to the selected work item's decisions.md; otherwise include them in the final response.",
|
|
12
|
+
debug: "When durable state is approved, append the validated root cause, rejected material hypotheses, and consequential fix choices to the selected work item's decisions.md and create handoff.md only when work remains; for a selected approved durable work item with an existing plan.md, update only relevant plan-item status and verification evidence for the performed debugging scope, never invent unrelated work, and do not mark the work completed unless the workspace lifecycle criteria are satisfied; otherwise include material decisions and performed-scope verification in the final response.",
|
|
13
|
+
estimate: "When durable state is approved, append scope interpretations, estimation model changes, and accepted schedule tradeoffs to the selected work item's decisions.md; otherwise include them in the final response.",
|
|
14
|
+
'fix-findings': "When durable state is approved, update the selected work item's findings.md with status and verification evidence, and append material remediation tradeoffs to decisions.md; otherwise report state changes and decisions in the final response.",
|
|
15
|
+
implement: "When durable state is approved, append the decision to the selected work item's `decisions.md` and update its plan or handoff when applicable; otherwise include it in the final response.",
|
|
16
|
+
migration: "When durable state is approved, append compatibility, sequencing, rollback, and point-of-no-return choices to the selected work item's decisions.md; otherwise include them in the final response.",
|
|
17
|
+
plan: "When durable state is approved, append the decision to the selected work item's `decisions.md`; otherwise include it in the final response.",
|
|
18
|
+
refactor: "When durable state is approved, append boundary changes, compatibility assumptions, and accepted tradeoffs to the selected work item's decisions.md; for a selected approved durable work item with an existing plan.md, update only relevant plan-item status and verification evidence for the performed refactoring scope, never invent unrelated work, and do not mark the work completed unless the workspace lifecycle criteria are satisfied; otherwise include material decisions and performed-scope verification in the final response.",
|
|
19
|
+
'release-readiness': "When durable state is approved, append only accepted release risk, waivers, rollback choices, and readiness-scope decisions to the selected work item's decisions.md; otherwise include them in the final response.",
|
|
20
|
+
review: "When durable state is approved, track defects and their lifecycle in the selected work item's findings.md and append only review-scope or accepted-risk decisions to decisions.md; otherwise report them in the final response.",
|
|
21
|
+
'security-review': "When durable state is approved, track sanitized vulnerabilities in the selected work item's findings.md and append accepted security tradeoffs, threat assumptions, compensating controls, or risk acceptance to decisions.md; otherwise report them in the final response.",
|
|
22
|
+
test: "When durable state is approved, append material test-boundary, fidelity, or coverage-risk decisions to the selected work item's decisions.md; for a selected approved durable work item with an existing plan.md, update only relevant plan-item status and verification evidence for the performed testing scope, never invent unrelated work, and do not mark the work completed unless the workspace lifecycle criteria are satisfied; otherwise include material decisions and performed-scope verification in the final response.",
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export const expectedRequiredResponsibilityLines = Object.freeze({
|
|
26
|
+
'release-readiness': Object.freeze([
|
|
27
|
+
'- For a selected work item, read its acceptance criteria, current plan state, findings, and verification evidence when available before judging readiness; reading this state neither authorizes release nor by itself requires artifact mutation.',
|
|
28
|
+
]),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const planDurableOutput = '- For approved durable work, updated `spec.md` and `plan.md` in the selected work-item directory';
|
|
32
|
+
|
|
33
|
+
export const allowedArtifactLines = Object.freeze(Object.fromEntries(
|
|
34
|
+
Object.entries(expectedDurableEndings).map(([name, ending]) => [
|
|
35
|
+
name,
|
|
36
|
+
Object.freeze(name === 'plan' ? [ending, planDurableOutput] : [ending]),
|
|
37
|
+
]),
|
|
38
|
+
));
|
|
39
|
+
|
|
40
|
+
const workspaceBody = workspaceSection.slice(workspaceSection.indexOf('\n\n') + 2);
|
|
41
|
+
const legacySingletonReference = /\bdecision-log\.md\b|\bdocs\/agent\/(?:spec|plan|decisions|decision-log|findings|handoff)\.md\b/i;
|
|
42
|
+
const workflowArtifactReference = /\b(?:spec|plan|decisions|findings|handoff)\.md\b/i;
|
|
43
|
+
|
|
44
|
+
function openingFence(line) {
|
|
45
|
+
const match = line.match(/^ {0,3}(`{3,}|~{3,})(.*)$/);
|
|
46
|
+
if (!match || (match[1][0] === '`' && match[2].includes('`'))) return null;
|
|
47
|
+
return { character: match[1][0], length: match[1].length };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function closesFence(line, fence) {
|
|
51
|
+
const match = line.match(/^ {0,3}(`+|~+)[ \t]*$/);
|
|
52
|
+
return Boolean(
|
|
53
|
+
match
|
|
54
|
+
&& match[1][0] === fence.character
|
|
55
|
+
&& match[1].length >= fence.length,
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function stripHtmlComments(line, commentOpen) {
|
|
60
|
+
let cursor = 0;
|
|
61
|
+
let text = '';
|
|
62
|
+
let hadComment = commentOpen;
|
|
63
|
+
|
|
64
|
+
while (cursor < line.length) {
|
|
65
|
+
if (commentOpen) {
|
|
66
|
+
const close = line.indexOf('-->', cursor);
|
|
67
|
+
if (close === -1) return { commentOpen: true, hadComment: true, text };
|
|
68
|
+
cursor = close + 3;
|
|
69
|
+
commentOpen = false;
|
|
70
|
+
hadComment = true;
|
|
71
|
+
} else {
|
|
72
|
+
const open = line.indexOf('<!--', cursor);
|
|
73
|
+
if (open === -1) {
|
|
74
|
+
text += line.slice(cursor);
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
text += line.slice(cursor, open);
|
|
78
|
+
cursor = open + 4;
|
|
79
|
+
commentOpen = true;
|
|
80
|
+
hadComment = true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return { commentOpen, hadComment, text };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function authoritativeLines(content) {
|
|
88
|
+
const sourceLines = content.split('\n');
|
|
89
|
+
const lines = [];
|
|
90
|
+
let fence = null;
|
|
91
|
+
let htmlCommentOpen = false;
|
|
92
|
+
let start = 0;
|
|
93
|
+
|
|
94
|
+
for (let index = 0; index < sourceLines.length; index += 1) {
|
|
95
|
+
const text = sourceLines[index];
|
|
96
|
+
const hasLineEnding = index < sourceLines.length - 1;
|
|
97
|
+
const end = start + text.length + (hasLineEnding ? 1 : 0);
|
|
98
|
+
|
|
99
|
+
if (fence) {
|
|
100
|
+
if (closesFence(text, fence)) fence = null;
|
|
101
|
+
} else {
|
|
102
|
+
const visible = stripHtmlComments(text, htmlCommentOpen);
|
|
103
|
+
htmlCommentOpen = visible.commentOpen;
|
|
104
|
+
if (!(visible.hadComment && visible.text.trim() === '')) {
|
|
105
|
+
if (/^(?: {4}|\t)/.test(visible.text)) {
|
|
106
|
+
start = end;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const openedFence = openingFence(visible.text);
|
|
110
|
+
if (openedFence) {
|
|
111
|
+
fence = openedFence;
|
|
112
|
+
} else {
|
|
113
|
+
lines.push({
|
|
114
|
+
text: visible.text,
|
|
115
|
+
start,
|
|
116
|
+
end,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
start = end;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return lines;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function normalizedLevelTwoHeading(line) {
|
|
128
|
+
const match = line.match(/^ {0,3}##(?!#)(?:[ \t]+(.*))?[ \t]*$/);
|
|
129
|
+
if (!match) return null;
|
|
130
|
+
const name = (match[1] ?? '')
|
|
131
|
+
.trimEnd()
|
|
132
|
+
.replace(/[ \t]+#+$/, '')
|
|
133
|
+
.trim();
|
|
134
|
+
return name || null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function markdownSections(lines) {
|
|
138
|
+
const sections = [];
|
|
139
|
+
for (const line of lines) {
|
|
140
|
+
const name = normalizedLevelTwoHeading(line.text);
|
|
141
|
+
if (name) sections.push({ name, start: line.start, bodyStart: line.end });
|
|
142
|
+
}
|
|
143
|
+
return sections;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function uniqueSectionIndex(name, sections, skillName) {
|
|
147
|
+
const indexes = sections
|
|
148
|
+
.map((section, index) => (section.name === name ? index : -1))
|
|
149
|
+
.filter((index) => index !== -1);
|
|
150
|
+
assert.equal(
|
|
151
|
+
indexes.length,
|
|
152
|
+
1,
|
|
153
|
+
`${skillName} must define exactly one normalized ${name} section`,
|
|
154
|
+
);
|
|
155
|
+
return indexes[0];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function sectionBody(content, sections, index) {
|
|
159
|
+
const end = sections[index + 1]?.start ?? content.length;
|
|
160
|
+
return content.slice(sections[index].bodyStart, end);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function normalizeInlineMarkdown(text) {
|
|
164
|
+
return text
|
|
165
|
+
.replace(/!?\[([^\]\n]*)\]\(((?:\\.|[^\\)\n])*)\)/g, '$1 $2')
|
|
166
|
+
.replace(/\\([\\`*_{}\[\]()#+\-.!])/g, '$1')
|
|
167
|
+
.replace(/[`*_~]/g, '');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function assertArtifactLines(name, lines) {
|
|
171
|
+
const allowedLines = allowedArtifactLines[name];
|
|
172
|
+
const normalizedLines = lines.map(({ text }) => ({
|
|
173
|
+
normalized: normalizeInlineMarkdown(text),
|
|
174
|
+
text,
|
|
175
|
+
}));
|
|
176
|
+
|
|
177
|
+
for (const { normalized } of normalizedLines) {
|
|
178
|
+
assert.doesNotMatch(
|
|
179
|
+
normalized,
|
|
180
|
+
legacySingletonReference,
|
|
181
|
+
`${name} must not reference legacy singleton workflow artifacts`,
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
for (const { normalized, text } of normalizedLines) {
|
|
186
|
+
if (workflowArtifactReference.test(normalized)) {
|
|
187
|
+
assert.ok(
|
|
188
|
+
allowedLines.includes(text.trim()),
|
|
189
|
+
`${name} must use only allowed authoritative workflow artifact lines`,
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
for (const allowedLine of allowedLines) {
|
|
195
|
+
assert.equal(
|
|
196
|
+
normalizedLines.filter(({ text }) => text.trim() === allowedLine).length,
|
|
197
|
+
1,
|
|
198
|
+
`${name} must include each allowed authoritative workflow artifact line exactly once`,
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function assertRequiredResponsibilityLines(name, lines) {
|
|
204
|
+
for (const requiredLine of expectedRequiredResponsibilityLines[name] ?? []) {
|
|
205
|
+
assert.equal(
|
|
206
|
+
lines.filter(({ text }) => text.trim() === requiredLine).length,
|
|
207
|
+
1,
|
|
208
|
+
`${name} must include each required responsibility line exactly once`,
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function finalAuthoritativeSectionLine(lines, sections, index) {
|
|
214
|
+
const start = sections[index].bodyStart;
|
|
215
|
+
const end = sections[index + 1]?.start ?? Number.POSITIVE_INFINITY;
|
|
216
|
+
return lines
|
|
217
|
+
.filter((line) => line.start >= start && line.start < end && line.text.trim() !== '')
|
|
218
|
+
.at(-1)?.text.trim();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export function assertSkillWorkspaceContract(name, content) {
|
|
222
|
+
const expectedEnding = expectedDurableEndings[name];
|
|
223
|
+
assert.ok(expectedEnding, `${name} must be in the expected skill inventory`);
|
|
224
|
+
|
|
225
|
+
const lines = authoritativeLines(content);
|
|
226
|
+
const sections = markdownSections(lines);
|
|
227
|
+
const purposeIndex = uniqueSectionIndex('Purpose', sections, name);
|
|
228
|
+
const workspaceIndex = uniqueSectionIndex('Workspace protocol', sections, name);
|
|
229
|
+
const decisionIndex = uniqueSectionIndex('Decision-log updates', sections, name);
|
|
230
|
+
assert.equal(
|
|
231
|
+
workspaceIndex,
|
|
232
|
+
purposeIndex + 1,
|
|
233
|
+
`${name} must place the Workspace protocol section immediately after Purpose`,
|
|
234
|
+
);
|
|
235
|
+
assert.equal(
|
|
236
|
+
sectionBody(content, sections, workspaceIndex).replace(/\n+$/, ''),
|
|
237
|
+
`\n${workspaceBody}`,
|
|
238
|
+
`${name} must use the exact Workspace protocol section`,
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
assert.equal(
|
|
242
|
+
finalAuthoritativeSectionLine(lines, sections, decisionIndex),
|
|
243
|
+
expectedEnding,
|
|
244
|
+
`${name} must end Decision-log updates with its durable-state contract`,
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
assertArtifactLines(name, lines);
|
|
248
|
+
assertRequiredResponsibilityLines(name, lines);
|
|
249
|
+
}
|
package/src/uninstall.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { constants } from 'node:fs';
|
|
3
|
+
import { lstat, open, readFile, realpath, rm, stat } from 'node:fs/promises';
|
|
2
4
|
import path from 'node:path';
|
|
3
5
|
|
|
4
|
-
import { sha256File } from './fs-safe.js';
|
|
5
6
|
import { readMarketplace, removeMarketplaceEntry, verifyOwnership, writeJsonAtomic } from './plugin-state.js';
|
|
6
7
|
|
|
7
8
|
async function exists(file) {
|
|
@@ -32,18 +33,163 @@ export async function uninstallPlugin({ home, runCodex }) {
|
|
|
32
33
|
return { status: 'uninstalled', projectArtifactsPreserved: true };
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
function recordedPathPolicy(relative) {
|
|
37
|
+
const normalized = relative.replaceAll('\\', '/');
|
|
38
|
+
if (path.posix.isAbsolute(normalized) || /^[A-Za-z]:\//.test(normalized)) {
|
|
39
|
+
return { safe: false };
|
|
40
|
+
}
|
|
41
|
+
const canonical = path.posix.normalize(normalized);
|
|
42
|
+
if (canonical === '..' || canonical.startsWith('../')) {
|
|
43
|
+
return { safe: false };
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
safe: true,
|
|
47
|
+
canonical,
|
|
48
|
+
isWorkItem: canonical.toLowerCase().startsWith('docs/agent/work/'),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function isStrictDescendant(root, candidate) {
|
|
53
|
+
const relative = path.relative(root, candidate);
|
|
54
|
+
return relative !== ''
|
|
55
|
+
&& relative !== '..'
|
|
56
|
+
&& !relative.startsWith(`..${path.sep}`)
|
|
57
|
+
&& !path.isAbsolute(relative);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function sameFileSnapshot(left, right) {
|
|
61
|
+
return left.dev === right.dev
|
|
62
|
+
&& left.ino === right.ino
|
|
63
|
+
&& left.mode === right.mode
|
|
64
|
+
&& left.size === right.size
|
|
65
|
+
&& left.mtimeNs === right.mtimeNs
|
|
66
|
+
&& left.ctimeNs === right.ctimeNs;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function isUnsafePathError(error) {
|
|
70
|
+
return error.code === 'ELOOP' || error.code === 'ENOTDIR';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function inspectDescendant(root, candidate) {
|
|
74
|
+
if (!isStrictDescendant(root, candidate)) return { status: 'unsafe' };
|
|
75
|
+
const relative = path.relative(root, candidate);
|
|
76
|
+
let current = root;
|
|
77
|
+
let snapshot;
|
|
78
|
+
for (const component of relative.split(path.sep)) {
|
|
79
|
+
current = path.join(current, component);
|
|
80
|
+
try {
|
|
81
|
+
snapshot = await lstat(current, { bigint: true });
|
|
82
|
+
} catch (error) {
|
|
83
|
+
if (error.code === 'ENOENT') return { status: 'missing' };
|
|
84
|
+
if (isUnsafePathError(error)) return { status: 'unsafe' };
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
if (snapshot.isSymbolicLink()) return { status: 'unsafe' };
|
|
88
|
+
}
|
|
89
|
+
return { status: 'safe', snapshot };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function validatePhysicalCandidate({ lexicalRoot, physicalRoot, candidate, expected }) {
|
|
93
|
+
const lexical = await inspectDescendant(lexicalRoot, candidate);
|
|
94
|
+
if (lexical.status !== 'safe') {
|
|
95
|
+
return expected && lexical.status === 'missing' ? { status: 'unsafe' } : lexical;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
let physical;
|
|
99
|
+
try {
|
|
100
|
+
physical = await realpath(candidate);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
if (error.code === 'ENOENT' || isUnsafePathError(error)) return { status: 'unsafe' };
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
if (!isStrictDescendant(physicalRoot, physical)) return { status: 'unsafe' };
|
|
106
|
+
|
|
107
|
+
const physicalInspection = await inspectDescendant(physicalRoot, physical);
|
|
108
|
+
const lexicalConfirmation = await inspectDescendant(lexicalRoot, candidate);
|
|
109
|
+
if (physicalInspection.status !== 'safe' || lexicalConfirmation.status !== 'safe') {
|
|
110
|
+
return { status: 'unsafe' };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
let physicalConfirmation;
|
|
114
|
+
try {
|
|
115
|
+
physicalConfirmation = await realpath(candidate);
|
|
116
|
+
} catch (error) {
|
|
117
|
+
if (error.code === 'ENOENT' || isUnsafePathError(error)) return { status: 'unsafe' };
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
if (physicalConfirmation !== physical
|
|
121
|
+
|| !sameFileSnapshot(lexical.snapshot, physicalInspection.snapshot)
|
|
122
|
+
|| !sameFileSnapshot(lexical.snapshot, lexicalConfirmation.snapshot)) {
|
|
123
|
+
return { status: 'unsafe' };
|
|
124
|
+
}
|
|
125
|
+
if (expected && (expected.physical !== physical || !sameFileSnapshot(expected.snapshot, lexical.snapshot))) {
|
|
126
|
+
return { status: 'unsafe' };
|
|
127
|
+
}
|
|
128
|
+
return { status: 'safe', physical, snapshot: lexical.snapshot };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async function hashValidatedFile(file, expectedSnapshot) {
|
|
132
|
+
let handle;
|
|
133
|
+
try {
|
|
134
|
+
handle = await open(file, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
135
|
+
} catch (error) {
|
|
136
|
+
if (error.code === 'ENOENT' || isUnsafePathError(error)) return { status: 'unsafe' };
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
const before = await handle.stat({ bigint: true });
|
|
141
|
+
if (!sameFileSnapshot(before, expectedSnapshot)) return { status: 'unsafe' };
|
|
142
|
+
const content = await handle.readFile();
|
|
143
|
+
const after = await handle.stat({ bigint: true });
|
|
144
|
+
if (!sameFileSnapshot(before, after)) return { status: 'unsafe' };
|
|
145
|
+
return { status: 'safe', digest: createHash('sha256').update(content).digest('hex') };
|
|
146
|
+
} finally {
|
|
147
|
+
await handle.close();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
35
151
|
export async function purgeProject({ targetRoot, recordedChecksums }) {
|
|
36
152
|
const removed = [];
|
|
37
153
|
const preserved = [];
|
|
154
|
+
const lexicalRoot = path.resolve(targetRoot);
|
|
155
|
+
let physicalRoot;
|
|
156
|
+
try {
|
|
157
|
+
physicalRoot = await realpath(lexicalRoot);
|
|
158
|
+
} catch (error) {
|
|
159
|
+
if (error.code !== 'ENOENT') throw error;
|
|
160
|
+
}
|
|
38
161
|
for (const [relative, expected] of Object.entries(recordedChecksums).sort(([a], [b]) => a.localeCompare(b))) {
|
|
39
|
-
const
|
|
162
|
+
const policy = recordedPathPolicy(relative);
|
|
163
|
+
if (!policy.safe || policy.isWorkItem) {
|
|
164
|
+
preserved.push(relative);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (!physicalRoot) continue;
|
|
168
|
+
const file = path.resolve(lexicalRoot, ...policy.canonical.split('/'));
|
|
40
169
|
try {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
170
|
+
const beforeHash = await validatePhysicalCandidate({ lexicalRoot, physicalRoot, candidate: file });
|
|
171
|
+
if (beforeHash.status === 'missing') continue;
|
|
172
|
+
if (beforeHash.status !== 'safe') {
|
|
173
|
+
preserved.push(relative);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const hash = await hashValidatedFile(beforeHash.physical, beforeHash.snapshot);
|
|
177
|
+
if (hash.status !== 'safe' || hash.digest !== expected) {
|
|
178
|
+
preserved.push(relative);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
const beforeRemoval = await validatePhysicalCandidate({
|
|
182
|
+
lexicalRoot, physicalRoot, candidate: file, expected: beforeHash,
|
|
183
|
+
});
|
|
184
|
+
if (beforeRemoval.status !== 'safe') {
|
|
185
|
+
preserved.push(relative);
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
await rm(beforeRemoval.physical);
|
|
189
|
+
removed.push(relative);
|
|
45
190
|
} catch (error) {
|
|
46
|
-
if (error.code
|
|
191
|
+
if (error.code === 'ENOENT') preserved.push(relative);
|
|
192
|
+
else throw error;
|
|
47
193
|
}
|
|
48
194
|
}
|
|
49
195
|
return { removed, preserved };
|
package/templates/AGENTS.md
CHANGED
|
@@ -18,19 +18,11 @@ Keep this file specific to the repository. Replace placeholders with commands an
|
|
|
18
18
|
- Keep external writes, commits, pushes, merges, releases, deployments, and production mutations behind explicit user authorization.
|
|
19
19
|
- Verify changed behavior with the strongest safe repository checks available. Report what ran and what remains unverified.
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## Durable task state
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Keep simple, one-shot work artifact-free; ask before creating a new durable workspace unless the user explicitly requested durable artifacts or named an existing work item.
|
|
24
24
|
|
|
25
|
-
- `spec.md
|
|
26
|
-
- `plan.md`: current execution map, status, dependencies, and verification targets
|
|
27
|
-
- `decision-log.md`: material decisions, evidence, alternatives, and consequences
|
|
28
|
-
- `findings.md`: review findings and their lifecycle
|
|
29
|
-
- `handoff.md`: resumable state when work remains or ownership changes
|
|
30
|
-
|
|
31
|
-
Do not create missing workflow artifacts unless the user requests durable artifacts or runs `npx nono-skills init`. Without them, put the same material information in the final response.
|
|
32
|
-
|
|
33
|
-
Append a decision only when it changes a contract, resolves meaningful ambiguity, accepts risk or a costly tradeoff, changes the plan materially, or records an assumption future work must preserve. Supersede accepted entries instead of rewriting history. Do not log routine edits or shell commands.
|
|
25
|
+
Approved work lives under `docs/agent/work/<work-id>/`. Keep each feature isolated, let its `spec.md` define scope and status, record only material decisions, and never select another work item by recency alone. Repository-specific instructions override the default location.
|
|
34
26
|
|
|
35
27
|
## Definition of done
|
|
36
28
|
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# Decision Log
|
|
2
|
-
|
|
3
|
-
Append material decisions. Never silently rewrite an accepted decision; supersede it with a new entry.
|
|
4
|
-
|
|
5
|
-
## YYYY-MM-DD HH:MM — Decision title
|
|
6
|
-
|
|
7
|
-
- Status: proposed | accepted | superseded | rejected
|
|
8
|
-
- Context:
|
|
9
|
-
- Decision:
|
|
10
|
-
- Alternatives:
|
|
11
|
-
- Evidence and rationale:
|
|
12
|
-
- Consequences:
|
|
13
|
-
- Follow-up:
|
|
14
|
-
- Related:
|
|
15
|
-
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# Findings
|
|
2
|
-
|
|
3
|
-
## Finding ID — Short title
|
|
4
|
-
|
|
5
|
-
- Severity: critical | high | medium | low
|
|
6
|
-
- State: open | accepted | fixed | verified | wont-fix | not-reproducible
|
|
7
|
-
- Evidence:
|
|
8
|
-
- Impact:
|
|
9
|
-
- Reproduction or reasoning:
|
|
10
|
-
- Remediation direction:
|
|
11
|
-
- Verification:
|
|
12
|
-
- Owner or follow-up:
|
|
13
|
-
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# Working Plan
|
|
2
|
-
|
|
3
|
-
Status values: `pending`, `in-progress`, `blocked`, `done`.
|
|
4
|
-
|
|
5
|
-
| Status | Work item | Verification | Notes |
|
|
6
|
-
|---|---|---|---|
|
|
7
|
-
| pending | | | |
|
|
8
|
-
|
|
9
|
-
## Risks and dependencies
|
|
10
|
-
|
|
11
|
-
## Human decisions needed
|
|
12
|
-
|
|
13
|
-
## Latest checkpoint
|
|
14
|
-
|