aw-spec-cli 0.1.0 → 0.1.1
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/assets/.agents/skills/aw-spec-addcomponent/SKILL.md +116 -0
- package/assets/.agents/skills/aw-spec-agent-context-update/SKILL.md +31 -0
- package/assets/.agents/skills/aw-spec-analyze/SKILL.md +292 -0
- package/assets/.agents/skills/aw-spec-checklist/SKILL.md +374 -0
- package/assets/.agents/skills/aw-spec-clarify/SKILL.md +316 -0
- package/assets/.agents/skills/aw-spec-constitution/SKILL.md +190 -0
- package/assets/.agents/skills/aw-spec-foundation/SKILL.md +188 -0
- package/assets/.agents/skills/aw-spec-implement/SKILL.md +268 -0
- package/assets/.agents/skills/aw-spec-plan/SKILL.md +217 -0
- package/assets/.agents/skills/aw-spec-select-domain/SKILL.md +73 -0
- package/assets/.agents/skills/aw-spec-specify/SKILL.md +378 -0
- package/assets/.agents/skills/aw-spec-tasks/SKILL.md +255 -0
- package/assets/.agents/skills/aw-spec-taskstoissues/SKILL.md +107 -0
- package/assets/.aw-spec/domain.json +3 -0
- package/assets/.aw-spec/extensions/.registry +19 -0
- package/assets/.aw-spec/extensions/agent-context/README.md +57 -0
- package/assets/.aw-spec/extensions/agent-context/agent-context-config.yml +4 -0
- package/assets/.aw-spec/extensions/agent-context/commands/aw-spec.agent-context.update.md +26 -0
- package/assets/.aw-spec/extensions/agent-context/extension.yml +34 -0
- package/assets/.aw-spec/extensions/agent-context/scripts/bash/update-agent-context.sh +201 -0
- package/assets/.aw-spec/extensions/agent-context/scripts/powershell/update-agent-context.ps1 +237 -0
- package/assets/.aw-spec/extensions.yml +23 -0
- package/assets/.aw-spec/feature.json +3 -0
- package/assets/.aw-spec/init-options.json +9 -0
- package/assets/.aw-spec/integration.json +15 -0
- package/assets/.aw-spec/integrations/aw-spec.manifest.json +17 -0
- package/assets/.aw-spec/integrations/claude.manifest.json +17 -0
- package/assets/.aw-spec/memory/constitution.md +50 -0
- package/assets/.aw-spec/scripts/bash/check-prerequisites.sh +189 -0
- package/assets/.aw-spec/scripts/bash/common.sh +582 -0
- package/assets/.aw-spec/scripts/bash/create-new-feature.sh +299 -0
- package/assets/.aw-spec/scripts/bash/setup-plan.sh +84 -0
- package/assets/.aw-spec/scripts/bash/setup-tasks.sh +91 -0
- package/assets/.aw-spec/templates/checklist-template.md +40 -0
- package/assets/.aw-spec/templates/constitution-template.md +57 -0
- package/assets/.aw-spec/templates/plan-template.md +113 -0
- package/assets/.aw-spec/templates/spec-template.md +131 -0
- package/assets/.aw-spec/templates/tasks-template.md +252 -0
- package/assets/.aw-spec/workflows/aw-spec/workflow.yml +77 -0
- package/assets/.aw-spec/workflows/workflow-registry.json +13 -0
- package/assets/.claude/skills/aw-spec-addcomponent/SKILL.md +116 -0
- package/assets/.claude/skills/aw-spec-agent-context-update/SKILL.md +31 -0
- package/assets/.claude/skills/aw-spec-analyze/SKILL.md +292 -0
- package/assets/.claude/skills/aw-spec-checklist/SKILL.md +374 -0
- package/assets/.claude/skills/aw-spec-clarify/SKILL.md +316 -0
- package/assets/.claude/skills/aw-spec-constitution/SKILL.md +190 -0
- package/assets/.claude/skills/aw-spec-foundation/SKILL.md +188 -0
- package/assets/.claude/skills/aw-spec-implement/SKILL.md +268 -0
- package/assets/.claude/skills/aw-spec-plan/SKILL.md +217 -0
- package/assets/.claude/skills/aw-spec-select-domain/SKILL.md +73 -0
- package/assets/.claude/skills/aw-spec-specify/SKILL.md +378 -0
- package/assets/.claude/skills/aw-spec-tasks/SKILL.md +255 -0
- package/assets/.claude/skills/aw-spec-taskstoissues/SKILL.md +107 -0
- package/assets/docs/README.md +106 -0
- package/assets/docs/VerticalSlice/PACKAGING.md +185 -0
- package/assets/docs/VerticalSlice/VerticalSlice.pack.txt +2833 -0
- package/assets/docs/VerticalSlice/pack-foundation.ps1 +145 -0
- package/assets/docs/VerticalSlice/pack-foundation.sh +196 -0
- package/assets/docs/VerticalSlice/unpack-foundation.ps1 +126 -0
- package/assets/docs/VerticalSlice/unpack-foundation.sh +217 -0
- package/assets/docs/architecture/clean-architecture.md +71 -0
- package/assets/docs/architecture/cqrs.md +141 -0
- package/assets/docs/architecture/eventing.md +83 -0
- package/assets/docs/architecture/folder-structure.md +61 -0
- package/assets/docs/architecture/modular-monolith.md +47 -0
- package/assets/docs/architecture/persistence.md +269 -0
- package/assets/docs/architecture/testing.md +55 -0
- package/assets/docs/architecture/vertical-slices.md +201 -0
- package/assets/docs/command.txt +295 -0
- package/assets/docs/components/Email/README.md +112 -0
- package/assets/docs/components/Email/integration.md +260 -0
- package/assets/docs/components/Jobs/README.md +113 -0
- package/assets/docs/components/Jobs/integration.md +245 -0
- package/assets/docs/components/QrGenerator/README.md +78 -0
- package/assets/docs/components/QrGenerator/integration.md +185 -0
- package/assets/docs/components/README.md +57 -0
- package/assets/docs/domain/domain-driven-design.md +212 -0
- package/assets/docs/domainspecs/healthcare/ai-rules.domain.md +34 -0
- package/assets/docs/domainspecs/healthcare/api-versioning.domain.md +17 -0
- package/assets/docs/domainspecs/healthcare/auditing.domain.md +29 -0
- package/assets/docs/domainspecs/healthcare/authorization.domain.md +26 -0
- package/assets/docs/domainspecs/healthcare/clinical-terms.md +20 -0
- package/assets/docs/domainspecs/healthcare/coding-standards.domain.md +26 -0
- package/assets/docs/domainspecs/healthcare/comandrulemap.md +119 -0
- package/assets/docs/domainspecs/healthcare/consent.md +19 -0
- package/assets/docs/domainspecs/healthcare/cqrs.domain.md +12 -0
- package/assets/docs/domainspecs/healthcare/data-classification.domain.md +28 -0
- package/assets/docs/domainspecs/healthcare/dependency-policy.domain.md +11 -0
- package/assets/docs/domainspecs/healthcare/dicom.md +15 -0
- package/assets/docs/domainspecs/healthcare/domain-driven-design.domain.md +28 -0
- package/assets/docs/domainspecs/healthcare/domain-requirements.md +55 -0
- package/assets/docs/domainspecs/healthcare/eventing.domain.md +18 -0
- package/assets/docs/domainspecs/healthcare/fhir.md +36 -0
- package/assets/docs/domainspecs/healthcare/folder-structure.domain.md +23 -0
- package/assets/docs/domainspecs/healthcare/hipaa.md +34 -0
- package/assets/docs/domainspecs/healthcare/hl7.md +15 -0
- package/assets/docs/domainspecs/healthcare/integration-terms.md +21 -0
- package/assets/docs/domainspecs/healthcare/persistence.domain.md +20 -0
- package/assets/docs/domainspecs/healthcare/terminology.md +30 -0
- package/assets/docs/domainspecs/healthcare/testing.domain.md +15 -0
- package/assets/docs/domainspecs/healthcare/vertical-slices.domain.md +18 -0
- package/assets/docs/domainspecs/healthcare/zero-trust.domain.md +12 -0
- package/assets/docs/domainspecs/pharma/ai-rules.domain.md +32 -0
- package/assets/docs/domainspecs/pharma/api-versioning.domain.md +20 -0
- package/assets/docs/domainspecs/pharma/atc.md +22 -0
- package/assets/docs/domainspecs/pharma/auditing.domain.md +26 -0
- package/assets/docs/domainspecs/pharma/authorization.domain.md +25 -0
- package/assets/docs/domainspecs/pharma/coding-standards.domain.md +28 -0
- package/assets/docs/domainspecs/pharma/comandrulemap.md +136 -0
- package/assets/docs/domainspecs/pharma/cqrs.domain.md +16 -0
- package/assets/docs/domainspecs/pharma/data-classification.domain.md +24 -0
- package/assets/docs/domainspecs/pharma/data-provenance.md +21 -0
- package/assets/docs/domainspecs/pharma/dependency-policy.domain.md +11 -0
- package/assets/docs/domainspecs/pharma/domain-driven-design.domain.md +36 -0
- package/assets/docs/domainspecs/pharma/domain-requirements.md +99 -0
- package/assets/docs/domainspecs/pharma/eventing.domain.md +18 -0
- package/assets/docs/domainspecs/pharma/fhir.md +31 -0
- package/assets/docs/domainspecs/pharma/folder-structure.domain.md +24 -0
- package/assets/docs/domainspecs/pharma/hl7.md +17 -0
- package/assets/docs/domainspecs/pharma/idmp.md +26 -0
- package/assets/docs/domainspecs/pharma/integration-terms.md +21 -0
- package/assets/docs/domainspecs/pharma/ndc.md +28 -0
- package/assets/docs/domainspecs/pharma/persistence.domain.md +23 -0
- package/assets/docs/domainspecs/pharma/pharma-terms.md +27 -0
- package/assets/docs/domainspecs/pharma/product-lifecycle.domain.md +30 -0
- package/assets/docs/domainspecs/pharma/regulatory-compliance.md +19 -0
- package/assets/docs/domainspecs/pharma/terminology.md +32 -0
- package/assets/docs/domainspecs/pharma/testing.domain.md +19 -0
- package/assets/docs/domainspecs/pharma/vertical-slices.domain.md +17 -0
- package/assets/docs/domainspecs/pharma/zero-trust.domain.md +12 -0
- package/assets/docs/glossary/ai-rules.md +59 -0
- package/assets/docs/governance/api-versioning.md +99 -0
- package/assets/docs/governance/coding-standards.md +87 -0
- package/assets/docs/governance/dependency-policy.md +40 -0
- package/assets/docs/interop/ihe-conformance.md +31 -0
- package/assets/docs/pharma-constitution.my-ref.md +86 -0
- package/assets/docs/requirement-spec.txt +15 -0
- package/assets/docs/security/auditing.md +117 -0
- package/assets/docs/security/authorization-matrix.md +14 -0
- package/assets/docs/security/authorization.md +87 -0
- package/assets/docs/security/data-classification.md +38 -0
- package/assets/docs/security/zero-trust.md +76 -0
- package/assets/docs/technology-constitution.md +172 -0
- package/dist/utils/paths.js +1 -1
- package/dist/utils/paths.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# update-agent-context.sh
|
|
3
|
+
#
|
|
4
|
+
# Refresh the managed AW-Spec section in the coding agent's context file
|
|
5
|
+
# (e.g. CLAUDE.md, .github/copilot-instructions.md, AGENTS.md).
|
|
6
|
+
#
|
|
7
|
+
# Reads `context_file` and `context_markers.{start,end}` from the
|
|
8
|
+
# agent-context extension config:
|
|
9
|
+
# .aw-spec/extensions/agent-context/agent-context-config.yml
|
|
10
|
+
#
|
|
11
|
+
# Usage: update-agent-context.sh [plan_path]
|
|
12
|
+
#
|
|
13
|
+
# When `plan_path` is omitted, the script picks the most recently modified
|
|
14
|
+
# `specs/*/plan.md` if any exist, otherwise emits the section without a
|
|
15
|
+
# concrete plan path.
|
|
16
|
+
|
|
17
|
+
set -euo pipefail
|
|
18
|
+
|
|
19
|
+
PROJECT_ROOT="$(pwd)"
|
|
20
|
+
EXT_CONFIG="$PROJECT_ROOT/.aw-spec/extensions/agent-context/agent-context-config.yml"
|
|
21
|
+
DEFAULT_START="<!-- AW-SPEC START -->"
|
|
22
|
+
DEFAULT_END="<!-- AW-SPEC END -->"
|
|
23
|
+
|
|
24
|
+
if [[ ! -f "$EXT_CONFIG" ]]; then
|
|
25
|
+
echo "agent-context: $EXT_CONFIG not found; nothing to do." >&2
|
|
26
|
+
exit 0
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# Locate a suitable Python interpreter (python3, then python).
|
|
30
|
+
_python=""
|
|
31
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
32
|
+
_python="python3"
|
|
33
|
+
elif command -v python >/dev/null 2>&1 && python --version 2>&1 | grep -q "^Python 3"; then
|
|
34
|
+
_python="python"
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
if [[ -z "$_python" ]]; then
|
|
38
|
+
echo "agent-context: Python 3 not found on PATH; skipping update." >&2
|
|
39
|
+
exit 0
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# Parse extension config once; emit three newline-separated fields:
|
|
43
|
+
# context_file, context_markers.start, context_markers.end
|
|
44
|
+
if ! _raw_opts="$("$_python" - "$EXT_CONFIG" <<'PY'
|
|
45
|
+
import sys
|
|
46
|
+
try:
|
|
47
|
+
import yaml
|
|
48
|
+
except ImportError:
|
|
49
|
+
print(
|
|
50
|
+
"agent-context: PyYAML is required to parse extension config but is not available "
|
|
51
|
+
"in the current Python environment.\n"
|
|
52
|
+
" To resolve: pip install pyyaml (or install it into the environment used by python3).\n"
|
|
53
|
+
" Context file will not be updated until PyYAML is importable.",
|
|
54
|
+
file=sys.stderr,
|
|
55
|
+
)
|
|
56
|
+
sys.exit(2)
|
|
57
|
+
try:
|
|
58
|
+
with open(sys.argv[1], "r", encoding="utf-8") as fh:
|
|
59
|
+
data = yaml.safe_load(fh)
|
|
60
|
+
except Exception as exc:
|
|
61
|
+
print(
|
|
62
|
+
f"agent-context: unable to parse {sys.argv[1]} ({exc}); cannot update context.",
|
|
63
|
+
file=sys.stderr,
|
|
64
|
+
)
|
|
65
|
+
sys.exit(2)
|
|
66
|
+
if not isinstance(data, dict):
|
|
67
|
+
data = {}
|
|
68
|
+
def get_str(obj, *keys):
|
|
69
|
+
node = obj
|
|
70
|
+
for k in keys:
|
|
71
|
+
if isinstance(node, dict) and k in node:
|
|
72
|
+
node = node[k]
|
|
73
|
+
else:
|
|
74
|
+
return ""
|
|
75
|
+
return node if isinstance(node, str) else ""
|
|
76
|
+
print(get_str(data, "context_file"))
|
|
77
|
+
print(get_str(data, "context_markers", "start"))
|
|
78
|
+
print(get_str(data, "context_markers", "end"))
|
|
79
|
+
PY
|
|
80
|
+
)"; then
|
|
81
|
+
echo "agent-context: skipping update (see above for details)." >&2
|
|
82
|
+
exit 0
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
_opts_lines=()
|
|
86
|
+
while IFS= read -r _line || [[ -n "$_line" ]]; do
|
|
87
|
+
_opts_lines+=("$_line")
|
|
88
|
+
done < <(printf '%s\n' "$_raw_opts")
|
|
89
|
+
if (( ${#_opts_lines[@]} < 3 )); then
|
|
90
|
+
echo "agent-context: malformed config parser output; expected 3 lines (context_file, marker_start, marker_end), got ${#_opts_lines[@]}; skipping update." >&2
|
|
91
|
+
exit 0
|
|
92
|
+
fi
|
|
93
|
+
CONTEXT_FILE="${_opts_lines[0]}"
|
|
94
|
+
MARKER_START="${_opts_lines[1]}"
|
|
95
|
+
MARKER_END="${_opts_lines[2]}"
|
|
96
|
+
|
|
97
|
+
if [[ -z "$CONTEXT_FILE" ]]; then
|
|
98
|
+
echo "agent-context: context_file not set in extension config; nothing to do." >&2
|
|
99
|
+
exit 0
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
# Reject absolute paths, backslash separators, and '..' path segments in context_file
|
|
103
|
+
if [[ "$CONTEXT_FILE" == /* ]] || [[ "$CONTEXT_FILE" =~ ^[A-Za-z]: ]]; then
|
|
104
|
+
echo "agent-context: context_file must be a project-relative path; got '$CONTEXT_FILE'." >&2
|
|
105
|
+
exit 1
|
|
106
|
+
fi
|
|
107
|
+
if [[ "$CONTEXT_FILE" == *\\* ]]; then
|
|
108
|
+
echo "agent-context: context_file must not contain backslash separators; got '$CONTEXT_FILE'." >&2
|
|
109
|
+
exit 1
|
|
110
|
+
fi
|
|
111
|
+
IFS='/' read -ra _cf_parts <<< "$CONTEXT_FILE"
|
|
112
|
+
for _seg in "${_cf_parts[@]}"; do
|
|
113
|
+
if [[ "$_seg" == ".." ]]; then
|
|
114
|
+
echo "agent-context: context_file must not contain '..' path segments; got '$CONTEXT_FILE'." >&2
|
|
115
|
+
exit 1
|
|
116
|
+
fi
|
|
117
|
+
done
|
|
118
|
+
unset _cf_parts _seg
|
|
119
|
+
|
|
120
|
+
[[ -z "$MARKER_START" ]] && MARKER_START="$DEFAULT_START"
|
|
121
|
+
[[ -z "$MARKER_END" ]] && MARKER_END="$DEFAULT_END"
|
|
122
|
+
|
|
123
|
+
PLAN_PATH="${1:-}"
|
|
124
|
+
if [[ -z "$PLAN_PATH" ]]; then
|
|
125
|
+
# Pick the most recently modified plan.md two levels deep
|
|
126
|
+
# (specs/<Aggregate>/<Feature>/plan.md).
|
|
127
|
+
# Use find + sort by modification time to avoid ls/head fragility with
|
|
128
|
+
# spaces in paths or SIGPIPE from pipefail.
|
|
129
|
+
_plan_abs="$("$_python" - "$PROJECT_ROOT" <<'PY'
|
|
130
|
+
import sys, os
|
|
131
|
+
from pathlib import Path
|
|
132
|
+
specs = Path(sys.argv[1]) / "specs"
|
|
133
|
+
plans = sorted(
|
|
134
|
+
specs.glob("*/plan.md"),
|
|
135
|
+
key=lambda p: p.stat().st_mtime,
|
|
136
|
+
reverse=True,
|
|
137
|
+
)
|
|
138
|
+
print(plans[0] if plans else "")
|
|
139
|
+
PY
|
|
140
|
+
)"
|
|
141
|
+
if [[ -n "$_plan_abs" ]]; then
|
|
142
|
+
PLAN_PATH="${_plan_abs#"$PROJECT_ROOT/"}"
|
|
143
|
+
fi
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
CTX_PATH="$PROJECT_ROOT/$CONTEXT_FILE"
|
|
147
|
+
mkdir -p "$(dirname "$CTX_PATH")"
|
|
148
|
+
|
|
149
|
+
# Build the managed section
|
|
150
|
+
TMP_SECTION="$(mktemp)"
|
|
151
|
+
trap 'rm -f "$TMP_SECTION"' EXIT
|
|
152
|
+
{
|
|
153
|
+
echo "$MARKER_START"
|
|
154
|
+
echo "For additional context about technologies to be used, project structure,"
|
|
155
|
+
echo "shell commands, and other important information, read the current plan"
|
|
156
|
+
if [[ -n "$PLAN_PATH" ]]; then
|
|
157
|
+
echo "at $PLAN_PATH"
|
|
158
|
+
fi
|
|
159
|
+
echo "$MARKER_END"
|
|
160
|
+
} > "$TMP_SECTION"
|
|
161
|
+
|
|
162
|
+
"$_python" - "$CTX_PATH" "$MARKER_START" "$MARKER_END" "$TMP_SECTION" <<'PY'
|
|
163
|
+
import sys, os
|
|
164
|
+
ctx_path, start, end, section_path = sys.argv[1:5]
|
|
165
|
+
with open(section_path, "r", encoding="utf-8") as fh:
|
|
166
|
+
section = fh.read().rstrip("\n") + "\n"
|
|
167
|
+
|
|
168
|
+
if os.path.exists(ctx_path):
|
|
169
|
+
with open(ctx_path, "r", encoding="utf-8-sig") as fh:
|
|
170
|
+
content = fh.read()
|
|
171
|
+
s = content.find(start)
|
|
172
|
+
e = content.find(end, s if s != -1 else 0)
|
|
173
|
+
if s != -1 and e != -1 and e > s:
|
|
174
|
+
end_of_marker = e + len(end)
|
|
175
|
+
if end_of_marker < len(content) and content[end_of_marker] == "\r":
|
|
176
|
+
end_of_marker += 1
|
|
177
|
+
if end_of_marker < len(content) and content[end_of_marker] == "\n":
|
|
178
|
+
end_of_marker += 1
|
|
179
|
+
new_content = content[:s] + section + content[end_of_marker:]
|
|
180
|
+
elif s != -1:
|
|
181
|
+
new_content = content[:s] + section
|
|
182
|
+
elif e != -1:
|
|
183
|
+
end_of_marker = e + len(end)
|
|
184
|
+
if end_of_marker < len(content) and content[end_of_marker] == "\r":
|
|
185
|
+
end_of_marker += 1
|
|
186
|
+
if end_of_marker < len(content) and content[end_of_marker] == "\n":
|
|
187
|
+
end_of_marker += 1
|
|
188
|
+
new_content = section + content[end_of_marker:]
|
|
189
|
+
else:
|
|
190
|
+
if content and not content.endswith("\n"):
|
|
191
|
+
content += "\n"
|
|
192
|
+
new_content = (content + "\n" + section) if content else section
|
|
193
|
+
else:
|
|
194
|
+
new_content = section
|
|
195
|
+
|
|
196
|
+
new_content = new_content.replace("\r\n", "\n").replace("\r", "\n")
|
|
197
|
+
with open(ctx_path, "wb") as fh:
|
|
198
|
+
fh.write(new_content.encode("utf-8"))
|
|
199
|
+
PY
|
|
200
|
+
|
|
201
|
+
echo "agent-context: updated $CONTEXT_FILE"
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
#!/usr/bin/env pwsh
|
|
2
|
+
# update-agent-context.ps1
|
|
3
|
+
#
|
|
4
|
+
# Refresh the managed AW-Spec section in the coding agent's context file
|
|
5
|
+
# (e.g. CLAUDE.md, .github/copilot-instructions.md, AGENTS.md).
|
|
6
|
+
#
|
|
7
|
+
# Reads `context_file` and `context_markers.{start,end}` from the
|
|
8
|
+
# agent-context extension config:
|
|
9
|
+
# .aw-spec/extensions/agent-context/agent-context-config.yml
|
|
10
|
+
#
|
|
11
|
+
# Usage: update-agent-context.ps1 [plan_path]
|
|
12
|
+
|
|
13
|
+
[CmdletBinding()]
|
|
14
|
+
param(
|
|
15
|
+
[Parameter(Position = 0)]
|
|
16
|
+
[string]$PlanPath
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
function Get-ConfigValue {
|
|
20
|
+
param(
|
|
21
|
+
[AllowNull()][object]$Object,
|
|
22
|
+
[Parameter(Mandatory = $true)][string]$Key
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
if ($null -eq $Object) {
|
|
26
|
+
return $null
|
|
27
|
+
}
|
|
28
|
+
if ($Object -is [System.Collections.IDictionary]) {
|
|
29
|
+
return $Object[$Key]
|
|
30
|
+
}
|
|
31
|
+
$prop = $Object.PSObject.Properties[$Key]
|
|
32
|
+
if ($prop) {
|
|
33
|
+
return $prop.Value
|
|
34
|
+
}
|
|
35
|
+
return $null
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function Test-ConfigObject {
|
|
39
|
+
param(
|
|
40
|
+
[AllowNull()][object]$Object
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
if ($null -eq $Object) {
|
|
44
|
+
return $false
|
|
45
|
+
}
|
|
46
|
+
if ($Object -is [System.Collections.IDictionary]) {
|
|
47
|
+
return $true
|
|
48
|
+
}
|
|
49
|
+
if ($Object -is [System.Management.Automation.PSCustomObject]) {
|
|
50
|
+
return $true
|
|
51
|
+
}
|
|
52
|
+
return $false
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
$ErrorActionPreference = 'Stop'
|
|
56
|
+
$DefaultStart = '<!-- AW-SPEC START -->'
|
|
57
|
+
$DefaultEnd = '<!-- AW-SPEC END -->'
|
|
58
|
+
$ProjectRoot = (Get-Location).Path
|
|
59
|
+
$ExtConfig = Join-Path $ProjectRoot '.aw-spec/extensions/agent-context/agent-context-config.yml'
|
|
60
|
+
|
|
61
|
+
if (-not (Test-Path -LiteralPath $ExtConfig)) {
|
|
62
|
+
Write-Warning "agent-context: $ExtConfig not found; nothing to do."
|
|
63
|
+
exit 0
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
$Options = $null
|
|
67
|
+
if (Get-Command ConvertFrom-Yaml -ErrorAction SilentlyContinue) {
|
|
68
|
+
try {
|
|
69
|
+
$Options = Get-Content -LiteralPath $ExtConfig -Raw | ConvertFrom-Yaml -ErrorAction Stop
|
|
70
|
+
} catch {
|
|
71
|
+
# fall through to Python fallback
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if ($null -eq $Options) {
|
|
76
|
+
# ConvertFrom-Yaml unavailable or failed; fall back to Python+PyYAML.
|
|
77
|
+
$pythonCmd = $null
|
|
78
|
+
foreach ($candidate in @('python3', 'python')) {
|
|
79
|
+
if (Get-Command $candidate -ErrorAction SilentlyContinue) {
|
|
80
|
+
# Verify it is Python 3
|
|
81
|
+
$verOut = & $candidate --version 2>&1
|
|
82
|
+
if ($verOut -match 'Python 3') {
|
|
83
|
+
$pythonCmd = $candidate
|
|
84
|
+
break
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if ($pythonCmd) {
|
|
90
|
+
try {
|
|
91
|
+
$jsonOut = & $pythonCmd -c @'
|
|
92
|
+
import json
|
|
93
|
+
import sys
|
|
94
|
+
try:
|
|
95
|
+
import yaml
|
|
96
|
+
except ImportError:
|
|
97
|
+
print(
|
|
98
|
+
"agent-context: PyYAML is required to parse extension config; cannot update context.",
|
|
99
|
+
file=sys.stderr,
|
|
100
|
+
)
|
|
101
|
+
sys.exit(2)
|
|
102
|
+
|
|
103
|
+
try:
|
|
104
|
+
with open(sys.argv[1], "r", encoding="utf-8") as fh:
|
|
105
|
+
data = yaml.safe_load(fh)
|
|
106
|
+
except Exception as exc:
|
|
107
|
+
print(
|
|
108
|
+
f"agent-context: unable to parse {sys.argv[1]} ({exc}); cannot update context.",
|
|
109
|
+
file=sys.stderr,
|
|
110
|
+
)
|
|
111
|
+
sys.exit(2)
|
|
112
|
+
|
|
113
|
+
if not isinstance(data, dict):
|
|
114
|
+
data = {}
|
|
115
|
+
|
|
116
|
+
print(json.dumps(data))
|
|
117
|
+
'@ $ExtConfig
|
|
118
|
+
if ($LASTEXITCODE -eq 0 -and $jsonOut) {
|
|
119
|
+
$Options = $jsonOut | ConvertFrom-Json -ErrorAction Stop
|
|
120
|
+
}
|
|
121
|
+
} catch {
|
|
122
|
+
$Options = $null
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (-not $Options) {
|
|
127
|
+
Write-Warning "agent-context: unable to parse $ExtConfig; skipping update."
|
|
128
|
+
exit 0
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (-not (Test-ConfigObject -Object $Options)) {
|
|
133
|
+
Write-Warning "agent-context: $ExtConfig must contain a YAML mapping; skipping update."
|
|
134
|
+
exit 0
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
$ContextFile = Get-ConfigValue -Object $Options -Key 'context_file'
|
|
138
|
+
if (-not $ContextFile) {
|
|
139
|
+
Write-Warning 'agent-context: context_file not set in extension config; nothing to do.'
|
|
140
|
+
exit 0
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
# Reject absolute paths and '..' path segments in context_file
|
|
144
|
+
if ([System.IO.Path]::IsPathRooted($ContextFile)) {
|
|
145
|
+
Write-Warning "agent-context: context_file must be a project-relative path; got '$ContextFile'."
|
|
146
|
+
exit 1
|
|
147
|
+
}
|
|
148
|
+
$cfSegments = $ContextFile -split '[/\\]'
|
|
149
|
+
if ($cfSegments -contains '..') {
|
|
150
|
+
Write-Warning "agent-context: context_file must not contain '..' path segments; got '$ContextFile'."
|
|
151
|
+
exit 1
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
$MarkerStart = $DefaultStart
|
|
155
|
+
$MarkerEnd = $DefaultEnd
|
|
156
|
+
$cm = Get-ConfigValue -Object $Options -Key 'context_markers'
|
|
157
|
+
if ($cm) {
|
|
158
|
+
$cmStart = Get-ConfigValue -Object $cm -Key 'start'
|
|
159
|
+
if ($cmStart -is [string] -and $cmStart) {
|
|
160
|
+
$MarkerStart = $cmStart
|
|
161
|
+
}
|
|
162
|
+
$cmEnd = Get-ConfigValue -Object $cm -Key 'end'
|
|
163
|
+
if ($cmEnd -is [string] -and $cmEnd) {
|
|
164
|
+
$MarkerEnd = $cmEnd
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (-not $PlanPath) {
|
|
169
|
+
# Discover plan.md two levels deep under the spec root
|
|
170
|
+
# (specs/<Aggregate>/<Feature>/plan.md). Wrap in try/catch so access
|
|
171
|
+
# errors under $ErrorActionPreference = 'Stop' don't abort the script.
|
|
172
|
+
try {
|
|
173
|
+
$specsDir = Join-Path $ProjectRoot 'specs'
|
|
174
|
+
$candidate = Get-ChildItem -Path $specsDir -Directory -ErrorAction SilentlyContinue |
|
|
175
|
+
ForEach-Object { Get-Item -LiteralPath (Join-Path $_.FullName 'plan.md') -ErrorAction SilentlyContinue } |
|
|
176
|
+
Where-Object { $_ } |
|
|
177
|
+
Sort-Object LastWriteTime -Descending |
|
|
178
|
+
Select-Object -First 1
|
|
179
|
+
if ($candidate) {
|
|
180
|
+
$PlanPath = [System.IO.Path]::GetRelativePath($ProjectRoot, $candidate.FullName).Replace('\','/')
|
|
181
|
+
}
|
|
182
|
+
} catch {
|
|
183
|
+
# Non-fatal: continue without a plan path.
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
$CtxPath = Join-Path $ProjectRoot $ContextFile
|
|
188
|
+
$CtxDir = Split-Path -Parent $CtxPath
|
|
189
|
+
if ($CtxDir -and -not (Test-Path -LiteralPath $CtxDir)) {
|
|
190
|
+
New-Item -ItemType Directory -Path $CtxDir -Force | Out-Null
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
$lines = @($MarkerStart,
|
|
194
|
+
'For additional context about technologies to be used, project structure,',
|
|
195
|
+
'shell commands, and other important information, read the current plan')
|
|
196
|
+
if ($PlanPath) {
|
|
197
|
+
$lines += "at $PlanPath"
|
|
198
|
+
}
|
|
199
|
+
$lines += $MarkerEnd
|
|
200
|
+
$Section = ($lines -join "`n") + "`n"
|
|
201
|
+
|
|
202
|
+
if (Test-Path -LiteralPath $CtxPath) {
|
|
203
|
+
$rawBytes = [System.IO.File]::ReadAllBytes($CtxPath)
|
|
204
|
+
# Strip UTF-8 BOM if present
|
|
205
|
+
if ($rawBytes.Length -ge 3 -and $rawBytes[0] -eq 0xEF -and $rawBytes[1] -eq 0xBB -and $rawBytes[2] -eq 0xBF) {
|
|
206
|
+
$content = [System.Text.Encoding]::UTF8.GetString($rawBytes, 3, $rawBytes.Length - 3)
|
|
207
|
+
} else {
|
|
208
|
+
$content = [System.Text.Encoding]::UTF8.GetString($rawBytes)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
$s = $content.IndexOf($MarkerStart)
|
|
212
|
+
$e = if ($s -ge 0) { $content.IndexOf($MarkerEnd, $s) } else { $content.IndexOf($MarkerEnd) }
|
|
213
|
+
|
|
214
|
+
if ($s -ge 0 -and $e -ge 0 -and $e -gt $s) {
|
|
215
|
+
$endOfMarker = $e + $MarkerEnd.Length
|
|
216
|
+
if ($endOfMarker -lt $content.Length -and $content[$endOfMarker] -eq "`r") { $endOfMarker++ }
|
|
217
|
+
if ($endOfMarker -lt $content.Length -and $content[$endOfMarker] -eq "`n") { $endOfMarker++ }
|
|
218
|
+
$newContent = $content.Substring(0, $s) + $Section + $content.Substring($endOfMarker)
|
|
219
|
+
} elseif ($s -ge 0) {
|
|
220
|
+
$newContent = $content.Substring(0, $s) + $Section
|
|
221
|
+
} elseif ($e -ge 0) {
|
|
222
|
+
$endOfMarker = $e + $MarkerEnd.Length
|
|
223
|
+
if ($endOfMarker -lt $content.Length -and $content[$endOfMarker] -eq "`r") { $endOfMarker++ }
|
|
224
|
+
if ($endOfMarker -lt $content.Length -and $content[$endOfMarker] -eq "`n") { $endOfMarker++ }
|
|
225
|
+
$newContent = $Section + $content.Substring($endOfMarker)
|
|
226
|
+
} else {
|
|
227
|
+
if ($content -and -not $content.EndsWith("`n")) { $content += "`n" }
|
|
228
|
+
if ($content) { $newContent = $content + "`n" + $Section } else { $newContent = $Section }
|
|
229
|
+
}
|
|
230
|
+
} else {
|
|
231
|
+
$newContent = $Section
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
$newContent = $newContent.Replace("`r`n", "`n").Replace("`r", "`n")
|
|
235
|
+
[System.IO.File]::WriteAllText($CtxPath, $newContent, (New-Object System.Text.UTF8Encoding($false)))
|
|
236
|
+
|
|
237
|
+
Write-Host "agent-context: updated $ContextFile"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
installed:
|
|
2
|
+
- agent-context
|
|
3
|
+
settings:
|
|
4
|
+
auto_execute_hooks: true
|
|
5
|
+
hooks:
|
|
6
|
+
after_specify:
|
|
7
|
+
- extension: agent-context
|
|
8
|
+
command: aw-spec.agent-context.update
|
|
9
|
+
enabled: true
|
|
10
|
+
optional: true
|
|
11
|
+
priority: 10
|
|
12
|
+
prompt: Execute aw-spec.agent-context.update?
|
|
13
|
+
description: Refresh agent context after specification
|
|
14
|
+
condition: null
|
|
15
|
+
after_plan:
|
|
16
|
+
- extension: agent-context
|
|
17
|
+
command: aw-spec.agent-context.update
|
|
18
|
+
enabled: true
|
|
19
|
+
optional: true
|
|
20
|
+
priority: 10
|
|
21
|
+
prompt: Execute aw-spec.agent-context.update?
|
|
22
|
+
description: Refresh agent context after planning
|
|
23
|
+
condition: null
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.10.1",
|
|
3
|
+
"integration_state_schema": 1,
|
|
4
|
+
"installed_integrations": [
|
|
5
|
+
"claude"
|
|
6
|
+
],
|
|
7
|
+
"integration_settings": {
|
|
8
|
+
"claude": {
|
|
9
|
+
"script": "sh",
|
|
10
|
+
"invoke_separator": "-"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"integration": "claude",
|
|
14
|
+
"default_integration": "claude"
|
|
15
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"integration": "aw-spec",
|
|
3
|
+
"version": "0.10.1",
|
|
4
|
+
"installed_at": "2026-06-10T07:39:01.950069+00:00",
|
|
5
|
+
"files": {
|
|
6
|
+
".aw-spec/scripts/bash/common.sh": "21cc21dd88c36e632fd052eca435c0e7ab262acaff632667dec87ff8b794ef43",
|
|
7
|
+
".aw-spec/scripts/bash/setup-plan.sh": "4eb12c5b00f5c66a7d01b56c90898d320dcef4425d9b96652d57156c84948eda",
|
|
8
|
+
".aw-spec/scripts/bash/setup-tasks.sh": "cf21ba2212b4dd5b435c5ea8527500cfd27768b86c0bbc7ebc3207759f118d27",
|
|
9
|
+
".aw-spec/scripts/bash/check-prerequisites.sh": "afce0aa8db177320d83aa0b8e3619c06b865fd810781894e4a7a3f81664941ce",
|
|
10
|
+
".aw-spec/scripts/bash/create-new-feature.sh": "324762a95ec2f534d0982931fdb11380558258791fe3bfe3ca7e11a768653134",
|
|
11
|
+
".aw-spec/templates/constitution-template.md": "ce7549540fa45543cca797a150201d868e64495fdff39dc38246fb17bd4024b3",
|
|
12
|
+
".aw-spec/templates/checklist-template.md": "c37695297e5d3153d64f82c21223509940b13932046c7961c42d1d669516130c",
|
|
13
|
+
".aw-spec/templates/tasks-template.md": "fc29a233f6f5a27ca31f1aa46b596af6500c627441c6e62b2bc4a1d721525842",
|
|
14
|
+
".aw-spec/templates/spec-template.md": "3945437fc35cd30a5b2bf7beea680337c3516826d3efa5a6b92c4a7eca1ba28e",
|
|
15
|
+
".aw-spec/templates/plan-template.md": "cc7f7979cf8d8836ec26492785affd80791d3422a2b745062ec695be8c985ef7"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"integration": "claude",
|
|
3
|
+
"version": "0.10.1",
|
|
4
|
+
"installed_at": "2026-06-10T07:39:01.929414+00:00",
|
|
5
|
+
"files": {
|
|
6
|
+
".claude/skills/aw-spec-analyze/SKILL.md": "9b8caa25a53ba97ddcfc993b5f304990468e29aa0bf1e397f534c7a0a54678ab",
|
|
7
|
+
".claude/skills/aw-spec-clarify/SKILL.md": "fc52a87c6a851c5cdb1451c766c6c71619554b35d219071c74214a4f4cc33d8a",
|
|
8
|
+
".claude/skills/aw-spec-constitution/SKILL.md": "cbe4e06a11cbf92bdb39bcf2a3000717f33556c751ad5666bfefcc2811851bf6",
|
|
9
|
+
".claude/skills/aw-spec-implement/SKILL.md": "6018e531dd7d366318d107fba44ad36881e0ce3649a93365292eedb713203710",
|
|
10
|
+
".claude/skills/aw-spec-plan/SKILL.md": "93b68cc5219333a9588813830ed6a61904f8f470bd0c5b01419b5b31b923b433",
|
|
11
|
+
".claude/skills/aw-spec-checklist/SKILL.md": "7e223721a3c43e1083a018af3ced3297b3c1486468a158b29f09a85b4f2a6e2b",
|
|
12
|
+
".claude/skills/aw-spec-specify/SKILL.md": "823f6ebe99d1f7b7f5e29754a16c0fa6e8be36087aa97344ddb61a22e54dac79",
|
|
13
|
+
".claude/skills/aw-spec-tasks/SKILL.md": "8c2ff9da9e93603484ac4ef077dd0c67b7b51253315e71fbdc334924e145a03e",
|
|
14
|
+
".claude/skills/aw-spec-taskstoissues/SKILL.md": "41e708e04a8449a2ee27cdbffb19b0fbb8596ef0862611e827afb1372056c23f",
|
|
15
|
+
".claude/skills/aw-spec-select-domain/SKILL.md": "07cbbc12dcbad9c2d0342fde853c4338eb91c9c818586f75aa291f6ebcf59eca"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# [PROJECT_NAME] Constitution
|
|
2
|
+
<!-- Example: Spec Constitution, TaskFlow Constitution, etc. -->
|
|
3
|
+
|
|
4
|
+
## Core Principles
|
|
5
|
+
|
|
6
|
+
### [PRINCIPLE_1_NAME]
|
|
7
|
+
<!-- Example: I. Library-First -->
|
|
8
|
+
[PRINCIPLE_1_DESCRIPTION]
|
|
9
|
+
<!-- Example: Every feature starts as a standalone library; Libraries must be self-contained, independently testable, documented; Clear purpose required - no organizational-only libraries -->
|
|
10
|
+
|
|
11
|
+
### [PRINCIPLE_2_NAME]
|
|
12
|
+
<!-- Example: II. CLI Interface -->
|
|
13
|
+
[PRINCIPLE_2_DESCRIPTION]
|
|
14
|
+
<!-- Example: Every library exposes functionality via CLI; Text in/out protocol: stdin/args → stdout, errors → stderr; Support JSON + human-readable formats -->
|
|
15
|
+
|
|
16
|
+
### [PRINCIPLE_3_NAME]
|
|
17
|
+
<!-- Example: III. Test-First (NON-NEGOTIABLE) -->
|
|
18
|
+
[PRINCIPLE_3_DESCRIPTION]
|
|
19
|
+
<!-- Example: TDD mandatory: Tests written → User approved → Tests fail → Then implement; Red-Green-Refactor cycle strictly enforced -->
|
|
20
|
+
|
|
21
|
+
### [PRINCIPLE_4_NAME]
|
|
22
|
+
<!-- Example: IV. Integration Testing -->
|
|
23
|
+
[PRINCIPLE_4_DESCRIPTION]
|
|
24
|
+
<!-- Example: Focus areas requiring integration tests: New library contract tests, Contract changes, Inter-service communication, Shared schemas -->
|
|
25
|
+
|
|
26
|
+
### [PRINCIPLE_5_NAME]
|
|
27
|
+
<!-- Example: V. Observability, VI. Versioning & Breaking Changes, VII. Simplicity -->
|
|
28
|
+
[PRINCIPLE_5_DESCRIPTION]
|
|
29
|
+
<!-- Example: Text I/O ensures debuggability; Structured logging required; Or: MAJOR.MINOR.BUILD format; Or: Start simple, YAGNI principles -->
|
|
30
|
+
|
|
31
|
+
## [SECTION_2_NAME]
|
|
32
|
+
<!-- Example: Additional Constraints, Security Requirements, Performance Standards, etc. -->
|
|
33
|
+
|
|
34
|
+
[SECTION_2_CONTENT]
|
|
35
|
+
<!-- Example: Technology stack requirements, compliance standards, deployment policies, etc. -->
|
|
36
|
+
|
|
37
|
+
## [SECTION_3_NAME]
|
|
38
|
+
<!-- Example: Development Workflow, Review Process, Quality Gates, etc. -->
|
|
39
|
+
|
|
40
|
+
[SECTION_3_CONTENT]
|
|
41
|
+
<!-- Example: Code review requirements, testing gates, deployment approval process, etc. -->
|
|
42
|
+
|
|
43
|
+
## Governance
|
|
44
|
+
<!-- Example: Constitution supersedes all other practices; Amendments require documentation, approval, migration plan -->
|
|
45
|
+
|
|
46
|
+
[GOVERNANCE_RULES]
|
|
47
|
+
<!-- Example: All PRs/reviews must verify compliance; Complexity must be justified; Use [GUIDANCE_FILE] for runtime development guidance -->
|
|
48
|
+
|
|
49
|
+
**Version**: [CONSTITUTION_VERSION] | **Ratified**: [RATIFICATION_DATE] | **Last Amended**: [LAST_AMENDED_DATE]
|
|
50
|
+
<!-- Example: Version: 2.1.1 | Ratified: 2025-06-13 | Last Amended: 2025-07-16 -->
|