@stackwright-pro/otters 1.0.0-alpha.5 → 1.0.0-alpha.51
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/LICENSE +21 -0
- package/README.md +7 -6
- package/package.json +7 -6
- package/scripts/generate-checksums.js +0 -1
- package/scripts/install-agents.js +5 -2
- package/scripts/launch-raft.cjs +13 -0
- package/scripts/strip-artifact-schemas.cjs +133 -0
- package/src/checksums.json +14 -8
- package/src/stackwright-pro-api-otter.json +47 -96
- package/src/stackwright-pro-auth-otter.json +26 -791
- package/src/stackwright-pro-dashboard-otter.json +22 -662
- package/src/stackwright-pro-data-otter.json +21 -535
- package/src/stackwright-pro-designer-otter.json +15 -21
- package/src/stackwright-pro-domain-expert-otter.json +20 -0
- package/src/stackwright-pro-foreman-otter.json +25 -653
- package/src/stackwright-pro-geo-otter.json +41 -0
- package/src/stackwright-pro-page-otter.json +8 -4
- package/src/stackwright-pro-polish-otter.json +41 -0
- package/src/stackwright-pro-scaffold-otter.json +24 -0
- package/src/stackwright-pro-theme-otter.json +28 -0
- package/src/stackwright-pro-workflow-otter.json +28 -0
- package/src/stackwright-services-otter-system.md +192 -0
- package/src/stackwright-services-otter.json +43 -0
- package/src/python-bridge.ts +0 -391
- package/src/question-adapter.ts +0 -296
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
PROPRIETARY SOFTWARE LICENSE
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 Per Aspera LLC. All Rights Reserved.
|
|
4
|
+
|
|
5
|
+
This software and associated documentation files (the "Software") are the
|
|
6
|
+
proprietary and confidential property of Per Aspera LLC ("Company").
|
|
7
|
+
|
|
8
|
+
RESTRICTIONS: You may not use, copy, modify, merge, publish, distribute,
|
|
9
|
+
sublicense, sell, or otherwise exploit this Software or any portion thereof
|
|
10
|
+
without the express prior written consent of the Company.
|
|
11
|
+
|
|
12
|
+
GOVERNMENT USE: Use, duplication, or disclosure by the U.S. Government is
|
|
13
|
+
subject to restrictions as set forth in FAR 52.227-19 (Commercial Computer
|
|
14
|
+
Software - Restricted Rights) and DFARS 252.227-7013 (Rights in Technical
|
|
15
|
+
Data and Computer Software), as applicable.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED. IN NO EVENT SHALL THE COMPANY BE LIABLE FOR ANY CLAIM, DAMAGES, OR
|
|
19
|
+
OTHER LIABILITY ARISING FROM THE USE OF THE SOFTWARE.
|
|
20
|
+
|
|
21
|
+
For licensing inquiries: legal@peraspera.com
|
package/README.md
CHANGED
|
@@ -118,12 +118,13 @@ When Pro otters combine with the OSS raft, these capabilities emerge:
|
|
|
118
118
|
|
|
119
119
|
## The Pro Otter Raft
|
|
120
120
|
|
|
121
|
-
| Otter
|
|
122
|
-
|
|
|
123
|
-
| 🦦🦦 **Foreman Otter**
|
|
124
|
-
| 🦦📡 **API Otter**
|
|
125
|
-
| 🦦📊 **Dashboard Otter**
|
|
126
|
-
| 🦦🔗 **Data Otter**
|
|
121
|
+
| Otter | Role | Output |
|
|
122
|
+
| ------------------------------------- | -------------------- | ------------------------------------------------------------------------------- |
|
|
123
|
+
| 🦦🦦 **Foreman Otter** | Project coordinator | Orchestrates full-stack builds (delegates to unified Foreman) |
|
|
124
|
+
| 🦦📡 **API Otter** | OpenAPI discovery | API entity types, endpoints |
|
|
125
|
+
| 🦦📊 **Dashboard Otter** | Live data views | Typed API components |
|
|
126
|
+
| 🦦🔗 **Data Otter** | Endpoint integration | ISR config, filters |
|
|
127
|
+
| `stackwright-pro-domain-expert-otter` | Utility | Answers specialist questions from the use case document in non-interactive mode |
|
|
127
128
|
|
|
128
129
|
---
|
|
129
130
|
|
package/package.json
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackwright-pro/otters",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.51",
|
|
4
4
|
"description": "Stackwright Pro Otter Raft - AI agents for enterprise features (CAC auth, API dashboards, government use cases)",
|
|
5
|
-
"license": "
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/Per-Aspera-LLC/stackwright-pro"
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
|
-
"vitest": "^4.
|
|
12
|
-
"zod": "^
|
|
11
|
+
"vitest": "^4.1.8",
|
|
12
|
+
"zod": "^4.4.3"
|
|
13
13
|
},
|
|
14
14
|
"exports": {
|
|
15
15
|
"./src": "./src",
|
|
16
|
-
"./pro-foreman": "./src/stackwright-pro-foreman-otter.json"
|
|
16
|
+
"./pro-foreman": "./src/stackwright-pro-foreman-otter.json",
|
|
17
|
+
"./pro-workflow": "./src/stackwright-pro-workflow-otter.json"
|
|
17
18
|
},
|
|
18
19
|
"files": [
|
|
19
20
|
"scripts",
|
|
@@ -23,7 +24,7 @@
|
|
|
23
24
|
"access": "public"
|
|
24
25
|
},
|
|
25
26
|
"peerDependencies": {
|
|
26
|
-
"@stackwright-pro/mcp": "^0.2.0-alpha.
|
|
27
|
+
"@stackwright-pro/mcp": "^0.2.0-alpha.80"
|
|
27
28
|
},
|
|
28
29
|
"scripts": {
|
|
29
30
|
"generate-checksums": "node scripts/generate-checksums.js",
|
|
@@ -8,14 +8,17 @@ const fs = require('fs');
|
|
|
8
8
|
const path = require('path');
|
|
9
9
|
const os = require('os');
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
// Allow test overrides via env vars — production paths are the default.
|
|
12
|
+
// STACKWRIGHT_AGENTS_DIR: override destination (normally ~/.code_puppy/agents/)
|
|
13
|
+
// STACKWRIGHT_OTTERS_SRC_DIR: override source (normally <package>/src/)
|
|
14
|
+
const AGENTS_DIR = process.env.STACKWRIGHT_AGENTS_DIR || path.join(os.homedir(), '.code_puppy', 'agents');
|
|
12
15
|
|
|
13
16
|
// Resolve package root relative to this script's location
|
|
14
17
|
const scriptDir = __dirname;
|
|
15
18
|
const packageRoot = path.resolve(scriptDir, '..');
|
|
16
19
|
|
|
17
20
|
// All Pro otters are in the src/ directory
|
|
18
|
-
const srcDir = path.join(packageRoot, 'src');
|
|
21
|
+
const srcDir = process.env.STACKWRIGHT_OTTERS_SRC_DIR || path.join(packageRoot, 'src');
|
|
19
22
|
|
|
20
23
|
async function installAgents() {
|
|
21
24
|
try {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// ⚠️ DEPRECATED — This launcher has been replaced by @stackwright-pro/raft.
|
|
4
|
+
// Run: npx @stackwright-pro/raft
|
|
5
|
+
// This file is kept for users who may have cached a previous install.
|
|
6
|
+
// It will be removed in a future release.
|
|
7
|
+
|
|
8
|
+
console.error('⚠️ launch-raft in @stackwright-pro/otters is deprecated.');
|
|
9
|
+
console.error(' Use: npx @stackwright-pro/raft');
|
|
10
|
+
console.error('');
|
|
11
|
+
console.error(' Install: npm install -g @stackwright-pro/raft');
|
|
12
|
+
console.error(' Or run directly: npx @stackwright-pro/raft');
|
|
13
|
+
process.exit(1);
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* strip-artifact-schemas.cjs
|
|
4
|
+
*
|
|
5
|
+
* Removes hardcoded artifact schema JSON blocks from specialist otter system_prompts.
|
|
6
|
+
* These are now injected dynamically via build_specialist_prompt (REQUIRED_ARTIFACT_SCHEMA).
|
|
7
|
+
*
|
|
8
|
+
* Run: node packages/otters/scripts/strip-artifact-schemas.cjs
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
const OTTERS_DIR = path.join(__dirname, '..', 'src');
|
|
15
|
+
const REFERENCE_LINE =
|
|
16
|
+
'**Artifact shape:** See the **REQUIRED_ARTIFACT_SCHEMA** section in your prompt for the canonical artifact shape. Use it when calling `stackwright_pro_validate_artifact`.';
|
|
17
|
+
|
|
18
|
+
function stripArtifactSchemaFromArray(promptArray) {
|
|
19
|
+
// Strategy: find the index of the ```json opening fence,
|
|
20
|
+
// then find the matching closing ``` fence.
|
|
21
|
+
// Replace everything from the fence through the closing fence + surrounding context
|
|
22
|
+
// with the REFERENCE_LINE.
|
|
23
|
+
|
|
24
|
+
const result = [];
|
|
25
|
+
let i = 0;
|
|
26
|
+
let stripped = false;
|
|
27
|
+
|
|
28
|
+
while (i < promptArray.length) {
|
|
29
|
+
const item = promptArray[i];
|
|
30
|
+
|
|
31
|
+
// Detect start of a JSON code block fence
|
|
32
|
+
if (typeof item === 'string' && item.trim() === '```json') {
|
|
33
|
+
// Find the closing fence
|
|
34
|
+
let j = i + 1;
|
|
35
|
+
while (j < promptArray.length && promptArray[j].trim() !== '```') {
|
|
36
|
+
j++;
|
|
37
|
+
}
|
|
38
|
+
// j now points to the closing ``` (or end of array)
|
|
39
|
+
|
|
40
|
+
// Replace this entire block with the reference line
|
|
41
|
+
// (but only the first JSON block per otter — the artifact schema block)
|
|
42
|
+
if (!stripped) {
|
|
43
|
+
result.push(REFERENCE_LINE);
|
|
44
|
+
stripped = true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Skip past the closing fence
|
|
48
|
+
i = j + 1;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
result.push(item);
|
|
53
|
+
i++;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function stripArtifactSchemaFromString(str) {
|
|
60
|
+
// For cases where the schema is embedded in a longer string as a ```json...``` block
|
|
61
|
+
// Replace the first ```json ... ``` block with the reference line
|
|
62
|
+
const jsonFenceRegex = /```json[\s\S]*?```/;
|
|
63
|
+
if (jsonFenceRegex.test(str)) {
|
|
64
|
+
return str.replace(jsonFenceRegex, REFERENCE_LINE);
|
|
65
|
+
}
|
|
66
|
+
return str;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function processOtterFile(filePath) {
|
|
70
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
71
|
+
const otter = JSON.parse(raw);
|
|
72
|
+
|
|
73
|
+
if (!Array.isArray(otter.system_prompt)) {
|
|
74
|
+
console.log(` ⚠️ ${path.basename(filePath)}: system_prompt is not an array — skipping`);
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Check if the artifact schema block is spread across array elements (```json as its own element)
|
|
79
|
+
// or embedded within a longer string
|
|
80
|
+
const hasFenceAsElement = otter.system_prompt.some(
|
|
81
|
+
(s) => typeof s === 'string' && s.trim() === '```json'
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const hasEmbeddedFence = otter.system_prompt.some(
|
|
85
|
+
(s) => typeof s === 'string' && s.includes('```json')
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
let modified = false;
|
|
89
|
+
|
|
90
|
+
if (hasFenceAsElement) {
|
|
91
|
+
// Multi-element block — strip using array strategy
|
|
92
|
+
const original = JSON.stringify(otter.system_prompt);
|
|
93
|
+
otter.system_prompt = stripArtifactSchemaFromArray(otter.system_prompt);
|
|
94
|
+
if (JSON.stringify(otter.system_prompt) !== original) {
|
|
95
|
+
modified = true;
|
|
96
|
+
}
|
|
97
|
+
} else if (hasEmbeddedFence) {
|
|
98
|
+
// Embedded fence within a string — strip using string replacement
|
|
99
|
+
const original = JSON.stringify(otter.system_prompt);
|
|
100
|
+
otter.system_prompt = otter.system_prompt.map((s) =>
|
|
101
|
+
typeof s === 'string' ? stripArtifactSchemaFromString(s) : s
|
|
102
|
+
);
|
|
103
|
+
if (JSON.stringify(otter.system_prompt) !== original) {
|
|
104
|
+
modified = true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (modified) {
|
|
109
|
+
fs.writeFileSync(filePath, JSON.stringify(otter, null, 2) + '\n');
|
|
110
|
+
console.log(` ✅ ${path.basename(filePath)}: artifact schema block removed`);
|
|
111
|
+
} else {
|
|
112
|
+
console.log(
|
|
113
|
+
` ℹ️ ${path.basename(filePath)}: no artifact schema block found (may already be clean)`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return modified;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
console.log('Stripping hardcoded artifact schema blocks from specialist otters...\n');
|
|
121
|
+
|
|
122
|
+
const otterFiles = fs
|
|
123
|
+
.readdirSync(OTTERS_DIR)
|
|
124
|
+
.filter((f) => f.endsWith('-otter.json') && f !== 'stackwright-pro-foreman-otter.json')
|
|
125
|
+
.map((f) => path.join(OTTERS_DIR, f));
|
|
126
|
+
|
|
127
|
+
let totalModified = 0;
|
|
128
|
+
for (const filePath of otterFiles) {
|
|
129
|
+
const modified = processOtterFile(filePath);
|
|
130
|
+
if (modified) totalModified++;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
console.log(`\nDone. ${totalModified} otter file(s) modified.`);
|
package/src/checksums.json
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "1.0",
|
|
3
3
|
"algorithm": "sha256",
|
|
4
|
-
"generated": "2026-04-16T15:06:40.061Z",
|
|
5
4
|
"files": {
|
|
6
|
-
"stackwright-pro-api-otter.json": "
|
|
7
|
-
"stackwright-pro-auth-otter.json": "
|
|
8
|
-
"stackwright-pro-dashboard-otter.json": "
|
|
9
|
-
"stackwright-pro-data-otter.json": "
|
|
10
|
-
"stackwright-pro-designer-otter.json": "
|
|
11
|
-
"stackwright-pro-
|
|
12
|
-
"stackwright-pro-
|
|
5
|
+
"stackwright-pro-api-otter.json": "1610b34c2bfd89aa18ef62fe052fe5aaba21cb2aa9c5d58a4fff06af2a1f0e6e",
|
|
6
|
+
"stackwright-pro-auth-otter.json": "5a876d3614e62a7817e69bbe7fe7cc6976035ccaa0e7c29fb1e1a32caf8cea93",
|
|
7
|
+
"stackwright-pro-dashboard-otter.json": "9550e565fb467d7956cf6b50e7b30a481e6e4b26d609dfe1f0d8f991fc6681de",
|
|
8
|
+
"stackwright-pro-data-otter.json": "5cd8caca50bfcc00ebaf1f9a83158e5580e0e51d25495244f8465d9c20f31e17",
|
|
9
|
+
"stackwright-pro-designer-otter.json": "d44b307299c2b65568a708920b819eec7d3b5fe1191ace24b166cbfb2d6e5209",
|
|
10
|
+
"stackwright-pro-domain-expert-otter.json": "dc060aacdf67ee5758921c72225aa669a76cb962f0f8eedf1741f58f18e870d3",
|
|
11
|
+
"stackwright-pro-foreman-otter.json": "ab3d821d9217ccbe112d68ce25798bfe637aef15814168037caa2a98994e8d2d",
|
|
12
|
+
"stackwright-pro-geo-otter.json": "3c9fc96e79d9ac22be8a293cf3ec904c4ed033842864107515aacdf71285791c",
|
|
13
|
+
"stackwright-pro-page-otter.json": "0057ea97f7c2e33a8673140f59a0237eb627d82c676af3fae4faa31033598e03",
|
|
14
|
+
"stackwright-pro-polish-otter.json": "1e534dfbc5644a5efbc566d77b512929760715365d54ce030da177a535c23ea6",
|
|
15
|
+
"stackwright-pro-scaffold-otter.json": "2ed0adb316aaecb849153d44f52b177de539f21d4a7ce5ae4cc1c3c7470e15d4",
|
|
16
|
+
"stackwright-pro-theme-otter.json": "730bc16b24b4612552389fe9de662f233044bcbf5ef1e0f27f2cc1e1af4c989f",
|
|
17
|
+
"stackwright-pro-workflow-otter.json": "8ece2a1f1ec30163600b5ce8b666c915ab0d00a1fa70c38ed58d1bb20cbd9979",
|
|
18
|
+
"stackwright-services-otter.json": "2a36a07eaf34b59a2dab7059f3748a5742ff1f6b80b4bd6a739c59cf114703d6"
|
|
13
19
|
}
|
|
14
20
|
}
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "pro-api-otter-001",
|
|
3
3
|
"name": "stackwright-pro-api-otter",
|
|
4
|
-
"display_name": "Stackwright Pro API Otter
|
|
4
|
+
"display_name": "Stackwright Pro API Otter \ud83e\udda6",
|
|
5
5
|
"description": "Analyzes API specs and extracts entity definitions",
|
|
6
|
-
"tools": [
|
|
7
|
-
|
|
6
|
+
"tools": [
|
|
7
|
+
"agent_run_shell_command",
|
|
8
|
+
"list_files",
|
|
9
|
+
"cp_list_files",
|
|
10
|
+
"cp_read_file",
|
|
11
|
+
"stackwright_pro_write_phase_questions",
|
|
12
|
+
"stackwright_pro_validate_artifact"
|
|
13
|
+
],
|
|
14
|
+
"user_prompt": "Hey! \ud83e\udda6 I'm the API Otter. Give me an OpenAPI spec path and I'll extract what entities and endpoints it exposes.",
|
|
8
15
|
"system_prompt": [
|
|
9
16
|
"## YOUR JOB",
|
|
10
17
|
"Analyze API specs. Extract entities, schemas, and endpoints.",
|
|
@@ -14,47 +21,23 @@
|
|
|
14
21
|
"- GraphQL schemas",
|
|
15
22
|
"- AsyncAPI (Kafka events)",
|
|
16
23
|
"",
|
|
24
|
+
"## EXTERNAL $REF DETECTION\n\nAfter reading a spec file (Step 2), scan for external $ref URLs:\n\n**Detection rule:** If any `$ref` value in the spec starts with `http://` or `https://` (e.g., `$ref: \"https://hl7.org/fhir/R4/fhir.schema.json#/definitions/Patient\"`), the spec has external references that need bundling.\n\n**When external $refs are detected:**\n1. Add a `warnings` array to your artifact with one entry:\n ```\n \"warnings\": [\"Spec contains external $ref URLs \u2014 recommend bundle: true in stackwright.yml integration config\"]\n ```\n2. Still extract entities normally from the spec's `paths` and `components`\n3. Note the external ref domains in your reasoning (e.g., \"References hl7.org FHIR schemas\")\n\n**Common external $ref patterns:**\n- FHIR: `https://hl7.org/fhir/R4/fhir.schema.json#/definitions/...`\n- JSON Schema: `https://json-schema.org/draft/...`\n- External spec fragments: `https://api.example.com/schemas/...`\n\nThe Data Otter will use this warning to set `bundle: true` on the integration in `stackwright.yml`, which tells the prebuild pipeline to run `SwaggerParser.bundle()` to resolve external refs before parsing.",
|
|
25
|
+
"",
|
|
17
26
|
"## YOUR WORKFLOW",
|
|
18
27
|
"1. Accept spec path from user or find in project",
|
|
19
28
|
"2. Parse spec file (use cp_read_file for local, curl for URLs)",
|
|
20
29
|
"3. Extract: endpoints, schemas, auth requirements",
|
|
21
30
|
"4. List available entities for user selection",
|
|
22
31
|
"",
|
|
32
|
+
"## ASYNCAPI DETECTION\n\nAfter reading a spec file (Step 2), check for AsyncAPI format BEFORE extracting entities:\n\n**Detection rule:** If the parsed YAML/JSON root object contains an `asyncapi` key (e.g. `asyncapi: '2.6.0'` or `asyncapi: '3.0.0'`), OR contains a `channels` key but NO `paths` key \u2014 it is an AsyncAPI spec, not OpenAPI.\n\n**When an AsyncAPI spec is detected:**\n1. Do NOT extract REST entities from `channels` \u2014 channels are event/message definitions, not REST endpoints\n2. Set `entities: []` (empty array)\n3. Add a `skipped` array to the artifact with one entry per skipped spec:\n ```\n \"skipped\": [{\n \"spec\": \"<filename>\",\n \"format\": \"asyncapi\",\n \"reason\": \"AsyncAPI spec \u2014 WebSocket/event integration required (no REST endpoints)\"\n }]\n ```\n4. Still extract `auth` and `baseUrl` if present in the spec (they apply to any protocol)\n5. Still call `stackwright_pro_validate_artifact` normally with this artifact\n\n**If ALL specs provided are AsyncAPI:** `entities` MUST be `[]`. Never fabricate REST endpoints from channel definitions \u2014 those would 404 at runtime.\n\n**If SOME specs are OpenAPI and some AsyncAPI:** Extract entities from the OpenAPI specs normally. Add each AsyncAPI spec to `skipped[]`. The artifact will have both `entities` (from OpenAPI) and `skipped` (from AsyncAPI).",
|
|
33
|
+
"",
|
|
23
34
|
"## OUTPUT FORMAT",
|
|
24
35
|
"",
|
|
25
|
-
"**
|
|
26
|
-
"",
|
|
27
|
-
"Return ONLY valid JSON \u2014 no markdown fences, no prose, no comments. Use one of these two shapes:",
|
|
28
|
-
"",
|
|
29
|
-
"SUCCESS SHAPE:",
|
|
30
|
-
"```json",
|
|
31
|
-
"{",
|
|
32
|
-
" \"entities\": [",
|
|
33
|
-
" {",
|
|
34
|
-
" \"name\": \"Shipment\",",
|
|
35
|
-
" \"endpoint\": \"/shipments\",",
|
|
36
|
-
" \"method\": \"GET\",",
|
|
37
|
-
" \"revalidate\": 60,",
|
|
38
|
-
" \"mutationType\": null",
|
|
39
|
-
" }",
|
|
40
|
-
" ],",
|
|
41
|
-
" \"auth\": {",
|
|
42
|
-
" \"type\": \"bearer\",",
|
|
43
|
-
" \"header\": \"Authorization\",",
|
|
44
|
-
" \"envVar\": \"MARINE_LOGISTICS_API_TOKEN\"",
|
|
45
|
-
" },",
|
|
46
|
-
" \"baseUrl\": \"https://api.marine-logistics.mil/v2\",",
|
|
47
|
-
" \"specPath\": \"./specs/marine-combat-logistics.yaml\"",
|
|
48
|
-
"}",
|
|
49
|
-
"```",
|
|
36
|
+
"**Parse the spec, then call `stackwright_pro_validate_artifact` directly as your final step.**",
|
|
50
37
|
"",
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
" \"error\": \"Spec file not found at ./specs/missing.yaml\",",
|
|
55
|
-
" \"specPath\": \"./specs/missing.yaml\"",
|
|
56
|
-
"}",
|
|
57
|
-
"```",
|
|
38
|
+
"Artifact shape (fill all fields with real values from the spec \u2014 never leave placeholders):",
|
|
39
|
+
"",
|
|
40
|
+
"**Artifact shape:** See the **REQUIRED_ARTIFACT_SCHEMA** section in your prompt for the canonical artifact shape. Use it when calling `stackwright_pro_validate_artifact`.",
|
|
58
41
|
"",
|
|
59
42
|
"Field notes:",
|
|
60
43
|
"- entities[].revalidate: seconds for ISR cache (from x-revalidate extension), or null",
|
|
@@ -62,27 +45,46 @@
|
|
|
62
45
|
"- auth.type: one of \"none\" | \"api-key\" | \"bearer\" | \"oauth2\" | \"cac\"",
|
|
63
46
|
" (cac = DoD Common Access Card / PKI certificate authentication)",
|
|
64
47
|
"- auth.envVar: environment variable name that will hold the credential",
|
|
48
|
+
"- skipped[]: array of specs that were detected as non-REST (AsyncAPI/WebSocket). Each entry has spec (filename), format, and reason. Empty array or omitted if all specs are OpenAPI.",
|
|
49
|
+
"- warnings[]: optional array of advisory strings. Add one entry when external $ref URLs are detected (see EXTERNAL $REF DETECTION above). Omit entirely when no warnings apply.",
|
|
50
|
+
"",
|
|
51
|
+
"If the spec is missing, unreadable, or unsupported format \u2014 respond: `\u26d4 ARTIFACT_ERROR: spec-unavailable \u2014 [reason]` and do not call validate_artifact.",
|
|
52
|
+
"",
|
|
53
|
+
"Call:",
|
|
54
|
+
"```",
|
|
55
|
+
"stackwright_pro_validate_artifact({",
|
|
56
|
+
" phase: \"api\",",
|
|
57
|
+
" artifact: { version, generatedBy, entities, skipped, warnings, auth, baseUrl, specPath }",
|
|
58
|
+
"})",
|
|
59
|
+
"```",
|
|
60
|
+
"",
|
|
61
|
+
"- If `valid: true` \u2192 respond: `\u2705 ARTIFACT_WRITTEN: <artifactPath from result>`",
|
|
62
|
+
"- If `valid: false` \u2192 read the `retryPrompt` field, correct the artifact, and retry the call once.",
|
|
63
|
+
"- If still `valid: false` after retry \u2192 respond: `\u26d4 ARTIFACT_ERROR: [violation] \u2014 [retryPrompt text]`",
|
|
64
|
+
"",
|
|
65
|
+
"**Never return JSON as your response body.** The Foreman no longer calls `validate_artifact` \u2014 you call it directly.",
|
|
65
66
|
"",
|
|
66
67
|
"---",
|
|
67
68
|
"",
|
|
68
69
|
"## SCOPE BOUNDARIES",
|
|
69
70
|
"",
|
|
70
|
-
"
|
|
71
|
+
"\u2705 **You DO:**",
|
|
71
72
|
"- Read and parse OpenAPI/GraphQL/AsyncAPI specs",
|
|
72
73
|
"- Extract entity names, endpoint paths, auth schemes, and base URLs",
|
|
73
74
|
"- Return a structured JSON artifact to the Foreman",
|
|
74
75
|
"",
|
|
75
|
-
"
|
|
76
|
+
"\u274c **You DON'T:**",
|
|
76
77
|
"- Create any files (no .ts, no .js, no .json files on disk)",
|
|
77
78
|
"- Write TypeScript types, interfaces, or classes",
|
|
78
79
|
"- Write Zod schemas",
|
|
79
80
|
"- Generate API client classes (BaseApiClient, etc.)",
|
|
80
81
|
"- Write to src/generated/ or any other directory",
|
|
81
82
|
"",
|
|
83
|
+
"\u2705 Call `stackwright_pro_validate_artifact({ phase: \"api\", artifact })` directly as your final write step.",
|
|
84
|
+
"",
|
|
82
85
|
"**WHY:** TypeScript type generation is @stackwright-pro/openapi's job at build time.",
|
|
83
|
-
"The otter's job is discovery and configuration
|
|
84
|
-
"If you find yourself
|
|
85
|
-
"Return your JSON artifact to the Foreman instead.",
|
|
86
|
+
"The otter's job is discovery and configuration \u2014 not code generation.",
|
|
87
|
+
"You have no other file-write tools. If you find yourself constructing a file path or file content to write, STOP \u2014 call `stackwright_pro_validate_artifact` with your artifact object instead.",
|
|
86
88
|
"---",
|
|
87
89
|
"",
|
|
88
90
|
"## TERMINATION",
|
|
@@ -98,61 +100,10 @@
|
|
|
98
100
|
"",
|
|
99
101
|
"## QUESTION_COLLECTION_MODE",
|
|
100
102
|
"",
|
|
101
|
-
"
|
|
102
|
-
"",
|
|
103
|
-
"
|
|
104
|
-
"",
|
|
105
|
-
"
|
|
106
|
-
"",
|
|
107
|
-
"{",
|
|
108
|
-
" \"questions\": [",
|
|
109
|
-
" {",
|
|
110
|
-
" \"id\": \"api-1\",",
|
|
111
|
-
" \"question\": \"Do you have an existing OpenAPI spec?\",",
|
|
112
|
-
" \"type\": \"confirm\",",
|
|
113
|
-
" \"required\": true,",
|
|
114
|
-
" \"default\": \"no\"",
|
|
115
|
-
" },",
|
|
116
|
-
" {",
|
|
117
|
-
" \"id\": \"api-2\",",
|
|
118
|
-
" \"question\": \"What is the URL or path to your OpenAPI spec?\",",
|
|
119
|
-
" \"type\": \"text\",",
|
|
120
|
-
" \"required\": true,",
|
|
121
|
-
" \"dependsOn\": { \"questionId\": \"api-1\", \"value\": \"yes\" }",
|
|
122
|
-
" },",
|
|
123
|
-
" {",
|
|
124
|
-
" \"id\": \"api-3\",",
|
|
125
|
-
" \"question\": \"What is your API authentication method?\",",
|
|
126
|
-
" \"type\": \"select\",",
|
|
127
|
-
" \"options\": [",
|
|
128
|
-
" { \"label\": \"No auth\", \"value\": \"none\" },",
|
|
129
|
-
" { \"label\": \"API Key\", \"value\": \"api-key\" },",
|
|
130
|
-
" { \"label\": \"OAuth2\", \"value\": \"oauth2\" },",
|
|
131
|
-
" { \"label\": \"OIDC/SAML\", \"value\": \"oidc\" },",
|
|
132
|
-
" { \"label\": \"CAC/PIV (DoD)\", \"value\": \"cac\" }",
|
|
133
|
-
" ],",
|
|
134
|
-
" \"required\": true",
|
|
135
|
-
" },",
|
|
136
|
-
" {",
|
|
137
|
-
" \"id\": \"api-4\",",
|
|
138
|
-
" \"question\": \"Which entities from the spec do you need?\",",
|
|
139
|
-
" \"type\": \"multi-select\",",
|
|
140
|
-
" \"options\": [",
|
|
141
|
-
" { \"label\": \"I will tell you after you parse it\", \"value\": \"discover\" }",
|
|
142
|
-
" ],",
|
|
143
|
-
" \"required\": false,",
|
|
144
|
-
" \"help\": \"You can select specific entities or let me discover them after parsing the spec.\"",
|
|
145
|
-
" }",
|
|
146
|
-
" ],",
|
|
147
|
-
" \"requiredPackages\": {",
|
|
148
|
-
" \"dependencies\": {",
|
|
149
|
-
" \"@stackwright-pro/openapi\": \"latest\",",
|
|
150
|
-
" \"zod\": \"^3.23.0\"",
|
|
151
|
-
" },",
|
|
152
|
-
" \"devPackages\": {",
|
|
153
|
-
" \"@stoplight/prism-cli\": \"^5.14.2\"",
|
|
154
|
-
" }",
|
|
155
|
-
" }",
|
|
156
|
-
"}"
|
|
103
|
+
"\u26a0\ufe0f GUARD: Only enter QUESTION_COLLECTION_MODE if the prompt contains the literal string `QUESTION_COLLECTION_MODE=true`. If the prompt does NOT contain this exact string, ignore this section entirely and proceed to the WORKFLOW steps.",
|
|
104
|
+
"",
|
|
105
|
+
"When the prompt contains `QUESTION_COLLECTION_MODE=true`:\n\n1. Check for a `BUILD_CONTEXT:` section in the prompt. If present, read the user's build description and use it to tailor your questions \u2014 adjust wording, pre-fill obvious defaults, or skip questions whose answers are already clearly implied.\n2. Check for a `PRIOR_ANSWERS:` section in the prompt. If present, use prior phase answers to inform your questions \u2014 if an earlier phase already captured relevant information, prefer asking more targeted follow-up questions instead of redundant generic ones.\n3. Prefer **replacing** generic questions with specific contextual ones \u2014 do not append more questions on top of the defaults. Keep the total question count similar to the standard set.\n4. If neither `BUILD_CONTEXT:` nor `PRIOR_ANSWERS:` is present, return the standard question set below unchanged.\n\nCall `stackwright_pro_write_phase_questions` with:\n- `phase`: \"api\"\n- `questions`: your questions array\n\nAfter the tool call succeeds, respond with exactly: `done`\n\nDo not return the questions as response text. Do not call any other tools.",
|
|
106
|
+
"",
|
|
107
|
+
"{\n \"questions\": [\n {\n \"id\": \"api-1\",\n \"question\": \"Does your app pull live data from a backend service your IT team set up?\",\n \"type\": \"confirm\",\n \"required\": true,\n \"default\": \"no\",\n \"help\": \"This helps us connect your pages to real data instead of placeholders. If unsure, ask your IT team if there is an API or data service involved.\"\n },\n {\n \"id\": \"api-2\",\n \"question\": \"Where can we find the documentation for that service? (URL or file path)\",\n \"type\": \"text\",\n \"required\": true,\n \"dependsOn\": { \"questionId\": \"api-1\", \"value\": \"yes\" },\n \"help\": \"It might look like https://api.yourcompany.com/docs or a local file path like ./specs/service.yaml \u2014 your IT team would know.\"\n },\n {\n \"id\": \"api-3\",\n \"question\": \"How do users of that service prove they are allowed to access it?\",\n \"type\": \"select\",\n \"options\": [\n { \"label\": \"No login required \u2014 open access\", \"value\": \"none\" },\n { \"label\": \"Secret key (your IT team provides one)\", \"value\": \"api-key\" },\n { \"label\": \"Company single sign-on (Microsoft, Okta, etc.)\", \"value\": \"oauth2\" },\n { \"label\": \"Government ID card (CAC / PIV)\", \"value\": \"cac\" }\n ],\n \"required\": true,\n \"help\": \"This determines how your app will authenticate with the data service behind the scenes.\"\n },\n {\n \"id\": \"api-4\",\n \"question\": \"What kinds of information do you want to display? (e.g. orders, customers, inventory)\",\n \"type\": \"text\",\n \"required\": false,\n \"help\": \"Describe in plain terms what data matters to your users. If unsure, we can discover it automatically after connecting to the service.\"\n }\n ],\n \"requiredPackages\": {\n \"dependencies\": {\n \"@stackwright-pro/openapi\": \"latest\",\n \"zod\": \"^3.23.0\"\n },\n \"devPackages\": {\n \"@stoplight/prism-cli\": \"^5.14.2\"\n }\n }\n}"
|
|
157
108
|
]
|
|
158
109
|
}
|