@antoneeo/agentic-sdlc-skill 1.36.0 → 1.38.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/CHANGELOG.md +22 -0
- package/README.md +205 -204
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/scripts/init.js +6 -6
- package/skills/agentic-sdlc-skill/ENFORCEMENT.md +5 -5
- package/skills/agentic-sdlc-skill/SKILL.md +6 -5
- package/skills/agentic-sdlc-skill/architect.md +215 -215
- package/skills/agentic-sdlc-skill/debugging.md +107 -60
- package/skills/agentic-sdlc-skill/dispatch.md +5 -5
- package/skills/agentic-sdlc-skill/elicitation.md +216 -216
- package/skills/agentic-sdlc-skill/hybrid.md +110 -106
- package/skills/agentic-sdlc-skill/memory.md +88 -88
- package/skills/agentic-sdlc-skill/review.md +70 -9
- package/skills/agentic-sdlc-skill/routing.md +28 -16
- package/skills/agentic-sdlc-skill/scripts/knowledge.py +2091 -2089
- package/skills/agentic-sdlc-skill/scripts/sdlc_check.py +71 -71
- package/skills/agentic-sdlc-skill/scripts/sdlc_core.py +25 -9
- package/skills/agentic-sdlc-skill/templates.md +5 -5
- package/skills/agentic-sdlc-skill/vision.md +245 -245
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
"""Domain entry point with shared project memory.
|
|
4
|
-
|
|
5
|
-
Ship this file, sdlc_core.py and knowledge.py together. The core alone omits
|
|
6
|
-
knowledge integrity and this entry point\'s domain-specific behavior.
|
|
7
|
-
"""
|
|
8
|
-
import sys
|
|
9
|
-
from pathlib import Path
|
|
10
|
-
|
|
11
|
-
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
12
|
-
|
|
13
|
-
try:
|
|
14
|
-
import sdlc_core
|
|
15
|
-
except ImportError as exc: # pragma: no cover - exercised by TS12, not by unit tests
|
|
16
|
-
sys.stderr.write(
|
|
17
|
-
"[ERROR] sdlc_check.py cannot find sdlc_core.py next to it: " + str(exc) + "\n"
|
|
18
|
-
" The validator needs entry point, sdlc_core.py and knowledge.py.\n"
|
|
19
|
-
" Copy all three together; core alone omits memory and overlay checks.\n")
|
|
20
|
-
sys.exit(1)
|
|
21
|
-
|
|
22
|
-
# Re-export the core's surface: existing importers (`import sdlc_check as sc`)
|
|
23
|
-
# and the test batteries reach for these names on this module.
|
|
24
|
-
from sdlc_core import * # noqa: F401,F403
|
|
25
|
-
from sdlc_core import _map_refs # noqa: F401 underscore helper used by the batteries
|
|
26
|
-
import knowledge
|
|
27
|
-
|
|
28
|
-
# The domain this distribution implements. It does NOT decide any document's
|
|
29
|
-
# owning domain -- that is resolved per project (`default_domain:` in the docs
|
|
30
|
-
# root's README) and per artifact (`domain:`), so the same tree gets the same
|
|
31
|
-
# verdict from every installed distribution. What it decides is which portable
|
|
32
|
-
# checks a document may import here by name; the rest warn as unavailable.
|
|
33
|
-
DOMAIN = "code"
|
|
34
|
-
|
|
35
|
-
sdlc_core.set_entry_point(DOMAIN, provides=("code", "knowledge"))
|
|
36
|
-
|
|
37
|
-
# What this distribution carries. The shared battery reads it; the spine
|
|
38
|
-
# capabilities are not optional, and a shared test refuses a profile that drops one.
|
|
39
|
-
sdlc_core.set_profile(
|
|
40
|
-
skill_name="agentic-sdlc",
|
|
41
|
-
unit_noun="feature",
|
|
42
|
-
support_files=("templates.md", "architect.md", "guides.md", "vision.md", "tdd.md",
|
|
43
|
-
"debugging.md", "elicitation.md", "review.md", "dispatch.md",
|
|
44
|
-
"routing.md", "hybrid.md", "ENFORCEMENT.md", "memory.md"),
|
|
45
|
-
capabilities=(
|
|
46
|
-
# spine
|
|
47
|
-
"triage", "write_triggers", "workstream_registry", "vision_gate",
|
|
48
|
-
"design_review_gate", "guide_router", "worktree_hygiene",
|
|
49
|
-
# code overlay
|
|
50
|
-
"architect_pass", "interaction_contract", "comprehension_guides", "tdd",
|
|
51
|
-
"subagent_dispatch", "legacy_narrative_handoff", "question_discipline",
|
|
52
|
-
),
|
|
53
|
-
design_gate_between=("### 3. Request Analysis", "### 4. Development and Testing"),
|
|
54
|
-
remind_line=(
|
|
55
|
-
"first decide if this skill governs the work; if yes, LOAD it once -- an "
|
|
56
|
-
"unread protocol cannot be applied. Declare the level (L1/L2/L3/Spike) "
|
|
57
|
-
"and the guide-router verdict before acting; an imperative is a request "
|
|
58
|
-
"to triage. Name the mechanism before fixing the first defect you can "
|
|
59
|
-
"measure -- symptom patches recur and stack. Replay governing text -- "
|
|
60
|
-
"doctrine, a prompt, a schema -- against the case that motivated it: red "
|
|
61
|
-
"under the old text, green under the new."
|
|
62
|
-
),
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def main(argv=None):
|
|
67
|
-
return knowledge.main(argv)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if __name__ == "__main__":
|
|
71
|
-
sys.exit(main())
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Domain entry point with shared project memory.
|
|
4
|
+
|
|
5
|
+
Ship this file, sdlc_core.py and knowledge.py together. The core alone omits
|
|
6
|
+
knowledge integrity and this entry point\'s domain-specific behavior.
|
|
7
|
+
"""
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
import sdlc_core
|
|
15
|
+
except ImportError as exc: # pragma: no cover - exercised by TS12, not by unit tests
|
|
16
|
+
sys.stderr.write(
|
|
17
|
+
"[ERROR] sdlc_check.py cannot find sdlc_core.py next to it: " + str(exc) + "\n"
|
|
18
|
+
" The validator needs entry point, sdlc_core.py and knowledge.py.\n"
|
|
19
|
+
" Copy all three together; core alone omits memory and overlay checks.\n")
|
|
20
|
+
sys.exit(1)
|
|
21
|
+
|
|
22
|
+
# Re-export the core's surface: existing importers (`import sdlc_check as sc`)
|
|
23
|
+
# and the test batteries reach for these names on this module.
|
|
24
|
+
from sdlc_core import * # noqa: F401,F403
|
|
25
|
+
from sdlc_core import _map_refs # noqa: F401 underscore helper used by the batteries
|
|
26
|
+
import knowledge
|
|
27
|
+
|
|
28
|
+
# The domain this distribution implements. It does NOT decide any document's
|
|
29
|
+
# owning domain -- that is resolved per project (`default_domain:` in the docs
|
|
30
|
+
# root's README) and per artifact (`domain:`), so the same tree gets the same
|
|
31
|
+
# verdict from every installed distribution. What it decides is which portable
|
|
32
|
+
# checks a document may import here by name; the rest warn as unavailable.
|
|
33
|
+
DOMAIN = "code"
|
|
34
|
+
|
|
35
|
+
sdlc_core.set_entry_point(DOMAIN, provides=("code", "knowledge"))
|
|
36
|
+
|
|
37
|
+
# What this distribution carries. The shared battery reads it; the spine
|
|
38
|
+
# capabilities are not optional, and a shared test refuses a profile that drops one.
|
|
39
|
+
sdlc_core.set_profile(
|
|
40
|
+
skill_name="agentic-sdlc",
|
|
41
|
+
unit_noun="feature",
|
|
42
|
+
support_files=("templates.md", "architect.md", "guides.md", "vision.md", "tdd.md",
|
|
43
|
+
"debugging.md", "elicitation.md", "review.md", "dispatch.md",
|
|
44
|
+
"routing.md", "hybrid.md", "ENFORCEMENT.md", "memory.md"),
|
|
45
|
+
capabilities=(
|
|
46
|
+
# spine
|
|
47
|
+
"triage", "write_triggers", "workstream_registry", "vision_gate",
|
|
48
|
+
"design_review_gate", "guide_router", "worktree_hygiene",
|
|
49
|
+
# code overlay
|
|
50
|
+
"architect_pass", "interaction_contract", "comprehension_guides", "tdd",
|
|
51
|
+
"subagent_dispatch", "legacy_narrative_handoff", "question_discipline",
|
|
52
|
+
),
|
|
53
|
+
design_gate_between=("### 3. Request Analysis", "### 4. Development and Testing"),
|
|
54
|
+
remind_line=(
|
|
55
|
+
"first decide if this skill governs the work; if yes, LOAD it once -- an "
|
|
56
|
+
"unread protocol cannot be applied. Declare the level (L1/L2/L3/Spike) "
|
|
57
|
+
"and the guide-router verdict before acting; an imperative is a request "
|
|
58
|
+
"to triage. Name the mechanism before fixing the first defect you can "
|
|
59
|
+
"measure -- symptom patches recur and stack. Replay governing text -- "
|
|
60
|
+
"doctrine, a prompt, a schema -- against the case that motivated it: red "
|
|
61
|
+
"under the old text, green under the new."
|
|
62
|
+
),
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def main(argv=None):
|
|
67
|
+
return knowledge.main(argv)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
if __name__ == "__main__":
|
|
71
|
+
sys.exit(main())
|
|
@@ -203,6 +203,11 @@ DOMAINS = {
|
|
|
203
203
|
"risk_label": "## Threat Map / Plan Risks",
|
|
204
204
|
"id_prefix": "M-",
|
|
205
205
|
},
|
|
206
|
+
"course": {
|
|
207
|
+
"risk_section": ("## Learning and Content Risks",),
|
|
208
|
+
"risk_label": "## Learning and Content Risks",
|
|
209
|
+
"id_prefix": "C-",
|
|
210
|
+
},
|
|
206
211
|
}
|
|
207
212
|
# Absent everything -- no `default_domain:` line, no `domain:` field -- a project is
|
|
208
213
|
# `code`. That is what every project created before this field existed already is,
|
|
@@ -1298,7 +1303,7 @@ def cmd_validate(root, strict=False, hybrid=False):
|
|
|
1298
1303
|
"have the user validate it")
|
|
1299
1304
|
|
|
1300
1305
|
# ANALYSIS: frontmatter and mandatory sections
|
|
1301
|
-
# Ids are unique WITHIN a domain (prefixes F-/K-/M- keep them apart in practice):
|
|
1306
|
+
# Ids are unique WITHIN a domain (prefixes F-/K-/M-/C- keep them apart in practice):
|
|
1302
1307
|
# two lenses over one tree must not collide on a number neither of them chose.
|
|
1303
1308
|
seen_ids = {}
|
|
1304
1309
|
default_domain = project_default_domain(root)
|
|
@@ -1349,10 +1354,10 @@ def cmd_validate(root, strict=False, hybrid=False):
|
|
|
1349
1354
|
"doing the work it triggers")
|
|
1350
1355
|
# comment-stripped, anchored: a '<!-- TODO: the ## Capability Ledger -->'
|
|
1351
1356
|
# must not read as the section being present
|
|
1352
|
-
# Hybrid: the design lives in devPNT and
|
|
1353
|
-
#
|
|
1354
|
-
#
|
|
1355
|
-
#
|
|
1357
|
+
# Hybrid: the design lives in devPNT, and the agent review of it (the
|
|
1358
|
+
# same review.md review, run before the proposal) logs a row keyed on
|
|
1359
|
+
# its e_isp_/e_tdd_ doc_key, not on this filename -- so firing here
|
|
1360
|
+
# would be a permanent, unfixable false positive.
|
|
1356
1361
|
if not hybrid and design_review_due(meta) and not review_logged(root, p.name):
|
|
1357
1362
|
advisories.append(f"{rel}: L3 in implementation with no design-review row in "
|
|
1358
1363
|
f"{review_log_rel()} -- the design was reviewed by nobody but its "
|
|
@@ -1864,15 +1869,26 @@ def print_orient_hook_note(root):
|
|
|
1864
1869
|
pass # detection must never break check
|
|
1865
1870
|
|
|
1866
1871
|
|
|
1867
|
-
def cmd_check(root, strict=False, hybrid=False):
|
|
1872
|
+
def cmd_check(root, strict=False, hybrid=False, extra_validate=None, extra_sections=()):
|
|
1873
|
+
"""An overlay adds its checks through the two hooks, never after the call:
|
|
1874
|
+
the summary line is the verdict, so every check that can fail runs before
|
|
1875
|
+
it. `extra_validate()` folds into the validate stage; each
|
|
1876
|
+
(title, fn) in `extra_sections` gets its own banner and summary rc."""
|
|
1868
1877
|
print("===== validate =====")
|
|
1869
1878
|
rc_v = cmd_validate(root, strict=strict, hybrid=hybrid)
|
|
1879
|
+
if extra_validate is not None:
|
|
1880
|
+
rc_v = max(rc_v, extra_validate())
|
|
1870
1881
|
print("\n===== stale =====")
|
|
1871
1882
|
rc_s = cmd_stale(root, hybrid=hybrid)
|
|
1872
|
-
|
|
1873
|
-
|
|
1883
|
+
rcs = [("validate", rc_v), ("stale", rc_s)]
|
|
1884
|
+
for title, fn in extra_sections:
|
|
1885
|
+
print(f"\n===== {title} =====")
|
|
1886
|
+
rcs.append((title, fn()))
|
|
1887
|
+
failed = any(rc for _, rc in rcs)
|
|
1888
|
+
print(f"\ncheck: {'NOT CLEAN' if failed else 'CLEAN'} "
|
|
1889
|
+
f"({', '.join(f'{title} rc={rc}' for title, rc in rcs)})")
|
|
1874
1890
|
print_orient_hook_note(root)
|
|
1875
|
-
return 1 if
|
|
1891
|
+
return 1 if failed else 0
|
|
1876
1892
|
|
|
1877
1893
|
|
|
1878
1894
|
# --------------------------------------------------------------------- gate
|
|
@@ -14,14 +14,14 @@ Every durable canonical document opens with this frontmatter: it feeds the gener
|
|
|
14
14
|
description: One line — what the document is and when to read it.
|
|
15
15
|
status: CURRENT # CURRENT | SUPERSEDED | DRAFT | DEPRECATED
|
|
16
16
|
supersedes: old_doc.md # only if it replaces another canonical doc
|
|
17
|
-
domain: code # optional — code | knowledge | marketing
|
|
17
|
+
domain: code # optional — code | knowledge | marketing | course
|
|
18
18
|
---
|
|
19
19
|
# Document Title
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
When a doc replaces another: the new one declares `supersedes:`, the old one switches to `status: SUPERSEDED` (it stays as history, do not delete it). `sdlc_check.py validate` warns if `status` is missing or if a superseded doc is still `CURRENT`.
|
|
23
23
|
|
|
24
|
-
**`domain:` — write it only when it says something.** It names the domain whose fidelity discipline the document was written under, and it *records* an answer the work already has; it never decides one. Omit it and the project default applies (`default_domain:` in `ai_docs/README.md`, absent → `code`), so a single-domain project never writes the field at all.
|
|
24
|
+
**`domain:` — write it only when it says something.** It names the domain whose fidelity discipline the document was written under, and it *records* an answer the work already has; it never decides one. Omit it and the project default applies (`default_domain:` in `ai_docs/README.md`, absent → `code`), so a single-domain project never writes the field at all. Project-wide documents under `vision/` sit above the split. A course's feature Vision is the exception: `vision/features/VISION_course_<slug>.md` carries `domain: course` explicitly, even in a marketing-default project, so its owner remains unambiguous. In a mixed project, a wrong or forgotten field surfaces as a validation error on the missing mandatory risk section — never as a silent pass.
|
|
25
25
|
|
|
26
26
|
## ai_docs/reference/GUIDE_[topic].md
|
|
27
27
|
|
|
@@ -216,7 +216,7 @@ Only for features spanning multiple ANALYSIS documents or multiple milestones: o
|
|
|
216
216
|
|
|
217
217
|
The frontmatter is the source of truth for the feature state (the `features_history.md` index is generated from it).
|
|
218
218
|
|
|
219
|
-
`domain:` and `checks:` are optional and only earn their place in a project where more than one lens is installed
|
|
219
|
+
`domain:` and `checks:` are optional for ordinary analyses and only earn their place in a project where more than one lens is installed; a course ANALYSIS always declares `domain: course`. `checks:` names **portable checks** imported from another domain — e.g. `domain: knowledge` with `checks: [marketing.funnel]`. An imported check can only ADD findings, never relax what the owning domain requires, so importing one is always safe; naming a check this installation does not carry produces a visible warning, never a silent pass. `id:` is unique **within a domain**, and its prefix says which: `F-` code, `K-` knowledge, `M-` marketing, `C-` course. Projects that predate the prefixes keep their `F-` ids — uniqueness was already scoped to the one domain they have.
|
|
220
220
|
|
|
221
221
|
```markdown
|
|
222
222
|
---
|
|
@@ -226,7 +226,7 @@ status: PLANNED
|
|
|
226
226
|
level: L3
|
|
227
227
|
start_date: 2026-06-11
|
|
228
228
|
end_date:
|
|
229
|
-
domain: code # optional — code | knowledge | marketing
|
|
229
|
+
domain: code # optional — code | knowledge | marketing | course
|
|
230
230
|
checks: [marketing.funnel] # optional — extra portable checks to run on this document
|
|
231
231
|
---
|
|
232
232
|
# Feature Analysis: [Name]
|
|
@@ -501,7 +501,7 @@ One row per completed review (`review.md` §When a review is due). Append-only;
|
|
|
501
501
|
is the record that the gate ran and what it was worth. **One schema for both
|
|
502
502
|
modes** — one required CORE (`date`, `doc_key`, `tier`, `model`, `findings_raised`,
|
|
503
503
|
`findings_real`, `verdict`, `revise_rounds`) plus each mode's own realization
|
|
504
|
-
columns: Standalone adds `reviewer`, a Hybrid
|
|
504
|
+
columns: Standalone adds `reviewer`, a Hybrid row adds `instrument` and
|
|
505
505
|
`notes` and carries no `reviewer` at all. Both modes write this same file.
|
|
506
506
|
|
|
507
507
|
```markdown
|