abelworkflow 1.0.0-rc.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -8
- package/extensions/pi-gpt-responses-compat/index.ts +1 -1
- package/lib/cli/args.mjs +2 -2
- package/lib/cli/main.mjs +39 -41
- package/lib/cli/prompts.mjs +16 -29
- package/lib/installer/assets.mjs +13 -15
- package/lib/installer/install.mjs +18 -32
- package/lib/installer/state.mjs +0 -19
- package/lib/providers/claude.mjs +23 -214
- package/lib/providers/codex.mjs +14 -22
- package/lib/providers/pi.mjs +273 -58
- package/lib/providers/skills.mjs +39 -88
- package/lib/templates/workflow/AGENTS.md +10 -10
- package/lib/templates/workflow/commands/abel-design.md +175 -0
- package/lib/templates/workflow/commands/abel-implement.md +64 -46
- package/lib/templates/workflow/commands/abel-init.md +2 -4
- package/package.json +1 -7
- package/skills/grok-search/.env.example +3 -3
- package/skills/grok-search/SKILL.md +1 -1
- package/skills/grok-search/defaults.json +1 -1
- package/skills/grok-search/scripts/groksearch_cli.py +42 -15
- package/skills/prompt-enhancer/SKILL.md +2 -27
- package/lib/installer/render.mjs +0 -46
- package/lib/templates/workflow/commands/abel-plan.md +0 -82
- package/lib/templates/workflow/commands/abel-research.md +0 -126
- package/skills/prompt-enhancer/.env.example +0 -12
- package/skills/prompt-enhancer/ADVANCED.md +0 -103
- package/skills/prompt-enhancer/requirements.txt +0 -1
- package/skills/prompt-enhancer/scripts/_dotenv.py +0 -32
- package/skills/prompt-enhancer/scripts/enhance.py +0 -144
- package/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py +0 -238
|
@@ -24,7 +24,7 @@ Use this skill for web search, webpage retrieval, and current-information lookup
|
|
|
24
24
|
```bash
|
|
25
25
|
cp "<SKILL_DIR>/.env.example" "<SKILL_DIR>/.env"
|
|
26
26
|
|
|
27
|
-
python "<SKILL_DIR>/scripts/groksearch_entry.py" web_search --query "search terms" [--platform "GitHub"] [--min-results 3] [--max-results 10] [--model "grok-4.20-
|
|
27
|
+
python "<SKILL_DIR>/scripts/groksearch_entry.py" web_search --query "search terms" [--platform "GitHub"] [--min-results 3] [--max-results 10] [--model "grok-4.20-non-reasoning"] [--extra-sources 3]
|
|
28
28
|
|
|
29
29
|
python "<SKILL_DIR>/scripts/groksearch_entry.py" web_fetch --url "https://..." [--out file.md] [--fallback-grok]
|
|
30
30
|
|
|
@@ -216,7 +216,17 @@ def _emit_tavily_warning(message: str) -> None:
|
|
|
216
216
|
RETRYABLE_STATUS_CODES = {408, 429, 500, 502, 503, 504}
|
|
217
217
|
|
|
218
218
|
|
|
219
|
+
class StreamEmbeddedError(Exception):
|
|
220
|
+
"""SSE 流内嵌错误事件(HTTP 200 + data: {"error": ...})。"""
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
class EmptyStreamError(Exception):
|
|
224
|
+
"""流式响应解析完成但内容为空。"""
|
|
225
|
+
|
|
226
|
+
|
|
219
227
|
def _is_retryable_exception(exc) -> bool:
|
|
228
|
+
if isinstance(exc, (StreamEmbeddedError, EmptyStreamError)):
|
|
229
|
+
return True
|
|
220
230
|
if isinstance(exc, (httpx.TimeoutException, httpx.NetworkError, httpx.ConnectError, httpx.RemoteProtocolError)):
|
|
221
231
|
return True
|
|
222
232
|
if isinstance(exc, httpx.HTTPStatusError):
|
|
@@ -501,6 +511,7 @@ def _normalize_tavily_base_url(raw: str) -> str:
|
|
|
501
511
|
|
|
502
512
|
_http_client: Optional[httpx.AsyncClient] = None
|
|
503
513
|
_DEFAULT_TIMEOUT = httpx.Timeout(connect=6.0, read=60.0, write=10.0, pool=None)
|
|
514
|
+
_NON_STREAM_TIMEOUT = httpx.Timeout(connect=6.0, read=10.0, write=10.0, pool=None)
|
|
504
515
|
|
|
505
516
|
|
|
506
517
|
async def get_http_client() -> httpx.AsyncClient:
|
|
@@ -586,16 +597,23 @@ class GrokSearchProvider:
|
|
|
586
597
|
return await self._execute(payload)
|
|
587
598
|
|
|
588
599
|
async def _execute(self, payload: dict) -> str:
|
|
589
|
-
"""
|
|
600
|
+
"""执行请求:流式优先,失败时回退到非流式(10s 超时 fail-fast)。"""
|
|
590
601
|
try:
|
|
602
|
+
return await self._execute_stream(payload)
|
|
603
|
+
except httpx.HTTPStatusError as e:
|
|
604
|
+
if e.response.status_code not in RETRYABLE_STATUS_CODES:
|
|
605
|
+
raise
|
|
606
|
+
if config.debug_enabled:
|
|
607
|
+
print(f"[DEBUG] 流式失败: {e},回退到非流式", file=sys.stderr)
|
|
591
608
|
return await self._execute_non_stream(payload)
|
|
592
|
-
except (httpx.
|
|
609
|
+
except (httpx.TimeoutException, httpx.NetworkError, httpx.RemoteProtocolError,
|
|
610
|
+
StreamEmbeddedError, EmptyStreamError, json.JSONDecodeError) as e:
|
|
593
611
|
if config.debug_enabled:
|
|
594
|
-
print(f"[DEBUG]
|
|
595
|
-
return await self.
|
|
612
|
+
print(f"[DEBUG] 流式失败: {e},回退到非流式", file=sys.stderr)
|
|
613
|
+
return await self._execute_non_stream(payload)
|
|
596
614
|
|
|
597
615
|
async def _execute_non_stream(self, payload: dict) -> str:
|
|
598
|
-
"""
|
|
616
|
+
"""非流式请求(流式失败后的回退方案,10s read 超时 fail-fast)。"""
|
|
599
617
|
payload_copy = {**payload, "stream": False}
|
|
600
618
|
client = await get_http_client()
|
|
601
619
|
|
|
@@ -610,6 +628,7 @@ class GrokSearchProvider:
|
|
|
610
628
|
f"{self.api_url}/chat/completions",
|
|
611
629
|
headers=self._headers,
|
|
612
630
|
json=payload_copy,
|
|
631
|
+
timeout=_NON_STREAM_TIMEOUT,
|
|
613
632
|
)
|
|
614
633
|
response.raise_for_status()
|
|
615
634
|
data = response.json()
|
|
@@ -619,7 +638,7 @@ class GrokSearchProvider:
|
|
|
619
638
|
return ""
|
|
620
639
|
|
|
621
640
|
async def _execute_stream(self, payload: dict) -> str:
|
|
622
|
-
"""
|
|
641
|
+
"""流式请求(首选,chunk 保活避免网关超时)。"""
|
|
623
642
|
payload_copy = {**payload, "stream": True}
|
|
624
643
|
client = await get_http_client()
|
|
625
644
|
|
|
@@ -655,24 +674,30 @@ class GrokSearchProvider:
|
|
|
655
674
|
try:
|
|
656
675
|
json_str = line[5:].lstrip()
|
|
657
676
|
data = json.loads(json_str)
|
|
658
|
-
choices = data.get("choices", [])
|
|
659
|
-
if choices:
|
|
660
|
-
delta = choices[0].get("delta", {})
|
|
661
|
-
if "content" in delta:
|
|
662
|
-
content += delta["content"]
|
|
663
677
|
except (json.JSONDecodeError, IndexError):
|
|
664
678
|
continue
|
|
679
|
+
if isinstance(data, dict) and "error" in data:
|
|
680
|
+
raise StreamEmbeddedError(json.dumps(data["error"], ensure_ascii=False)[:300])
|
|
681
|
+
choices = data.get("choices", [])
|
|
682
|
+
if choices:
|
|
683
|
+
delta = choices[0].get("delta", {})
|
|
684
|
+
if "content" in delta:
|
|
685
|
+
content += delta["content"]
|
|
665
686
|
|
|
666
687
|
if not content and full_body_buffer:
|
|
667
688
|
try:
|
|
668
689
|
full_text = "".join(full_body_buffer)
|
|
669
690
|
data = json.loads(full_text)
|
|
691
|
+
if isinstance(data, dict) and "error" in data:
|
|
692
|
+
raise StreamEmbeddedError(json.dumps(data["error"], ensure_ascii=False)[:300])
|
|
670
693
|
if "choices" in data and data["choices"]:
|
|
671
694
|
message = data["choices"][0].get("message", {})
|
|
672
695
|
content = message.get("content", "")
|
|
673
696
|
except json.JSONDecodeError:
|
|
674
697
|
pass
|
|
675
698
|
|
|
699
|
+
if not content.strip():
|
|
700
|
+
raise EmptyStreamError("流式响应内容为空")
|
|
676
701
|
return content
|
|
677
702
|
|
|
678
703
|
|
|
@@ -935,8 +960,9 @@ async def cmd_web_search(args):
|
|
|
935
960
|
except ValueError as e:
|
|
936
961
|
print(json.dumps({"error": str(e)}, ensure_ascii=False), file=sys.stderr)
|
|
937
962
|
sys.exit(1)
|
|
938
|
-
except httpx.
|
|
939
|
-
|
|
963
|
+
except httpx.HTTPError as e:
|
|
964
|
+
detail = str(e.response.status_code) if isinstance(e, httpx.HTTPStatusError) else (str(e) or type(e).__name__)
|
|
965
|
+
print(json.dumps({"error": f"API错误: {detail}"}, ensure_ascii=False), file=sys.stderr)
|
|
940
966
|
sys.exit(1)
|
|
941
967
|
|
|
942
968
|
|
|
@@ -974,8 +1000,9 @@ async def cmd_web_fetch(args):
|
|
|
974
1000
|
except ValueError as e:
|
|
975
1001
|
print(f"错误: {e}", file=sys.stderr)
|
|
976
1002
|
sys.exit(1)
|
|
977
|
-
except httpx.
|
|
978
|
-
|
|
1003
|
+
except httpx.HTTPError as e:
|
|
1004
|
+
detail = str(e.response.status_code) if isinstance(e, httpx.HTTPStatusError) else (str(e) or type(e).__name__)
|
|
1005
|
+
print(f"API错误: {detail}", file=sys.stderr)
|
|
979
1006
|
sys.exit(1)
|
|
980
1007
|
|
|
981
1008
|
if not result and tavily_error and not use_grok_fallback:
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
name: prompt-enhancer
|
|
3
3
|
description: |
|
|
4
4
|
Rewrite a raw prompt into a clearer prompt for a coding agent. Use only when the user explicitly asks to improve, optimize, rewrite, or structure a prompt for Codex, Claude Code, Gemini CLI, or another AI agent. Triggers: "improve this prompt", "rewrite this prompt", "optimize this prompt for Codex", "make this prompt better for an AI agent".
|
|
5
|
-
allowed-tools: Bash(python:*), Bash(python3:*), Bash(uv:*), Read, Grep
|
|
6
5
|
---
|
|
7
6
|
|
|
8
7
|
# Prompt Enhancer
|
|
@@ -19,31 +18,7 @@ Do not use this for general writing edits like email, docs, or PR copy.
|
|
|
19
18
|
|
|
20
19
|
## Do
|
|
21
20
|
|
|
22
|
-
-
|
|
23
|
-
- Third-party path: use the Python entrypoint only when the user explicitly provides `url`, `apiKey`, and `model`, or when all three are already configured in `<SKILL_DIR>/.env`.
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "user's raw prompt here"
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
- Do not call `scripts/enhance.py` directly.
|
|
30
|
-
- Use the installed skill directory for `<SKILL_DIR>`.
|
|
31
|
-
- If any of `url`, `apiKey`, or `model` is missing, do not invoke the script. Use the current agent directly instead.
|
|
32
|
-
- Optional setup: `cp "<SKILL_DIR>/.env.example" "<SKILL_DIR>/.env"`
|
|
33
|
-
|
|
34
|
-
## Output
|
|
35
|
-
|
|
36
|
-
- Read the enhanced prompt from `stdout`.
|
|
37
|
-
- Keep `stderr` for usage or optional debug output only.
|
|
21
|
+
- Rewrite the prompt directly with the current agent, following the structure from [TEMPLATE.md](TEMPLATE.md).
|
|
38
22
|
- Preserve the user's intent and explicit constraints.
|
|
39
23
|
- Add structure and missing execution context only when it helps the agent act.
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
## Notes
|
|
43
|
-
|
|
44
|
-
- Local config file: `<SKILL_DIR>/.env`
|
|
45
|
-
- The entrypoint auto-loads `<SKILL_DIR>/.env` before bootstrap and dependency install.
|
|
46
|
-
- Optional debug flag: `PE_DEBUG=1`
|
|
47
|
-
- Bootstrap controls: `PROMPT_ENHANCER_VENV_DIR`, `PROMPT_ENHANCER_PYTHON`, `AGENTS_SKILLS_PYTHON`
|
|
48
|
-
- Setup and troubleshooting: [ADVANCED.md](ADVANCED.md)
|
|
49
|
-
- Prompt template reference: [TEMPLATE.md](TEMPLATE.md)
|
|
24
|
+
- Use placeholders for unknown context instead of inventing new requirements.
|
package/lib/installer/render.mjs
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
const augmentContextEngineRetrievalTool = "mcp__augment-context-engine__codebase-retrieval";
|
|
2
|
-
const localCodebaseRetrievalPolicy = "Use local codebase retrieval with `rg`, `rg --files`, `git grep`, and direct file reads. Do not require augment-context-engine MCP.";
|
|
3
|
-
const augmentCodebaseRetrievalPolicy = `Use \`${augmentContextEngineRetrievalTool}\` as the primary codebase search tool.`;
|
|
4
|
-
|
|
5
|
-
function resolveAugmentContextEngineFeature(options = {}, previousMetadata = {}) {
|
|
6
|
-
if (typeof options.augmentContextEngine === "boolean") return options.augmentContextEngine;
|
|
7
|
-
if (typeof previousMetadata?.features?.augmentContextEngine === "boolean") {
|
|
8
|
-
return previousMetadata.features.augmentContextEngine;
|
|
9
|
-
}
|
|
10
|
-
return false;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function getWorkflowRenderValues(augmentContextEngine) {
|
|
14
|
-
return {
|
|
15
|
-
CODEBASE_RETRIEVAL_POLICY: augmentContextEngine ? augmentCodebaseRetrievalPolicy : localCodebaseRetrievalPolicy,
|
|
16
|
-
AUGMENT_CONTEXT_ENGINE_VALIDATION: augmentContextEngine
|
|
17
|
-
? `Verify MCP availability:\n - \`${augmentContextEngineRetrievalTool}\``
|
|
18
|
-
: "Skip augment-context-engine MCP validation; use local retrieval tools.",
|
|
19
|
-
CODEBASE_RETRIEVAL_MANDATORY_RULE: augmentContextEngine
|
|
20
|
-
? `Mandatory use of \`${augmentContextEngineRetrievalTool}\``
|
|
21
|
-
: "Mandatory use of configured codebase retrieval policy.",
|
|
22
|
-
CODEBASE_RETRIEVAL_STRUCTURE_REFERENCE: augmentContextEngine
|
|
23
|
-
? `Inspect codebase structure: \`${augmentContextEngineRetrievalTool}\` with \`file list --recursive\`.`
|
|
24
|
-
: "Inspect codebase structure with `rg --files`, `git grep`, and direct file reads.",
|
|
25
|
-
CODEBASE_RETRIEVAL_PATTERN_AUDIT: augmentContextEngine
|
|
26
|
-
? `Use augment-context-engine to validate against existing codebase patterns.\n ${augmentContextEngineRetrievalTool}: "Search for existing implementations similar to change <change_name>. Keywords: [key concepts from proposal]"`
|
|
27
|
-
: "Use `rg`, `rg --files`, `git grep`, and direct file reads to validate against existing codebase patterns."
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function renderWorkflowTemplate(content, { augmentContextEngine = false } = {}) {
|
|
32
|
-
let nextContent = content;
|
|
33
|
-
for (const [key, value] of Object.entries(getWorkflowRenderValues(augmentContextEngine))) {
|
|
34
|
-
nextContent = nextContent.replaceAll(`{{${key}}}`, value);
|
|
35
|
-
}
|
|
36
|
-
if (nextContent.includes("{{") || nextContent.includes("}}")) {
|
|
37
|
-
throw new Error("工作流模板包含未解析占位符");
|
|
38
|
-
}
|
|
39
|
-
return nextContent;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export {
|
|
43
|
-
getWorkflowRenderValues,
|
|
44
|
-
renderWorkflowTemplate,
|
|
45
|
-
resolveAugmentContextEngineFeature
|
|
46
|
-
};
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: abel-plan
|
|
3
|
-
description: Refine approved change into a zero-decision executable plan.
|
|
4
|
-
category: abel
|
|
5
|
-
tags: [abel, plan, PBT]
|
|
6
|
-
argument-hint: [change_name]
|
|
7
|
-
---
|
|
8
|
-
<!-- ABEL:START -->
|
|
9
|
-
**Guardrails**
|
|
10
|
-
- Strictly adhere to **OpenSpec** rules when writing **standardized spec-structured projects**.
|
|
11
|
-
- The goal of this phase is to eliminate ALL decision points from the task flow—implementation should be pure mechanical execution.
|
|
12
|
-
- Do not proceed to implementation until every ambiguity is resolved and every constraint is explicitly documented.
|
|
13
|
-
- Every requirement must have Property-Based Testing (PBT) properties defined—focus on invariants, not just example-based tests.
|
|
14
|
-
- If constraints cannot be fully specified, escalate back to the user or return to the research phase rather than making assumptions.
|
|
15
|
-
- Refer to `openspec/AGENTS.md` for additional conventions; run `openspec update` if the file is missing.
|
|
16
|
-
|
|
17
|
-
**Skill Integration**: See `Stage Skill Matrix` (Plan column)
|
|
18
|
-
|
|
19
|
-
**FORBIDDEN**: Direct implementation code generation
|
|
20
|
-
|
|
21
|
-
**Steps**
|
|
22
|
-
1. Run `openspec view` to display all **Active Changes**, then confirm with the user which change folder (`<change_name>`) they wish to refine into a zero-decision plan.
|
|
23
|
-
|
|
24
|
-
2. Navigate to `openspec/changes/<change_name>/` and review existing artifacts:
|
|
25
|
-
- Check `openspec status --change <change_name>` for artifact completion
|
|
26
|
-
- Use `openspec instructions specs --change <change_name>` for specs guidance
|
|
27
|
-
|
|
28
|
-
3. **Implementation Analysis**: Perform systematic analysis to derive a plan. If the proposal has 3+ interconnected requirements, first break it down into components, identify dependencies, evaluate architectural trade-offs, and surface potential conflicts. Then invoke `/context7-auto-research` to validate framework/library choices:
|
|
29
|
-
```
|
|
30
|
-
/context7-auto-research: "For each technology mentioned in change <change_name>, retrieve official documentation patterns and best practices."
|
|
31
|
-
```
|
|
32
|
-
Produce a consolidated, constraint-complete plan and list any missing constraints as questions to the user.
|
|
33
|
-
|
|
34
|
-
4. **Uncertainty Elimination Audit**: Invoke skills to detect and eliminate remaining ambiguities:
|
|
35
|
-
```
|
|
36
|
-
# First, validate against existing codebase patterns
|
|
37
|
-
{{CODEBASE_RETRIEVAL_PATTERN_AUDIT}}
|
|
38
|
-
# Then audit for ambiguities directly and list them explicitly
|
|
39
|
-
Review change <change_name> for decision points that remain unspecified. For each: [AMBIGUITY] <description> → [REQUIRED CONSTRAINT] <what must be specified>.
|
|
40
|
-
Identify implicit assumptions in change <change_name>. For each: [ASSUMPTION] <description> → [EXPLICIT CONSTRAINT NEEDED] <concrete specification>.
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
**Anti-Pattern Detection** (flag and reject):
|
|
44
|
-
- Information collection without decision boundaries (e.g., "JWT vs OAuth2 vs session—all viable")
|
|
45
|
-
- Technical comparisons without selection criteria
|
|
46
|
-
- Deferred decisions marked as "to be determined during implementation"
|
|
47
|
-
|
|
48
|
-
**Target Pattern** (required for approval):
|
|
49
|
-
- Explicit technology choices with parameters (e.g., "JWT with accessToken TTL=15min, refreshToken TTL=7days")
|
|
50
|
-
- Concrete algorithm selections with configurations (e.g., "bcrypt with cost factor=12")
|
|
51
|
-
- Precise behavioral rules (e.g., "Lock account for 30min after 5 failed login attempts")
|
|
52
|
-
|
|
53
|
-
Iterate with user until ALL ambiguities are resolved into explicit constraints.
|
|
54
|
-
|
|
55
|
-
5. **PBT Property Extraction**: Invoke skills to derive testable invariants:
|
|
56
|
-
```
|
|
57
|
-
"Extract Property-Based Testing properties from change <change_name>. For each requirement: [INVARIANT] <must always hold> → [FALSIFICATION STRATEGY] <how to generate counterexamples>."
|
|
58
|
-
"Define system properties for change <change_name>: [PROPERTY] <name> | [DEFINITION] <formal description> | [BOUNDARY CONDITIONS] <edge cases> | [COUNTEREXAMPLE GENERATION] <approach>."
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
**PBT Property Categories to Extract**:
|
|
62
|
-
- **Commutativity/Associativity**: Order-independent operations
|
|
63
|
-
- **Idempotency**: Repeated operations yield same result
|
|
64
|
-
- **Round-trip**: Encode→Decode returns original
|
|
65
|
-
- **Invariant Preservation**: State constraints maintained across operations
|
|
66
|
-
- **Monotonicity**: Ordering guarantees (e.g., timestamps always increase)
|
|
67
|
-
- **Bounds**: Value ranges, size limits, rate constraints
|
|
68
|
-
|
|
69
|
-
**Reference**
|
|
70
|
-
- Use `openspec show <change_name> --json --deltas-only` to inspect proposal structure when validation fails.
|
|
71
|
-
- Use `openspec list --specs` to check for conflicts with existing specifications.
|
|
72
|
-
- Search existing patterns with `rg -n "INVARIANT:|PROPERTY:|Constraint:" openspec/` before defining new ones.
|
|
73
|
-
- For complex proposals, consider running steps 2-4 iteratively on sub-components.
|
|
74
|
-
- Ask the user directly for ANY ambiguity—do not assume or guess.
|
|
75
|
-
|
|
76
|
-
**Exit Criteria**
|
|
77
|
-
A proposal is ready to exit the Plan phase only when:
|
|
78
|
-
- [ ] Zero ambiguities remain (verified by step 4 audit)
|
|
79
|
-
- [ ] All PBT properties documented with falsification strategies
|
|
80
|
-
- [ ] `openspec validate <change_name> --strict` returns zero issues
|
|
81
|
-
- [ ] User has explicitly approved all constraint decisions
|
|
82
|
-
<!-- ABEL:END -->
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: abel-research
|
|
3
|
-
description: Transform user requirements into constraint sets via structured exploration (NO implementation)
|
|
4
|
-
category: abel
|
|
5
|
-
tags: [abel, research, constraints, exploration, subagents]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
<!-- ABEL:RESEARCH:START -->
|
|
9
|
-
|
|
10
|
-
# abel-research — Operating Mode (Constraints & Specs Only)
|
|
11
|
-
|
|
12
|
-
## Non‑Negotiable Rules (Highest Priority)
|
|
13
|
-
1. RESEARCH MODE ONLY.
|
|
14
|
-
- You MUST NOT generate code.
|
|
15
|
-
2. WRITE SCOPE IS RESTRICTED.
|
|
16
|
-
- You MAY create/edit files ONLY under: openspec/changes/<change-name>/** (and only after passing the confirmation gates).
|
|
17
|
-
- You MUST NOT write anywhere else.
|
|
18
|
-
3. Output must be constraint sets + verifiable success criteria, not an information dump.
|
|
19
|
-
|
|
20
|
-
## Goal
|
|
21
|
-
Produce constraint sets that narrow the solution space, plus measurable success criteria.
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
## Phase 0 — Requirement Intake Gate (MANDATORY)
|
|
28
|
-
- **MUST** confirm the user’s requirement exists and is clear **before** any research/action.
|
|
29
|
-
- If missing/unclear, **MUST** ask the user directly in a concise grouped message to collect: goal, in-scope area, top scenarios, non-goals, known constraints, success signals.
|
|
30
|
-
- **MUST NOT** run `/opsx:new`, any codebase retrieval, spawn subagents, or generate artifacts until the user confirms a brief requirement summary.
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## Phase 1 — Initialize OpenSpec Change Folder
|
|
35
|
-
1) Run: /opsx:new <change-name>
|
|
36
|
-
2) From now on, you may write ONLY under openspec/changes/<change-name>/**.
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
## Phase 2 — Initial Codebase Assessment (Read‑Only)
|
|
41
|
-
- {{CODEBASE_RETRIEVAL_POLICY}}
|
|
42
|
-
- If technical research needed (architectural patterns, best practices), invoke `/grok-search` skill
|
|
43
|
-
- If the codebase spans multiple modules/directories, dispatch parallel explore subagents by context boundary.
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## Phase 3 — Define Exploration Boundaries (Context-Based Division Only)
|
|
48
|
-
- Identify natural context boundaries in the codebase (NOT functional roles).
|
|
49
|
-
- Example divisions:
|
|
50
|
-
* Subagent 1: User domain code (user models, user services, user UI)
|
|
51
|
-
* Subagent 2: Authentication & authorization code (auth middleware, session, tokens)
|
|
52
|
-
* Subagent 3: Configuration & infrastructure (configs, deployments, build scripts)
|
|
53
|
-
- Each boundary should be self-contained: no cross-communication needed between subagents.
|
|
54
|
-
- Define exploration scope and expected output for each subagent.
|
|
55
|
-
|
|
56
|
-
---
|
|
57
|
-
|
|
58
|
-
## Phase 4 — Subagent Output Template (MANDATORY JSON)
|
|
59
|
-
All explore subagents MUST return valid JSON using this schema:
|
|
60
|
-
{
|
|
61
|
-
"module_name": "字符串 - 所探索的上下文边界",
|
|
62
|
-
"existing_structures": ["发现的关键结构/模式列表"],
|
|
63
|
-
"existing_conventions": ["当前使用的约定/标准列表"],
|
|
64
|
-
"constraints_discovered": ["限制解决方案空间的硬约束列表"],
|
|
65
|
-
"open_questions": ["需要用户输入的歧义问题列表"],
|
|
66
|
-
"dependencies": ["对其他模块/系统的依赖列表"],
|
|
67
|
-
"risks": ["潜在风险或阻碍列表"],
|
|
68
|
-
"success_criteria_hints": ["指示成功的可观察行为列表"]
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
---
|
|
72
|
-
|
|
73
|
-
## Phase 5 — Parallel Subagent Dispatch
|
|
74
|
-
- Monitor subagent execution and collect structured reports.
|
|
75
|
-
- For each boundary, spawn an Explore subagent with:
|
|
76
|
-
- {{CODEBASE_RETRIEVAL_MANDATORY_RULE}}
|
|
77
|
-
- Clear scope
|
|
78
|
-
- self-contained with independent output
|
|
79
|
-
- Required output template (from Phase 4)
|
|
80
|
-
- If boundary involves 3+ interconnected components, require explicit step-by-step dependency analysis
|
|
81
|
-
- Clear success criteria: complete analysis of assigned boundary
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
## Phase 6 — Aggregate & Synthesize
|
|
87
|
-
- Collect all subagent JSON outputs.
|
|
88
|
-
- Merge findings into unified constraint sets:
|
|
89
|
-
* **Hard constraints**: Technical limitations, existing patterns that cannot be violated.
|
|
90
|
-
* **Soft constraints**: Conventions, preferences, style guides.
|
|
91
|
-
* **Dependencies**: Cross-module relationships that affect implementation order.
|
|
92
|
-
* **Risks**: Potential blockers that need mitigation.
|
|
93
|
-
- Identify **open questions** from all reports that require user clarification.
|
|
94
|
-
- Synthesize **success criteria** from scenario hints across all contexts.
|
|
95
|
-
|
|
96
|
-
---
|
|
97
|
-
|
|
98
|
-
## Phase 7 — User Interaction for Ambiguity Resolution
|
|
99
|
-
- Compile prioritized list of open questions from aggregated reports.
|
|
100
|
-
- Present questions directly to the user in a concise grouped message:
|
|
101
|
-
* Group related questions together.
|
|
102
|
-
* Provide context for each question.
|
|
103
|
-
* Suggest default answers when applicable.
|
|
104
|
-
- Capture user responses as additional constraints.
|
|
105
|
-
- Update constraint sets with confirmed decisions.
|
|
106
|
-
|
|
107
|
-
---
|
|
108
|
-
|
|
109
|
-
## Phase 8 — Generate OpenSpec Artifacts
|
|
110
|
-
- Transform finalized constraint sets into OpenSpec proposal/specs/design/tasks.
|
|
111
|
-
- Every requirement MUST have a verifiable scenario and success criteria.
|
|
112
|
-
- Keep all writes inside openspec/changes/<change-name>/**.
|
|
113
|
-
|
|
114
|
-
## Reference
|
|
115
|
-
- Review existing constraints: `rg -n "Constraint:|MUST|MUST NOT" openspec/specs`
|
|
116
|
-
- {{CODEBASE_RETRIEVAL_STRUCTURE_REFERENCE}}
|
|
117
|
-
|
|
118
|
-
- Check prior research outputs: `ls openspec/changes/*/`
|
|
119
|
-
- OpenSpec CLI commands:
|
|
120
|
-
- `openspec view` - Interactive dashboard to browse changes
|
|
121
|
-
- `openspec list --changes` - List all active changes
|
|
122
|
-
- `openspec status --change <name>` - Check artifact completion status
|
|
123
|
-
- `openspec instructions proposal --change <name>` - Get proposal instructions
|
|
124
|
-
- Validate subagent outputs conform to template before aggregation.
|
|
125
|
-
- Ask the user directly for ANY ambiguity—do not assume or guess.
|
|
126
|
-
<!-- ABEL:RESEARCH:END -->
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# Prompt Enhancer CLI configuration
|
|
2
|
-
# Copy this file to .env and fill in the values you want to use.
|
|
3
|
-
|
|
4
|
-
# Optional: third-party OpenAI-compatible base URL
|
|
5
|
-
PE_API_URL=
|
|
6
|
-
|
|
7
|
-
# Optional: third-party OpenAI-compatible API key
|
|
8
|
-
PE_API_KEY=
|
|
9
|
-
|
|
10
|
-
# Optional: model name for the third-party endpoint
|
|
11
|
-
# Leave all three fields blank to use the current agent directly.
|
|
12
|
-
PE_MODEL=
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
# Advanced Usage
|
|
2
|
-
|
|
3
|
-
## Using the Python Script Directly
|
|
4
|
-
|
|
5
|
-
Use the bootstrap entrypoint from the installed skill directory:
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
# Assuming third-party config is already set in <SKILL_DIR>/.env or the environment
|
|
9
|
-
python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "your prompt here"
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
`prompt_enhancer_entry.py` is the canonical entrypoint. It creates or reuses a skill-local virtual environment and then runs `scripts/enhance.py`.
|
|
13
|
-
If `PE_API_URL`, `PE_API_KEY`, and `PE_MODEL` are not all present, do not call the script; rewrite the prompt directly with the current agent instead.
|
|
14
|
-
|
|
15
|
-
## Environment Variables
|
|
16
|
-
|
|
17
|
-
| Variable | Description | Default |
|
|
18
|
-
|----------|-------------|---------|
|
|
19
|
-
| `PE_API_URL` | Third-party OpenAI-compatible base URL | - |
|
|
20
|
-
| `PE_API_KEY` | Third-party OpenAI-compatible API key | - |
|
|
21
|
-
| `PE_MODEL` | Model to use on the third-party endpoint | - |
|
|
22
|
-
| `PE_DEBUG` | Print bootstrap and fallback diagnostics to `stderr` | `0` |
|
|
23
|
-
| `PROMPT_ENHANCER_VENV_DIR` | Override the skill-local venv path | `skills/prompt-enhancer/.venv` |
|
|
24
|
-
| `PROMPT_ENHANCER_PYTHON` | Python version/spec for `uv venv --python` | - |
|
|
25
|
-
| `AGENTS_SKILLS_PYTHON` | Absolute path to fallback/bootstrap Python | - |
|
|
26
|
-
|
|
27
|
-
## Local `.env`
|
|
28
|
-
|
|
29
|
-
The CLI loads `<SKILL_DIR>/.env` automatically if present:
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
cp "<SKILL_DIR>/.env.example" "<SKILL_DIR>/.env"
|
|
33
|
-
python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "your prompt here"
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## Integration with Other Tools
|
|
37
|
-
|
|
38
|
-
The enhanced prompt is written to `stdout`. Usage or debug diagnostics stay on `stderr`, and bootstrap/fallback diagnostics are only emitted when `PE_DEBUG=1`.
|
|
39
|
-
|
|
40
|
-
### Piping Output
|
|
41
|
-
|
|
42
|
-
Assuming `PE_API_URL`, `PE_API_KEY`, and `PE_MODEL` are already configured:
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
# Pipe to clipboard (macOS)
|
|
46
|
-
python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "my prompt" | pbcopy
|
|
47
|
-
|
|
48
|
-
# Pipe to file
|
|
49
|
-
python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "my prompt" > enhanced.md
|
|
50
|
-
|
|
51
|
-
# Chain with other commands
|
|
52
|
-
python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "my prompt" | claude -p
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### In Shell Scripts
|
|
56
|
-
|
|
57
|
-
Assuming the environment is already configured:
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
#!/bin/bash
|
|
61
|
-
ENHANCED=$(python "$HOME/.agents/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py" "$1")
|
|
62
|
-
echo "$ENHANCED"
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Manual Enhancement (Current Agent)
|
|
66
|
-
|
|
67
|
-
If the user does not provide `url`, `apiKey`, and `model`, use the current agent directly and apply the enhancement principles:
|
|
68
|
-
|
|
69
|
-
1. Read the user's prompt
|
|
70
|
-
2. Apply the template from [TEMPLATE.md](TEMPLATE.md)
|
|
71
|
-
3. Preserve every explicit user constraint
|
|
72
|
-
4. Use placeholders for unknown context instead of inventing requirements
|
|
73
|
-
5. Structure the output with:
|
|
74
|
-
- Context section
|
|
75
|
-
- Objective section
|
|
76
|
-
- Step-by-step instructions
|
|
77
|
-
- Constraints
|
|
78
|
-
|
|
79
|
-
## Troubleshooting
|
|
80
|
-
|
|
81
|
-
### Script Not Found
|
|
82
|
-
Verify the canonical entrypoint exists:
|
|
83
|
-
```bash
|
|
84
|
-
ls "$HOME/.agents/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py"
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### Permission Denied
|
|
88
|
-
Run it through Python instead of executing the file directly:
|
|
89
|
-
```bash
|
|
90
|
-
python "$HOME/.agents/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py" "your prompt here"
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
### Show Usage
|
|
94
|
-
Run the entrypoint without a prompt to print usage information:
|
|
95
|
-
```bash
|
|
96
|
-
python "$HOME/.agents/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py"
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### Missing Third-Party Config
|
|
100
|
-
The script requires `PE_API_URL`, `PE_API_KEY`, and `PE_MODEL`. If any field is missing, skip the script and use the current agent directly.
|
|
101
|
-
|
|
102
|
-
### Debug Fallbacks
|
|
103
|
-
Set `PE_DEBUG=1` to show dependency-install or configuration diagnostics on `stderr`.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
openai>=1.30,<2
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
"""Shared .env loader for Prompt Enhancer scripts."""
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def load_dotenv() -> bool:
|
|
8
|
-
env_path = Path(__file__).resolve().parent.parent / ".env"
|
|
9
|
-
if not env_path.exists():
|
|
10
|
-
return False
|
|
11
|
-
try:
|
|
12
|
-
seen_keys = set()
|
|
13
|
-
with open(env_path, "r", encoding="utf-8") as f:
|
|
14
|
-
for line in f:
|
|
15
|
-
line = line.strip()
|
|
16
|
-
if not line or line.startswith("#") or "=" not in line:
|
|
17
|
-
continue
|
|
18
|
-
key, _, value = line.partition("=")
|
|
19
|
-
key = key.strip()
|
|
20
|
-
value = value.strip()
|
|
21
|
-
if (value.startswith('"') and value.endswith('"')) or (
|
|
22
|
-
value.startswith("'") and value.endswith("'")
|
|
23
|
-
):
|
|
24
|
-
value = value[1:-1]
|
|
25
|
-
if not key or key in seen_keys:
|
|
26
|
-
continue
|
|
27
|
-
seen_keys.add(key)
|
|
28
|
-
if not os.environ.get(key):
|
|
29
|
-
os.environ[key] = value
|
|
30
|
-
return True
|
|
31
|
-
except IOError:
|
|
32
|
-
return False
|