@antoneeo/agentic-sdlc-skill 1.36.0 → 1.37.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.
@@ -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)
@@ -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; omit in a single-domain project
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. Documents under `vision/` sit above the split and take no `domain:`. 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.
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 (see the canonical-header note above for how an omitted `domain:` resolves). `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. Projects that predate the prefixes keep their `F-` ids — uniqueness was already scoped to the one domain they have.
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]