sdtk-ops-kit 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 +146 -0
- package/assets/manifest/toolkit-bundle.manifest.json +187 -0
- package/assets/manifest/toolkit-bundle.sha256.txt +36 -0
- package/assets/toolkit/toolkit/AGENTS.md +65 -0
- package/assets/toolkit/toolkit/SDTKOPS_TOOLKIT.md +166 -0
- package/assets/toolkit/toolkit/install.ps1 +138 -0
- package/assets/toolkit/toolkit/scripts/install-claude-skills.ps1 +81 -0
- package/assets/toolkit/toolkit/scripts/install-codex-skills.ps1 +127 -0
- package/assets/toolkit/toolkit/scripts/uninstall-claude-skills.ps1 +65 -0
- package/assets/toolkit/toolkit/scripts/uninstall-codex-skills.ps1 +53 -0
- package/assets/toolkit/toolkit/sdtk-spec.config.json +6 -0
- package/assets/toolkit/toolkit/sdtk-spec.config.profiles.example.json +12 -0
- package/assets/toolkit/toolkit/skills/ops-backup/SKILL.md +93 -0
- package/assets/toolkit/toolkit/skills/ops-backup/references/backup-script-patterns.md +108 -0
- package/assets/toolkit/toolkit/skills/ops-ci-cd/SKILL.md +88 -0
- package/assets/toolkit/toolkit/skills/ops-ci-cd/references/pipeline-examples.md +113 -0
- package/assets/toolkit/toolkit/skills/ops-compliance/SKILL.md +105 -0
- package/assets/toolkit/toolkit/skills/ops-container/SKILL.md +95 -0
- package/assets/toolkit/toolkit/skills/ops-container/references/k8s-manifest-patterns.md +116 -0
- package/assets/toolkit/toolkit/skills/ops-cost/SKILL.md +88 -0
- package/assets/toolkit/toolkit/skills/ops-debug/SKILL.md +311 -0
- package/assets/toolkit/toolkit/skills/ops-debug/references/root-cause-tracing.md +138 -0
- package/assets/toolkit/toolkit/skills/ops-deploy/SKILL.md +102 -0
- package/assets/toolkit/toolkit/skills/ops-discover/SKILL.md +102 -0
- package/assets/toolkit/toolkit/skills/ops-incident/SKILL.md +113 -0
- package/assets/toolkit/toolkit/skills/ops-incident/references/communication-templates.md +34 -0
- package/assets/toolkit/toolkit/skills/ops-incident/references/postmortem-template.md +69 -0
- package/assets/toolkit/toolkit/skills/ops-incident/references/runbook-template.md +69 -0
- package/assets/toolkit/toolkit/skills/ops-infra-plan/SKILL.md +123 -0
- package/assets/toolkit/toolkit/skills/ops-infra-plan/references/iac-patterns.md +141 -0
- package/assets/toolkit/toolkit/skills/ops-monitor/SKILL.md +110 -0
- package/assets/toolkit/toolkit/skills/ops-monitor/references/alert-rules.md +80 -0
- package/assets/toolkit/toolkit/skills/ops-monitor/references/slo-templates.md +83 -0
- package/assets/toolkit/toolkit/skills/ops-parallel/SKILL.md +177 -0
- package/assets/toolkit/toolkit/skills/ops-plan/SKILL.md +169 -0
- package/assets/toolkit/toolkit/skills/ops-security-infra/SKILL.md +126 -0
- package/assets/toolkit/toolkit/skills/ops-security-infra/references/cicd-security-pipeline.md +55 -0
- package/assets/toolkit/toolkit/skills/ops-security-infra/references/security-headers.md +24 -0
- package/assets/toolkit/toolkit/skills/ops-verify/SKILL.md +180 -0
- package/bin/sdtk-ops.js +14 -0
- package/package.json +46 -0
- package/src/commands/generate.js +12 -0
- package/src/commands/help.js +53 -0
- package/src/commands/init.js +86 -0
- package/src/commands/runtime.js +201 -0
- package/src/index.js +65 -0
- package/src/lib/args.js +107 -0
- package/src/lib/errors.js +41 -0
- package/src/lib/powershell.js +65 -0
- package/src/lib/scope.js +58 -0
- package/src/lib/toolkit-payload.js +123 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<!-- Based on agency-agents by AgentLand Contributors (MIT License, 2025). Adapted for SDTK-OPS. -->
|
|
2
|
+
|
|
3
|
+
# Security Headers
|
|
4
|
+
|
|
5
|
+
```nginx
|
|
6
|
+
server {
|
|
7
|
+
add_header X-Content-Type-Options "nosniff" always;
|
|
8
|
+
add_header X-Frame-Options "DENY" always;
|
|
9
|
+
add_header X-XSS-Protection "1; mode=block" always;
|
|
10
|
+
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
|
11
|
+
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';" always;
|
|
12
|
+
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
13
|
+
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;
|
|
14
|
+
|
|
15
|
+
server_tokens off;
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Pattern Notes
|
|
20
|
+
|
|
21
|
+
- tune CSP to the actual application surface before enforcing it
|
|
22
|
+
- keep headers consistent across edge and app-serving paths
|
|
23
|
+
- remove unnecessary server disclosure where the platform permits it
|
|
24
|
+
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
<!-- Based on superpowers by Jesse Vincent (MIT License, 2025). Adapted for SDTK-OPS. -->
|
|
2
|
+
---
|
|
3
|
+
name: ops-verify
|
|
4
|
+
description: Verification before completion. Use before claiming any infrastructure change, deployment, or operational task is done -- run verification commands and confirm output, evidence before assertions.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Ops Verify
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
Claiming work is complete without verification is dishonesty, not efficiency.
|
|
12
|
+
|
|
13
|
+
**Core principle:** Evidence before claims, always.
|
|
14
|
+
|
|
15
|
+
**Violating the letter of this rule is violating the spirit of this rule.**
|
|
16
|
+
|
|
17
|
+
## The Iron Law
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
If you have not run the verification command in this message, you cannot claim it passes.
|
|
24
|
+
|
|
25
|
+
## The Gate Function
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
BEFORE claiming any status or expressing satisfaction:
|
|
29
|
+
|
|
30
|
+
1. IDENTIFY: What command proves this claim?
|
|
31
|
+
2. RUN: Execute the FULL command (fresh, complete)
|
|
32
|
+
3. READ: Full output, check exit code, count failures
|
|
33
|
+
4. VERIFY: Does output confirm the claim?
|
|
34
|
+
- If NO: State actual status with evidence
|
|
35
|
+
- If YES: State claim WITH evidence
|
|
36
|
+
5. ONLY THEN: Make the claim
|
|
37
|
+
|
|
38
|
+
Skip any step = lying, not verifying
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Common Failures
|
|
42
|
+
|
|
43
|
+
| Claim | Requires | Not Sufficient |
|
|
44
|
+
|-------|----------|----------------|
|
|
45
|
+
| Tests pass | Test command output: 0 failures | Previous run, "should pass" |
|
|
46
|
+
| Linter clean | Linter output: 0 errors | Partial check, extrapolation |
|
|
47
|
+
| Build succeeds | Build command: exit 0 | Linter passing, logs look good |
|
|
48
|
+
| Bug fixed | Test original symptom: passes | Code changed, assumed fixed |
|
|
49
|
+
| Regression test works | Red-green cycle verified | Test passes once |
|
|
50
|
+
| Agent completed | VCS diff shows changes | Agent reports "success" |
|
|
51
|
+
| Requirements met | Line-by-line checklist | Tests passing |
|
|
52
|
+
|
|
53
|
+
## Common Mistakes
|
|
54
|
+
|
|
55
|
+
| Mistake | Why it fails |
|
|
56
|
+
|---------|--------------|
|
|
57
|
+
| Claim success from expectation instead of output | You report intent, not evidence |
|
|
58
|
+
| Reuse old command output | State may have changed since the earlier run |
|
|
59
|
+
| Verify only one layer of a multi-step change | Hidden failure survives past the claim |
|
|
60
|
+
| Trust a delegated agent without independent checks | Reported completion may not match the actual result |
|
|
61
|
+
|
|
62
|
+
## Red Flags - STOP
|
|
63
|
+
|
|
64
|
+
- Using "should", "probably", "seems to"
|
|
65
|
+
- Expressing satisfaction before verification ("Great!", "Perfect!", "Done!", etc.)
|
|
66
|
+
- About to commit, push, or close a task without verification
|
|
67
|
+
- Trusting agent success reports
|
|
68
|
+
- Relying on partial verification
|
|
69
|
+
- Thinking "just this once"
|
|
70
|
+
- Tired and wanting work over
|
|
71
|
+
- **ANY wording implying success without having run verification**
|
|
72
|
+
|
|
73
|
+
## Rationalization Prevention
|
|
74
|
+
|
|
75
|
+
| Excuse | Reality |
|
|
76
|
+
|--------|---------|
|
|
77
|
+
| "Should work now" | RUN the verification |
|
|
78
|
+
| "I'm confident" | Confidence is not evidence |
|
|
79
|
+
| "Just this once" | No exceptions |
|
|
80
|
+
| "Linter passed" | Linter is not compiler |
|
|
81
|
+
| "Agent said success" | Verify independently |
|
|
82
|
+
| "I'm tired" | Exhaustion is not an excuse |
|
|
83
|
+
| "Partial check is enough" | Partial proves nothing |
|
|
84
|
+
| "Different words so rule doesn't apply" | Spirit over letter |
|
|
85
|
+
|
|
86
|
+
## Key Patterns
|
|
87
|
+
|
|
88
|
+
**Tests:**
|
|
89
|
+
```
|
|
90
|
+
[Run test command] [See: 34/34 pass] "All tests pass"
|
|
91
|
+
"Should pass now" / "Looks correct"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Regression tests (TDD Red-Green):**
|
|
95
|
+
```
|
|
96
|
+
Write -> Run (pass) -> Revert fix -> Run (MUST FAIL) -> Restore -> Run (pass)
|
|
97
|
+
"I've written a regression test" (without red-green verification)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Build:**
|
|
101
|
+
```
|
|
102
|
+
[Run build] [See: exit 0] "Build passes"
|
|
103
|
+
"Linter passed" (linter does not check compilation)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Requirements:**
|
|
107
|
+
```
|
|
108
|
+
Re-read plan -> Create checklist -> Verify each -> Report gaps or completion
|
|
109
|
+
"Tests pass, phase complete"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Agent delegation:**
|
|
113
|
+
```
|
|
114
|
+
Agent reports success -> Check VCS diff -> Verify changes -> Report actual state
|
|
115
|
+
Trust agent report
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Infrastructure Verification Patterns
|
|
119
|
+
|
|
120
|
+
**Health check:**
|
|
121
|
+
```
|
|
122
|
+
[Run: curl -s https://service.example/health]
|
|
123
|
+
[See: {"status":"healthy"}]
|
|
124
|
+
"Service healthy"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**DNS:**
|
|
128
|
+
```
|
|
129
|
+
[Run: dig +short api.example.com]
|
|
130
|
+
[See: correct IP or CNAME]
|
|
131
|
+
"DNS propagated"
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Container:**
|
|
135
|
+
```
|
|
136
|
+
[Run: kubectl get pods -n production]
|
|
137
|
+
[See: Running, Ready 1/1]
|
|
138
|
+
"Pods healthy"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Cloud resource:**
|
|
142
|
+
```
|
|
143
|
+
[Run: provider CLI state check]
|
|
144
|
+
[See: active or available]
|
|
145
|
+
"Resource provisioned"
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Why This Matters
|
|
149
|
+
|
|
150
|
+
From repeated operational failures:
|
|
151
|
+
- the user stops trusting status claims that are not backed by evidence
|
|
152
|
+
- undefined or unhealthy runtime states can ship into production
|
|
153
|
+
- missing requirements or skipped rollback checks lead to incomplete releases
|
|
154
|
+
- time gets wasted on false completion -> redirect -> rework
|
|
155
|
+
- operational honesty matters as much as implementation honesty
|
|
156
|
+
|
|
157
|
+
## When To Apply
|
|
158
|
+
|
|
159
|
+
**ALWAYS before:**
|
|
160
|
+
- ANY variation of success or completion claims
|
|
161
|
+
- ANY expression of satisfaction
|
|
162
|
+
- ANY positive statement about operational state
|
|
163
|
+
- Deployment completion
|
|
164
|
+
- Incident closure
|
|
165
|
+
- Moving to the next task
|
|
166
|
+
- Delegating to agents
|
|
167
|
+
|
|
168
|
+
**Rule applies to:**
|
|
169
|
+
- Exact phrases
|
|
170
|
+
- Paraphrases and synonyms
|
|
171
|
+
- Implications of success
|
|
172
|
+
- ANY communication suggesting completion or correctness
|
|
173
|
+
|
|
174
|
+
## The Bottom Line
|
|
175
|
+
|
|
176
|
+
**No shortcuts for verification.**
|
|
177
|
+
|
|
178
|
+
Run the command. Read the output. THEN claim the result.
|
|
179
|
+
|
|
180
|
+
This is non-negotiable.
|
package/bin/sdtk-ops.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { run } = require("../src/index");
|
|
6
|
+
|
|
7
|
+
run(process.argv.slice(2))
|
|
8
|
+
.then((exitCode) => {
|
|
9
|
+
process.exitCode = Number.isInteger(exitCode) ? exitCode : 0;
|
|
10
|
+
})
|
|
11
|
+
.catch((error) => {
|
|
12
|
+
console.error(`sdtk-ops: ${error.message}`);
|
|
13
|
+
process.exitCode = typeof error.exitCode === "number" ? error.exitCode : 4;
|
|
14
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sdtk-ops-kit",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Skill-driven operations toolkit for deployment, verification, monitoring, incident response, backup, security, compliance, and cost discipline.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"sdtk-ops": "./bin/sdtk-ops.js"
|
|
7
|
+
},
|
|
8
|
+
"main": "src/index.js",
|
|
9
|
+
"type": "commonjs",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/codexsdtk/sdtk-toolkit.git",
|
|
13
|
+
"directory": "products/sdtk-ops/distribution/sdtk-ops-kit"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/codexsdtk/sdtk-toolkit/tree/main/products/sdtk-ops/distribution/sdtk-ops-kit",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/codexsdtk/sdtk-toolkit/issues"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"bin/",
|
|
21
|
+
"src/",
|
|
22
|
+
"assets/"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"test": "powershell -ExecutionPolicy Bypass -Command \"$ErrorActionPreference = 'Stop'; Set-Location '..\\..\\..\\..'; python -m unittest -v tests.test_sdtk_ops_cli\"",
|
|
26
|
+
"build:payload": "powershell -ExecutionPolicy Bypass -Command \"$ErrorActionPreference = 'Stop'; & 'scripts/sync-toolkit-assets.ps1'; & 'scripts/build-toolkit-manifest.ps1'\"",
|
|
27
|
+
"verify:payload": "node -e \"require('./src/lib/toolkit-payload').verify()\"",
|
|
28
|
+
"pack:smoke": "powershell -ExecutionPolicy Bypass -File scripts/pack-smoke.ps1",
|
|
29
|
+
"prepublishOnly": "npm run build:payload && npm run verify:payload"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18.13.0"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"sdtk-ops",
|
|
36
|
+
"cli",
|
|
37
|
+
"toolkit",
|
|
38
|
+
"operations",
|
|
39
|
+
"claude",
|
|
40
|
+
"codex"
|
|
41
|
+
],
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { ValidationError } = require("../lib/errors");
|
|
4
|
+
|
|
5
|
+
async function cmdGenerate(args) {
|
|
6
|
+
void args;
|
|
7
|
+
throw new ValidationError(
|
|
8
|
+
'The "generate" command is not part of the supported SDTK-OPS workflow-entry surface. Use "sdtk-ops help" for supported commands and start with the "ops-discover" skill if the correct journey is unclear.'
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = { cmdGenerate };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function cmdHelp() {
|
|
4
|
+
const text = [
|
|
5
|
+
"SDTK-OPS CLI -- internal operations discipline toolkit",
|
|
6
|
+
"",
|
|
7
|
+
"Usage:",
|
|
8
|
+
" sdtk-ops <command> [options]",
|
|
9
|
+
"",
|
|
10
|
+
"Commands:",
|
|
11
|
+
" init Initialize SDTK-OPS files in a project",
|
|
12
|
+
" runtime Manage runtime asset installation (install, uninstall, status)",
|
|
13
|
+
" help Show this help message",
|
|
14
|
+
"",
|
|
15
|
+
"Current supported surface:",
|
|
16
|
+
" Supported now: help, init, runtime install|status|uninstall",
|
|
17
|
+
" Not supported: generate",
|
|
18
|
+
" Package scope: internal_only",
|
|
19
|
+
"",
|
|
20
|
+
"Workflow entry:",
|
|
21
|
+
" After init, choose a journey directly if the goal is clear.",
|
|
22
|
+
" Canonical journeys: deployment, incident, monitoring, backup/recovery.",
|
|
23
|
+
" If the correct path is unclear, start with the ops-discover skill.",
|
|
24
|
+
" Close every journey with ops-verify before declaring work complete.",
|
|
25
|
+
"",
|
|
26
|
+
"Runtime support:",
|
|
27
|
+
" Claude: project + user scope",
|
|
28
|
+
" Codex: user scope only",
|
|
29
|
+
" Gate C0: Codex project scope is rejected",
|
|
30
|
+
"",
|
|
31
|
+
"Global options:",
|
|
32
|
+
" -h, --help Show this help",
|
|
33
|
+
" -v, --version Show version",
|
|
34
|
+
"",
|
|
35
|
+
"Examples:",
|
|
36
|
+
" sdtk-ops --help",
|
|
37
|
+
" sdtk-ops --version",
|
|
38
|
+
" sdtk-ops init --runtime claude --project-path ./my-project",
|
|
39
|
+
" sdtk-ops runtime install --runtime claude --scope project --project-path ./my-project",
|
|
40
|
+
" # Journey routing after init:",
|
|
41
|
+
" # deployment -> ops-plan -> ops-infra-plan -> ops-container -> ops-ci-cd -> ops-deploy -> ops-monitor -> ops-verify",
|
|
42
|
+
" # incident -> ops-incident -> ops-debug -> ops-monitor -> ops-verify",
|
|
43
|
+
" # monitoring -> ops-plan -> ops-monitor -> ops-verify",
|
|
44
|
+
" # recovery -> ops-plan -> ops-backup -> ops-verify",
|
|
45
|
+
" sdtk-ops runtime status --runtime codex",
|
|
46
|
+
" sdtk-ops runtime uninstall --runtime codex --scope user",
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
console.log(text.join("\n"));
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
module.exports = { cmdHelp };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const { parseFlags, validateChoice } = require("../lib/args");
|
|
5
|
+
const { verify, resolvePayloadFile } = require("../lib/toolkit-payload");
|
|
6
|
+
const { runScript } = require("../lib/powershell");
|
|
7
|
+
const { ValidationError } = require("../lib/errors");
|
|
8
|
+
const { VALID_SCOPES, defaultScope, isProjectScopeSupported } = require("../lib/scope");
|
|
9
|
+
|
|
10
|
+
const FLAG_DEFS = {
|
|
11
|
+
runtime: { type: "string" },
|
|
12
|
+
"project-path": { type: "string" },
|
|
13
|
+
"runtime-scope": { type: "string" },
|
|
14
|
+
force: { type: "boolean" },
|
|
15
|
+
"skip-skills": { type: "boolean" },
|
|
16
|
+
"skip-runtime-assets": { type: "boolean" },
|
|
17
|
+
verbose: { type: "boolean" },
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const VALID_RUNTIMES = ["codex", "claude"];
|
|
21
|
+
|
|
22
|
+
async function cmdInit(args) {
|
|
23
|
+
const { flags } = parseFlags(args, FLAG_DEFS);
|
|
24
|
+
|
|
25
|
+
const runtime = flags.runtime || "codex";
|
|
26
|
+
validateChoice(runtime, VALID_RUNTIMES, "runtime");
|
|
27
|
+
|
|
28
|
+
const scope = flags["runtime-scope"] || defaultScope(runtime);
|
|
29
|
+
validateChoice(scope, VALID_SCOPES, "runtime-scope");
|
|
30
|
+
if (scope === "project" && !isProjectScopeSupported(runtime)) {
|
|
31
|
+
throw new ValidationError(
|
|
32
|
+
"Codex does not support project-local skills. Use --runtime-scope user instead."
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const skipAssets = flags["skip-runtime-assets"] || flags["skip-skills"];
|
|
37
|
+
if (flags["skip-skills"] && !flags["skip-runtime-assets"]) {
|
|
38
|
+
console.warn("Warning: --skip-skills is deprecated. Use --skip-runtime-assets instead.");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const projectPath = flags["project-path"] ? path.resolve(flags["project-path"]) : process.cwd();
|
|
42
|
+
|
|
43
|
+
verify();
|
|
44
|
+
|
|
45
|
+
const installScript = resolvePayloadFile("toolkit/install.ps1");
|
|
46
|
+
const params = {
|
|
47
|
+
ProjectPath: projectPath,
|
|
48
|
+
Runtime: runtime,
|
|
49
|
+
Scope: scope,
|
|
50
|
+
};
|
|
51
|
+
if (flags.force) {
|
|
52
|
+
params.Force = true;
|
|
53
|
+
}
|
|
54
|
+
if (skipAssets) {
|
|
55
|
+
params.SkipRuntimeAssets = true;
|
|
56
|
+
}
|
|
57
|
+
if (!flags.verbose) {
|
|
58
|
+
params.Quiet = true;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log("Initializing SDTK-OPS workspace...");
|
|
62
|
+
console.log(` Runtime: ${runtime}`);
|
|
63
|
+
console.log(` Scope: ${scope}`);
|
|
64
|
+
console.log(` Project: ${projectPath}`);
|
|
65
|
+
console.log("");
|
|
66
|
+
|
|
67
|
+
const result = await runScript(installScript, params, { silent: !flags.verbose });
|
|
68
|
+
if (result.exitCode !== 0) {
|
|
69
|
+
if (result.stderr) {
|
|
70
|
+
console.error(result.stderr);
|
|
71
|
+
}
|
|
72
|
+
throw new ValidationError(`Initialization failed (exit code ${result.exitCode}).`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
console.log("");
|
|
76
|
+
console.log("SDTK-OPS workspace initialized successfully.");
|
|
77
|
+
console.log("");
|
|
78
|
+
console.log("Next steps:");
|
|
79
|
+
console.log(" 1. Review and customize sdtk-spec.config.json for your operations environment.");
|
|
80
|
+
console.log(" 2. Use the installed ops-* skill set for deployment, monitoring, incident, and recovery workflows.");
|
|
81
|
+
return 0;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
module.exports = {
|
|
85
|
+
cmdInit,
|
|
86
|
+
};
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const { parseFlags, requireFlag, validateChoice } = require("../lib/args");
|
|
6
|
+
const { verify, resolvePayloadFile } = require("../lib/toolkit-payload");
|
|
7
|
+
const { runScript } = require("../lib/powershell");
|
|
8
|
+
const { ValidationError } = require("../lib/errors");
|
|
9
|
+
const {
|
|
10
|
+
VALID_SCOPES,
|
|
11
|
+
defaultScope,
|
|
12
|
+
isProjectScopeSupported,
|
|
13
|
+
managedSkillNames,
|
|
14
|
+
resolveSkillsDir,
|
|
15
|
+
} = require("../lib/scope");
|
|
16
|
+
|
|
17
|
+
const FLAG_DEFS = {
|
|
18
|
+
runtime: { type: "string" },
|
|
19
|
+
scope: { type: "string" },
|
|
20
|
+
"project-path": { type: "string" },
|
|
21
|
+
force: { type: "boolean" },
|
|
22
|
+
all: { type: "boolean" },
|
|
23
|
+
verbose: { type: "boolean" },
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const VALID_RUNTIMES = ["codex", "claude"];
|
|
27
|
+
const SUBCOMMANDS = ["install", "uninstall", "status"];
|
|
28
|
+
|
|
29
|
+
function validateScopeForRuntime(runtime, scope, label) {
|
|
30
|
+
if (scope === "project" && !isProjectScopeSupported(runtime)) {
|
|
31
|
+
throw new ValidationError(
|
|
32
|
+
`Codex does not support project-local skills. Use --${label} user instead.`
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function cmdRuntimeInstall(flags) {
|
|
38
|
+
const runtime = requireFlag(flags, "runtime", "runtime");
|
|
39
|
+
validateChoice(runtime, VALID_RUNTIMES, "runtime");
|
|
40
|
+
|
|
41
|
+
const scope = flags.scope || defaultScope(runtime);
|
|
42
|
+
validateChoice(scope, VALID_SCOPES, "scope");
|
|
43
|
+
validateScopeForRuntime(runtime, scope, "scope");
|
|
44
|
+
|
|
45
|
+
const projectPath = flags["project-path"] ? path.resolve(flags["project-path"]) : process.cwd();
|
|
46
|
+
verify();
|
|
47
|
+
|
|
48
|
+
const scriptName =
|
|
49
|
+
runtime === "claude"
|
|
50
|
+
? "toolkit/scripts/install-claude-skills.ps1"
|
|
51
|
+
: "toolkit/scripts/install-codex-skills.ps1";
|
|
52
|
+
const script = resolvePayloadFile(scriptName);
|
|
53
|
+
const params = { Scope: scope };
|
|
54
|
+
if (runtime === "claude") {
|
|
55
|
+
params.ProjectPath = projectPath;
|
|
56
|
+
}
|
|
57
|
+
if (flags.force) {
|
|
58
|
+
params.Force = true;
|
|
59
|
+
}
|
|
60
|
+
if (!flags.verbose) {
|
|
61
|
+
params.Quiet = true;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log(`Installing ${runtime} runtime assets...`);
|
|
65
|
+
console.log(` Runtime: ${runtime}`);
|
|
66
|
+
console.log(` Scope: ${scope}`);
|
|
67
|
+
if (runtime === "claude" && scope === "project") {
|
|
68
|
+
console.log(` Project: ${projectPath}`);
|
|
69
|
+
}
|
|
70
|
+
console.log("");
|
|
71
|
+
|
|
72
|
+
const result = await runScript(script, params, { silent: !flags.verbose });
|
|
73
|
+
if (result.exitCode !== 0) {
|
|
74
|
+
if (result.stderr) {
|
|
75
|
+
console.error(result.stderr);
|
|
76
|
+
}
|
|
77
|
+
throw new ValidationError(`Runtime install failed (exit code ${result.exitCode}).`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log("");
|
|
81
|
+
console.log(`${runtime} runtime assets installed successfully.`);
|
|
82
|
+
return 0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function cmdRuntimeUninstall(flags) {
|
|
86
|
+
const runtime = requireFlag(flags, "runtime", "runtime");
|
|
87
|
+
validateChoice(runtime, VALID_RUNTIMES, "runtime");
|
|
88
|
+
|
|
89
|
+
const scope = flags.scope || defaultScope(runtime);
|
|
90
|
+
validateChoice(scope, VALID_SCOPES, "scope");
|
|
91
|
+
validateScopeForRuntime(runtime, scope, "scope");
|
|
92
|
+
|
|
93
|
+
const projectPath = flags["project-path"] ? path.resolve(flags["project-path"]) : process.cwd();
|
|
94
|
+
verify();
|
|
95
|
+
|
|
96
|
+
const scriptName =
|
|
97
|
+
runtime === "claude"
|
|
98
|
+
? "toolkit/scripts/uninstall-claude-skills.ps1"
|
|
99
|
+
: "toolkit/scripts/uninstall-codex-skills.ps1";
|
|
100
|
+
const script = resolvePayloadFile(scriptName);
|
|
101
|
+
const params = { All: true };
|
|
102
|
+
if (runtime === "claude") {
|
|
103
|
+
params.Scope = scope;
|
|
104
|
+
params.ProjectPath = projectPath;
|
|
105
|
+
}
|
|
106
|
+
if (!flags.verbose) {
|
|
107
|
+
params.Quiet = true;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const result = await runScript(script, params, { silent: !flags.verbose });
|
|
111
|
+
if (result.exitCode !== 0) {
|
|
112
|
+
if (result.stderr) {
|
|
113
|
+
console.error(result.stderr);
|
|
114
|
+
}
|
|
115
|
+
throw new ValidationError(`Runtime uninstall failed (exit code ${result.exitCode}).`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log(`Uninstalled ${runtime} runtime assets for scope ${scope}.`);
|
|
119
|
+
return 0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function cmdRuntimeStatus(flags) {
|
|
123
|
+
const runtime = requireFlag(flags, "runtime", "runtime");
|
|
124
|
+
validateChoice(runtime, VALID_RUNTIMES, "runtime");
|
|
125
|
+
|
|
126
|
+
const projectPath = flags["project-path"] ? path.resolve(flags["project-path"]) : process.cwd();
|
|
127
|
+
const scopes = runtime === "claude" ? ["project", "user"] : ["user"];
|
|
128
|
+
|
|
129
|
+
console.log(`Runtime: ${runtime}`);
|
|
130
|
+
console.log("");
|
|
131
|
+
|
|
132
|
+
for (const scope of scopes) {
|
|
133
|
+
const skillsDir = resolveSkillsDir(runtime, scope, projectPath);
|
|
134
|
+
const managed = managedSkillNames(runtime);
|
|
135
|
+
const exists = fs.existsSync(skillsDir);
|
|
136
|
+
let installedNames = [];
|
|
137
|
+
|
|
138
|
+
if (exists) {
|
|
139
|
+
try {
|
|
140
|
+
const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
|
|
141
|
+
installedNames = entries
|
|
142
|
+
.filter((entry) => entry.isDirectory() && managed.includes(entry.name))
|
|
143
|
+
.map((entry) => entry.name)
|
|
144
|
+
.sort();
|
|
145
|
+
} catch {
|
|
146
|
+
installedNames = [];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const skillCount = installedNames.length;
|
|
151
|
+
const allInstalled = skillCount === managed.length;
|
|
152
|
+
const hasManagedSkills = skillCount > 0;
|
|
153
|
+
const status = !exists || !hasManagedSkills
|
|
154
|
+
? "not installed"
|
|
155
|
+
: allInstalled
|
|
156
|
+
? `installed (${skillCount}/${managed.length} SDTK-OPS skills)`
|
|
157
|
+
: `partial (${skillCount}/${managed.length} SDTK-OPS skills)`;
|
|
158
|
+
|
|
159
|
+
console.log(` Scope: ${scope}`);
|
|
160
|
+
console.log(` Path: ${skillsDir}`);
|
|
161
|
+
console.log(` Status: ${status}`);
|
|
162
|
+
if (exists && hasManagedSkills && skillCount < managed.length) {
|
|
163
|
+
const missing = managed.filter((name) => !installedNames.includes(name));
|
|
164
|
+
console.log(` Missing: ${missing.join(", ")}`);
|
|
165
|
+
}
|
|
166
|
+
console.log("");
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return 0;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async function cmdRuntime(args) {
|
|
173
|
+
const { flags, positional } = parseFlags(args, FLAG_DEFS);
|
|
174
|
+
const subcommand = positional[0];
|
|
175
|
+
|
|
176
|
+
if (!subcommand) {
|
|
177
|
+
throw new ValidationError(
|
|
178
|
+
`Missing subcommand. Usage: sdtk-ops runtime <${SUBCOMMANDS.join("|")}> [options]`
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
if (!SUBCOMMANDS.includes(subcommand)) {
|
|
182
|
+
throw new ValidationError(
|
|
183
|
+
`Unknown subcommand: "${subcommand}". Must be one of: ${SUBCOMMANDS.join(", ")}`
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
switch (subcommand) {
|
|
188
|
+
case "install":
|
|
189
|
+
return cmdRuntimeInstall(flags);
|
|
190
|
+
case "uninstall":
|
|
191
|
+
return cmdRuntimeUninstall(flags);
|
|
192
|
+
case "status":
|
|
193
|
+
return cmdRuntimeStatus(flags);
|
|
194
|
+
default:
|
|
195
|
+
throw new ValidationError(`Unsupported runtime subcommand: "${subcommand}".`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
module.exports = {
|
|
200
|
+
cmdRuntime,
|
|
201
|
+
};
|
package/src/index.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { cmdHelp } = require("./commands/help");
|
|
4
|
+
const { cmdInit } = require("./commands/init");
|
|
5
|
+
const { cmdRuntime } = require("./commands/runtime");
|
|
6
|
+
const { ValidationError } = require("./lib/errors");
|
|
7
|
+
|
|
8
|
+
const COMMANDS = new Set(["help", "version", "init", "runtime"]);
|
|
9
|
+
|
|
10
|
+
function getVersion() {
|
|
11
|
+
const pkg = require("../package.json");
|
|
12
|
+
return pkg.version;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function parseCommand(argv) {
|
|
16
|
+
if (!argv || argv.length === 0) {
|
|
17
|
+
return { command: "help", args: [] };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const [first, ...rest] = argv;
|
|
21
|
+
if (first === "-h" || first === "--help") {
|
|
22
|
+
return { command: "help", args: [] };
|
|
23
|
+
}
|
|
24
|
+
if (first === "-v" || first === "--version") {
|
|
25
|
+
return { command: "version", args: [] };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return { command: first, args: rest };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function run(argv) {
|
|
32
|
+
const { command, args } = parseCommand(argv);
|
|
33
|
+
|
|
34
|
+
if (command === "generate") {
|
|
35
|
+
throw new ValidationError(
|
|
36
|
+
'The "generate" command is not part of the supported SDTK-OPS workflow-entry surface. Supported commands: help, init, runtime. If the correct journey is unclear, start with the "ops-discover" skill.'
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!COMMANDS.has(command)) {
|
|
41
|
+
throw new ValidationError(
|
|
42
|
+
`Unknown command: "${command}". Run "sdtk-ops --help" for available commands.`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
switch (command) {
|
|
47
|
+
case "help":
|
|
48
|
+
return cmdHelp();
|
|
49
|
+
case "version":
|
|
50
|
+
console.log(`sdtk-ops-kit ${getVersion()}`);
|
|
51
|
+
return 0;
|
|
52
|
+
case "init":
|
|
53
|
+
return cmdInit(args);
|
|
54
|
+
case "runtime":
|
|
55
|
+
return cmdRuntime(args);
|
|
56
|
+
default:
|
|
57
|
+
throw new ValidationError(`Unsupported command: "${command}".`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = {
|
|
62
|
+
getVersion,
|
|
63
|
+
parseCommand,
|
|
64
|
+
run,
|
|
65
|
+
};
|