dna-sdk 0.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/LICENSE +21 -0
- package/README.md +58 -0
- package/dist/adapters/embedding/onnx.d.ts +32 -0
- package/dist/adapters/embedding/onnx.js +51 -0
- package/dist/adapters/filesystem/cache.d.ts +16 -0
- package/dist/adapters/filesystem/cache.js +113 -0
- package/dist/adapters/filesystem/index.d.ts +2 -0
- package/dist/adapters/filesystem/index.js +2 -0
- package/dist/adapters/filesystem/source.d.ts +82 -0
- package/dist/adapters/filesystem/source.js +357 -0
- package/dist/adapters/postgres/index.d.ts +2 -0
- package/dist/adapters/postgres/index.js +2 -0
- package/dist/adapters/postgres/migrations.d.ts +14 -0
- package/dist/adapters/postgres/migrations.js +88 -0
- package/dist/adapters/postgres/source.d.ts +172 -0
- package/dist/adapters/postgres/source.js +569 -0
- package/dist/adapters/resolvers/github.d.ts +12 -0
- package/dist/adapters/resolvers/github.js +47 -0
- package/dist/adapters/resolvers/http.d.ts +22 -0
- package/dist/adapters/resolvers/http.js +145 -0
- package/dist/adapters/resolvers/index.d.ts +3 -0
- package/dist/adapters/resolvers/index.js +3 -0
- package/dist/adapters/resolvers/local.d.ts +24 -0
- package/dist/adapters/resolvers/local.js +132 -0
- package/dist/adapters/search/driver.d.ts +45 -0
- package/dist/adapters/search/driver.js +138 -0
- package/dist/adapters/search/migrations.d.ts +26 -0
- package/dist/adapters/search/migrations.js +58 -0
- package/dist/adapters/search/rrf.d.ts +23 -0
- package/dist/adapters/search/rrf.js +42 -0
- package/dist/adapters/search/sqlite-vec.d.ts +66 -0
- package/dist/adapters/search/sqlite-vec.js +294 -0
- package/dist/bootstrap.d.ts +45 -0
- package/dist/bootstrap.js +134 -0
- package/dist/extensions/agentskills/DOCS.md +18 -0
- package/dist/extensions/agentskills.d.ts +28 -0
- package/dist/extensions/agentskills.js +252 -0
- package/dist/extensions/agentsmd/DOCS.md +18 -0
- package/dist/extensions/agentsmd.d.ts +22 -0
- package/dist/extensions/agentsmd.js +170 -0
- package/dist/extensions/audit/kinds/audit-log.kind.yaml +148 -0
- package/dist/extensions/audit.d.ts +25 -0
- package/dist/extensions/audit.js +62 -0
- package/dist/extensions/automation/kinds/automation.kind.yaml +296 -0
- package/dist/extensions/automation/query.d.ts +49 -0
- package/dist/extensions/automation/query.js +77 -0
- package/dist/extensions/automation/write-guards.d.ts +59 -0
- package/dist/extensions/automation/write-guards.js +153 -0
- package/dist/extensions/automation.d.ts +41 -0
- package/dist/extensions/automation.js +54 -0
- package/dist/extensions/collab.d.ts +16 -0
- package/dist/extensions/collab.js +79 -0
- package/dist/extensions/doc/kinds/doc.kind.yaml +118 -0
- package/dist/extensions/doc.d.ts +25 -0
- package/dist/extensions/doc.js +10 -0
- package/dist/extensions/eval/kinds/eval-baseline.kind.yaml +65 -0
- package/dist/extensions/eval/kinds/eval-case.kind.yaml +140 -0
- package/dist/extensions/eval/kinds/eval-run.kind.yaml +134 -0
- package/dist/extensions/eval/kinds/eval-suite.kind.yaml +87 -0
- package/dist/extensions/eval.d.ts +24 -0
- package/dist/extensions/eval.js +31 -0
- package/dist/extensions/evidence/kinds/evidence.kind.yaml +92 -0
- package/dist/extensions/evidence.d.ts +17 -0
- package/dist/extensions/evidence.js +94 -0
- package/dist/extensions/federation.d.ts +22 -0
- package/dist/extensions/federation.js +173 -0
- package/dist/extensions/guardrails/DOCS.md +20 -0
- package/dist/extensions/guardrails.d.ts +31 -0
- package/dist/extensions/guardrails.js +228 -0
- package/dist/extensions/helix/DOCS-Actor.md +20 -0
- package/dist/extensions/helix/DOCS-Agent.md +20 -0
- package/dist/extensions/helix/DOCS-UseCase.md +20 -0
- package/dist/extensions/helix/layers.d.ts +12 -0
- package/dist/extensions/helix/layers.js +18 -0
- package/dist/extensions/helix/write-guards.d.ts +70 -0
- package/dist/extensions/helix/write-guards.js +172 -0
- package/dist/extensions/helix.d.ts +29 -0
- package/dist/extensions/helix.js +963 -0
- package/dist/extensions/helix_extras.d.ts +124 -0
- package/dist/extensions/helix_extras.js +328 -0
- package/dist/extensions/hooks.d.ts +31 -0
- package/dist/extensions/hooks.js +247 -0
- package/dist/extensions/kinddef/DOCS.md +24 -0
- package/dist/extensions/kinddef.d.ts +40 -0
- package/dist/extensions/kinddef.js +171 -0
- package/dist/extensions/lesson.d.ts +6 -0
- package/dist/extensions/lesson.js +194 -0
- package/dist/extensions/modelreg/kinds/model-profile.kind.yaml +155 -0
- package/dist/extensions/modelreg.d.ts +30 -0
- package/dist/extensions/modelreg.js +38 -0
- package/dist/extensions/recognizer.d.ts +34 -0
- package/dist/extensions/recognizer.js +272 -0
- package/dist/extensions/research.d.ts +32 -0
- package/dist/extensions/research.js +292 -0
- package/dist/extensions/safety.d.ts +33 -0
- package/dist/extensions/safety.js +230 -0
- package/dist/extensions/sdlc/kinds/adr.kind.yaml +136 -0
- package/dist/extensions/sdlc/kinds/archive-proposal.kind.yaml +107 -0
- package/dist/extensions/sdlc/kinds/changelog.kind.yaml +108 -0
- package/dist/extensions/sdlc/kinds/cognitive-policy.kind.yaml +470 -0
- package/dist/extensions/sdlc/kinds/forecast.kind.yaml +125 -0
- package/dist/extensions/sdlc/kinds/insight.kind.yaml +87 -0
- package/dist/extensions/sdlc/kinds/kaizen.kind.yaml +106 -0
- package/dist/extensions/sdlc/kinds/lesson-learned.kind.yaml +270 -0
- package/dist/extensions/sdlc/kinds/narrative.kind.yaml +189 -0
- package/dist/extensions/sdlc/kinds/pattern-insight.kind.yaml +204 -0
- package/dist/extensions/sdlc/kinds/postmortem.kind.yaml +168 -0
- package/dist/extensions/sdlc/kinds/pre-mortem.kind.yaml +145 -0
- package/dist/extensions/sdlc/kinds/prompt-template.kind.yaml +109 -0
- package/dist/extensions/sdlc/kinds/retrospective.kind.yaml +186 -0
- package/dist/extensions/sdlc/kinds/risk-register.kind.yaml +178 -0
- package/dist/extensions/sdlc/kinds/saved-view.kind.yaml +127 -0
- package/dist/extensions/sdlc/kinds/status-report.kind.yaml +129 -0
- package/dist/extensions/sdlc/kinds/synthesis-run.kind.yaml +279 -0
- package/dist/extensions/sdlc/kinds/synthesizer-state.kind.yaml +196 -0
- package/dist/extensions/sdlc/kinds/workflow-event.kind.yaml +195 -0
- package/dist/extensions/sdlc.d.ts +32 -0
- package/dist/extensions/sdlc.js +1318 -0
- package/dist/extensions/soulspec/DOCS.md +19 -0
- package/dist/extensions/soulspec.d.ts +22 -0
- package/dist/extensions/soulspec.js +287 -0
- package/dist/extensions/tenant.d.ts +6 -0
- package/dist/extensions/tenant.js +291 -0
- package/dist/extensions/testkit.d.ts +24 -0
- package/dist/extensions/testkit.js +211 -0
- package/dist/index.d.ts +80 -0
- package/dist/index.js +102 -0
- package/dist/kernel/_text.d.ts +28 -0
- package/dist/kernel/_text.js +42 -0
- package/dist/kernel/bundle-handle.d.ts +83 -0
- package/dist/kernel/bundle-handle.js +184 -0
- package/dist/kernel/capabilities.d.ts +157 -0
- package/dist/kernel/capabilities.js +109 -0
- package/dist/kernel/collaborator-ports.d.ts +91 -0
- package/dist/kernel/collaborator-ports.js +1 -0
- package/dist/kernel/composition-resolver.d.ts +215 -0
- package/dist/kernel/composition-resolver.js +558 -0
- package/dist/kernel/composition.d.ts +10 -0
- package/dist/kernel/composition.js +1 -0
- package/dist/kernel/descriptor-loader.d.ts +13 -0
- package/dist/kernel/descriptor-loader.js +48 -0
- package/dist/kernel/document.d.ts +43 -0
- package/dist/kernel/document.js +71 -0
- package/dist/kernel/embedding.d.ts +28 -0
- package/dist/kernel/embedding.js +78 -0
- package/dist/kernel/errors.d.ts +62 -0
- package/dist/kernel/errors.js +82 -0
- package/dist/kernel/events.d.ts +6 -0
- package/dist/kernel/events.js +21 -0
- package/dist/kernel/evidence-capture.d.ts +69 -0
- package/dist/kernel/evidence-capture.js +138 -0
- package/dist/kernel/fs.d.ts +20 -0
- package/dist/kernel/fs.js +128 -0
- package/dist/kernel/generic-rw.d.ts +33 -0
- package/dist/kernel/generic-rw.js +235 -0
- package/dist/kernel/hooks.d.ts +172 -0
- package/dist/kernel/hooks.js +256 -0
- package/dist/kernel/index.d.ts +624 -0
- package/dist/kernel/index.js +1638 -0
- package/dist/kernel/instance.d.ts +211 -0
- package/dist/kernel/instance.js +487 -0
- package/dist/kernel/kind-registry.d.ts +183 -0
- package/dist/kernel/kind-registry.js +710 -0
- package/dist/kernel/kind_base.d.ts +106 -0
- package/dist/kernel/kind_base.js +244 -0
- package/dist/kernel/layer-resolver.d.ts +48 -0
- package/dist/kernel/layer-resolver.js +284 -0
- package/dist/kernel/lock-manager.d.ts +21 -0
- package/dist/kernel/lock-manager.js +43 -0
- package/dist/kernel/lock.d.ts +38 -0
- package/dist/kernel/lock.js +115 -0
- package/dist/kernel/meta.d.ts +135 -0
- package/dist/kernel/meta.js +817 -0
- package/dist/kernel/models.d.ts +3089 -0
- package/dist/kernel/models.js +764 -0
- package/dist/kernel/navigator.d.ts +36 -0
- package/dist/kernel/navigator.js +132 -0
- package/dist/kernel/port-surface.d.ts +33 -0
- package/dist/kernel/port-surface.js +180 -0
- package/dist/kernel/preview.d.ts +60 -0
- package/dist/kernel/preview.js +54 -0
- package/dist/kernel/prompt-budget.d.ts +39 -0
- package/dist/kernel/prompt-budget.js +43 -0
- package/dist/kernel/prompt-builder.d.ts +25 -0
- package/dist/kernel/prompt-builder.js +237 -0
- package/dist/kernel/protocols.d.ts +751 -0
- package/dist/kernel/protocols.js +493 -0
- package/dist/kernel/reports.d.ts +26 -0
- package/dist/kernel/reports.js +215 -0
- package/dist/kernel/resolver.d.ts +146 -0
- package/dist/kernel/resolver.js +232 -0
- package/dist/kernel/resource.d.ts +57 -0
- package/dist/kernel/resource.js +97 -0
- package/dist/kernel/runtime.d.ts +16 -0
- package/dist/kernel/runtime.js +18 -0
- package/dist/kernel/safety-scanner.d.ts +38 -0
- package/dist/kernel/safety-scanner.js +228 -0
- package/dist/kernel/serialize-to-files.d.ts +29 -0
- package/dist/kernel/serialize-to-files.js +23 -0
- package/dist/kernel/spec-access.d.ts +23 -0
- package/dist/kernel/spec-access.js +40 -0
- package/dist/kernel/studio_ui.d.ts +88 -0
- package/dist/kernel/studio_ui.js +135 -0
- package/dist/kernel/templates.d.ts +77 -0
- package/dist/kernel/templates.js +116 -0
- package/dist/kernel/tool-registry.d.ts +52 -0
- package/dist/kernel/tool-registry.js +89 -0
- package/dist/kernel/write-pipeline.d.ts +65 -0
- package/dist/kernel/write-pipeline.js +271 -0
- package/dist/kernel/writer-helpers.d.ts +24 -0
- package/dist/kernel/writer-helpers.js +42 -0
- package/dist/memory/decay.d.ts +31 -0
- package/dist/memory/decay.js +97 -0
- package/dist/memory/ecphory.d.ts +25 -0
- package/dist/memory/ecphory.js +178 -0
- package/dist/memory/encodingContext.d.ts +21 -0
- package/dist/memory/encodingContext.js +62 -0
- package/dist/memory/index.d.ts +23 -0
- package/dist/memory/index.js +23 -0
- package/dist/memory/memoryType.d.ts +7 -0
- package/dist/memory/memoryType.js +24 -0
- package/dist/memory/policy.d.ts +35 -0
- package/dist/memory/policy.js +35 -0
- package/dist/memory/retrieval.d.ts +21 -0
- package/dist/memory/retrieval.js +145 -0
- package/dist/testing/index.d.ts +8 -0
- package/dist/testing/index.js +8 -0
- package/dist/testing/recordSearchConformance.d.ts +43 -0
- package/dist/testing/recordSearchConformance.js +147 -0
- package/dist/viz/ascii.d.ts +7 -0
- package/dist/viz/ascii.js +60 -0
- package/dist/viz/health.d.ts +8 -0
- package/dist/viz/health.js +161 -0
- package/dist/viz/index.d.ts +10 -0
- package/dist/viz/index.js +10 -0
- package/dist/viz/matrix.d.ts +8 -0
- package/dist/viz/matrix.js +84 -0
- package/dist/viz/mermaid.d.ts +38 -0
- package/dist/viz/mermaid.js +706 -0
- package/package.json +82 -0
|
@@ -0,0 +1,1318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SdlcExtension — software-development lifecycle Kinds.
|
|
3
|
+
*
|
|
4
|
+
* Seven Kinds for declarative product/engineering management as YAML/markdown:
|
|
5
|
+
*
|
|
6
|
+
* - Roadmap (sdlc-roadmap) — top-level, lists epics across horizons
|
|
7
|
+
* - Epic (sdlc-epic) — Jira/ADO-aligned aggregation umbrella; optional target date
|
|
8
|
+
* - Feature (sdlc-feature) — shippable unit; implements UseCases
|
|
9
|
+
* - Story (sdlc-story) — granular task with owner + estimate
|
|
10
|
+
* - Issue (sdlc-issue) — bug/enhancement/question/task; can link to a Finding
|
|
11
|
+
* - Spec (sdlc-spec) — top-level design artifact (ADR-style)
|
|
12
|
+
* - Plan (sdlc-plan) — implementation plan, child of a Spec
|
|
13
|
+
*
|
|
14
|
+
* 1:1 parity with Python ``dna.extensions.sdlc`` for the KIND
|
|
15
|
+
* surface (registration, descriptors, schemas, write-guards).
|
|
16
|
+
*
|
|
17
|
+
* Known Py-only helpers (verified 2026-07-08, s-dna-sdlc-cli-extraction —
|
|
18
|
+
* documented here on purpose, not silently): ``journey_derive.py`` (the
|
|
19
|
+
* derived per-work-item journey computation consumed by the server journey/
|
|
20
|
+
* focus routes and the CLI) and ``work_item_outputs.py`` (produces[]
|
|
21
|
+
* resolution) have NO TS twin. They are pure read-side helpers OVER Kind
|
|
22
|
+
* data, not Kind behavior — port them when a TS consumer needs the derived
|
|
23
|
+
* journey, and add their members to the parity fixtures at that point.
|
|
24
|
+
*
|
|
25
|
+
* v1.3 BREAKING: Milestone Kind renamed to Epic.
|
|
26
|
+
*/
|
|
27
|
+
import { KindBase } from "../kernel/kind_base.js";
|
|
28
|
+
import { SD, TenantScope } from "../kernel/protocols.js";
|
|
29
|
+
import { loadDescriptors } from "../kernel/descriptor-loader.js";
|
|
30
|
+
const API_VERSION = "github.com/ruinosus/dna/sdlc/v1";
|
|
31
|
+
// v1.3: MILESTONE_STATUSES → EPIC_STATUSES (Jira/ADO alignment).
|
|
32
|
+
const EPIC_STATUSES = ["planning", "in-progress", "done", "cancelled", "deprecated"];
|
|
33
|
+
const FEATURE_STATUSES = ["discovery", "in-development", "done", "cancelled", "blocked"];
|
|
34
|
+
// 2026-05-26 — rec-triage-as-status (Py twin): needs-triage prepended,
|
|
35
|
+
// deferred antes de cancelled. Stories existentes em `todo` permanecem.
|
|
36
|
+
const STORY_STATUSES = [
|
|
37
|
+
"needs-triage",
|
|
38
|
+
"todo",
|
|
39
|
+
"in-progress",
|
|
40
|
+
"review",
|
|
41
|
+
"done",
|
|
42
|
+
"blocked",
|
|
43
|
+
"deferred",
|
|
44
|
+
"cancelled",
|
|
45
|
+
];
|
|
46
|
+
const ISSUE_STATUSES = ["open", "triaged", "in-progress", "resolved", "wont-fix", "duplicate"];
|
|
47
|
+
const ISSUE_TYPES = ["bug", "enhancement", "question", "task"];
|
|
48
|
+
const ISSUE_SEVERITIES = ["low", "medium", "high", "critical"];
|
|
49
|
+
// v1.13: the Kaizen observation arc (observed → routed → resolved) lives
|
|
50
|
+
// ONLY in the descriptor sdlc/kinds/kaizen.kind.yaml since F3 P2 — the
|
|
51
|
+
// enum is the schema's `status.enum`; CLI call sites use literals.
|
|
52
|
+
// v1.5: shared priority enum across Story/Feature/Epic/Issue (Jira-aligned).
|
|
53
|
+
const PRIORITIES = ["highest", "high", "medium", "low", "lowest"];
|
|
54
|
+
// Universal journey phases — additive layer over Story/Feature/Epic
|
|
55
|
+
// status, Spec phase, etc. Maps to Superpowers / BMAD / Spec Kit / Kiro.
|
|
56
|
+
const JOURNEY_PHASES = ["discover", "specify", "plan", "build", "verify", "reflect"];
|
|
57
|
+
// v1.6: Activity Timeline event types — RECOGNIZED names, but the schema
|
|
58
|
+
// deliberately does NOT close the vocabulary (no enum): documentation-style
|
|
59
|
+
// so future types just work. Load-bearing since s-write-path-validation
|
|
60
|
+
// (i-008): writes really validate now, and the CLI already stamps types
|
|
61
|
+
// beyond these five ("pr_opened" from `dna sdlc story pr`).
|
|
62
|
+
const TIMELINE_TYPES = [
|
|
63
|
+
"status_change", "groom", "comment", "decision", "artifact_produced",
|
|
64
|
+
];
|
|
65
|
+
const TIMELINE_SOURCES = [
|
|
66
|
+
"cli", "studio", "agent-session-extracted", "system",
|
|
67
|
+
];
|
|
68
|
+
// produces[] — a work item is a HUB of the artifacts it produced, of ANY
|
|
69
|
+
// Kind (mirror of AgentSession.produced_artifacts + the Python
|
|
70
|
+
// _produces_field_schema). Read by the derived journey + FOCUS panel +
|
|
71
|
+
// `dna sdlc produces list` via resolveWorkItemOutputs (produces ∪ legacy).
|
|
72
|
+
// Parity: keep byte-aligned with packages/sdk-py .../sdlc/__init__.py.
|
|
73
|
+
function producesFieldSchema() {
|
|
74
|
+
return {
|
|
75
|
+
type: "array",
|
|
76
|
+
description: "Artifacts this work item produced — any Kind (hub).",
|
|
77
|
+
items: {
|
|
78
|
+
type: "object",
|
|
79
|
+
required: ["kind", "name"],
|
|
80
|
+
additionalProperties: true,
|
|
81
|
+
properties: {
|
|
82
|
+
kind: { type: "string", description: "Artifact Kind (any)." },
|
|
83
|
+
name: { type: "string", description: "Artifact doc name." },
|
|
84
|
+
role: { type: "string", description: "Optional role hint (e.g. visual-spec, plan, investigation)." },
|
|
85
|
+
at: { type: "string", format: "date-time" },
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function timelineFieldSchema() {
|
|
91
|
+
return {
|
|
92
|
+
type: "array",
|
|
93
|
+
description: "Append-only activity log. Auto-stamped by the CLI on every " +
|
|
94
|
+
"status flip / groom / artifact write; populated by AgentSession " +
|
|
95
|
+
"capture for decision + artifact_produced events.",
|
|
96
|
+
items: {
|
|
97
|
+
type: "object",
|
|
98
|
+
required: ["at", "actor", "type"],
|
|
99
|
+
additionalProperties: true,
|
|
100
|
+
properties: {
|
|
101
|
+
at: { type: "string", format: "date-time" },
|
|
102
|
+
actor: { type: "string" },
|
|
103
|
+
type: {
|
|
104
|
+
type: "string",
|
|
105
|
+
description: "Event type. Recognized: " + TIMELINE_TYPES.join(", ") +
|
|
106
|
+
" (open vocabulary — new types are additive, e.g. pr_opened).",
|
|
107
|
+
},
|
|
108
|
+
source: { type: "string", enum: [...TIMELINE_SOURCES] },
|
|
109
|
+
from: { type: "string" },
|
|
110
|
+
to: { type: "string" },
|
|
111
|
+
fields: { type: "object" },
|
|
112
|
+
summary: { type: "string" },
|
|
113
|
+
excerpt: { type: "string" },
|
|
114
|
+
paths: { type: "array", items: { type: "string" } },
|
|
115
|
+
commit_ref: { type: "string" },
|
|
116
|
+
session_ref: { type: "string" },
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
// Roadmap
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
class RoadmapKind extends KindBase {
|
|
125
|
+
apiVersion = API_VERSION;
|
|
126
|
+
scope = TenantScope.GLOBAL; // SDLC primitives are project-level
|
|
127
|
+
kind = "Roadmap";
|
|
128
|
+
alias = "sdlc-roadmap";
|
|
129
|
+
scopeInheritable = false;
|
|
130
|
+
origin = "github.com/ruinosus/dna/sdlc";
|
|
131
|
+
isPromptTarget = false;
|
|
132
|
+
promptTargetPriority = 0;
|
|
133
|
+
flattenInContext = false;
|
|
134
|
+
plane = "record";
|
|
135
|
+
storage = SD.yaml("roadmaps");
|
|
136
|
+
graphStyle = { fill: "#0EA5E9", stroke: "#0284C7", textColor: "#fff" };
|
|
137
|
+
asciiIcon = "🗺️";
|
|
138
|
+
displayLabel = "Roadmaps";
|
|
139
|
+
docs = "A Roadmap groups Epics across time horizons (e.g. Q1 2026, " +
|
|
140
|
+
"Q2 2026). Pure organizational doc — no status of its own; the " +
|
|
141
|
+
"rolled-up status comes from the Epics it lists.";
|
|
142
|
+
depFilters() { return { epics: "sdlc-epic" }; }
|
|
143
|
+
schema() {
|
|
144
|
+
return {
|
|
145
|
+
type: "object",
|
|
146
|
+
required: ["description", "horizons"],
|
|
147
|
+
additionalProperties: true,
|
|
148
|
+
properties: {
|
|
149
|
+
description: { type: "string" },
|
|
150
|
+
owner_team: { type: "string" },
|
|
151
|
+
horizons: {
|
|
152
|
+
type: "array",
|
|
153
|
+
items: {
|
|
154
|
+
type: "object",
|
|
155
|
+
required: ["label", "epics"],
|
|
156
|
+
properties: {
|
|
157
|
+
label: { type: "string", description: "e.g. 'Q1 2026'" },
|
|
158
|
+
start_date: { type: "string", format: "date" },
|
|
159
|
+
end_date: { type: "string", format: "date" },
|
|
160
|
+
epics: {
|
|
161
|
+
type: "array",
|
|
162
|
+
items: { type: "string" },
|
|
163
|
+
description: "Names of Epic docs in this horizon",
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
links: {
|
|
169
|
+
type: "array",
|
|
170
|
+
items: { type: "string" },
|
|
171
|
+
description: "External URLs (Confluence, Notion, etc.)",
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
summary(doc) {
|
|
177
|
+
const spec = (doc.spec ?? {});
|
|
178
|
+
const horizons = spec.horizons ?? [];
|
|
179
|
+
const total = horizons.reduce((sum, h) => sum + (h.epics?.length ?? 0), 0);
|
|
180
|
+
const desc = spec.description ?? "";
|
|
181
|
+
return {
|
|
182
|
+
description: desc.slice(0, 80),
|
|
183
|
+
horizons: horizons.length,
|
|
184
|
+
epics: total,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
// ---------------------------------------------------------------------------
|
|
189
|
+
// Epic — Jira/ADO-aligned aggregation umbrella (was Milestone in v1.2)
|
|
190
|
+
// ---------------------------------------------------------------------------
|
|
191
|
+
class EpicKind extends KindBase {
|
|
192
|
+
apiVersion = API_VERSION;
|
|
193
|
+
scope = TenantScope.GLOBAL; // SDLC primitives are project-level
|
|
194
|
+
kind = "Epic";
|
|
195
|
+
alias = "sdlc-epic";
|
|
196
|
+
origin = "github.com/ruinosus/dna/sdlc";
|
|
197
|
+
isPromptTarget = false;
|
|
198
|
+
promptTargetPriority = 0;
|
|
199
|
+
flattenInContext = false;
|
|
200
|
+
plane = "record";
|
|
201
|
+
storage = SD.yaml("epics");
|
|
202
|
+
graphStyle = { fill: "#8B5CF6", stroke: "#7C3AED", textColor: "#fff" };
|
|
203
|
+
asciiIcon = "🎯";
|
|
204
|
+
displayLabel = "Epics";
|
|
205
|
+
docs = "An Epic groups Features under a single business goal " +
|
|
206
|
+
"(Jira/ADO terminology). May optionally carry a target_date when " +
|
|
207
|
+
"the Epic doubles as a dated release; otherwise it's a pure " +
|
|
208
|
+
"aggregation umbrella. status: planning → in-progress → done.";
|
|
209
|
+
depFilters() { return { features: "sdlc-feature" }; }
|
|
210
|
+
schema() {
|
|
211
|
+
return {
|
|
212
|
+
type: "object",
|
|
213
|
+
required: ["status"], // v1.3: target_date no longer required
|
|
214
|
+
additionalProperties: true,
|
|
215
|
+
properties: {
|
|
216
|
+
title: {
|
|
217
|
+
type: "string",
|
|
218
|
+
description: "Human-readable display name (Jira 'summary').",
|
|
219
|
+
},
|
|
220
|
+
description: { type: "string" },
|
|
221
|
+
target_date: { type: "string", format: "date" },
|
|
222
|
+
status: { type: "string", enum: [...EPIC_STATUSES] },
|
|
223
|
+
target_package: {
|
|
224
|
+
type: "string",
|
|
225
|
+
description: "owner/name reference to a Genome",
|
|
226
|
+
},
|
|
227
|
+
target_version: {
|
|
228
|
+
type: "string",
|
|
229
|
+
description: "Semver to match Genome.spec.version when done",
|
|
230
|
+
},
|
|
231
|
+
features: { type: "array", items: { type: "string" } },
|
|
232
|
+
closed_at: { type: "string", format: "date-time" },
|
|
233
|
+
cancelled_reason: { type: "string" },
|
|
234
|
+
// v1.5 — board-grade common fields. Epics drop sprint_ref +
|
|
235
|
+
// time_tracking + mockups + release_target.
|
|
236
|
+
priority: { type: "string", enum: [...PRIORITIES] },
|
|
237
|
+
labels: { type: "array", items: { type: "string" } },
|
|
238
|
+
reporter: { type: "string" },
|
|
239
|
+
watchers: { type: "array", items: { type: "string" } },
|
|
240
|
+
journey_phase: { type: "string", enum: [...JOURNEY_PHASES] },
|
|
241
|
+
created_at: { type: "string", format: "date-time" },
|
|
242
|
+
updated_at: { type: "string", format: "date-time" },
|
|
243
|
+
definition_of_done: { type: "array", items: { type: "string" } },
|
|
244
|
+
business_value: { type: "number", minimum: 0, maximum: 1000 },
|
|
245
|
+
produces: producesFieldSchema(),
|
|
246
|
+
timeline: timelineFieldSchema(),
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
summary(doc) {
|
|
251
|
+
const spec = (doc.spec ?? {});
|
|
252
|
+
return {
|
|
253
|
+
status: spec.status ?? "planning",
|
|
254
|
+
target_date: spec.target_date ?? "",
|
|
255
|
+
target_package: spec.target_package ?? "",
|
|
256
|
+
target_version: spec.target_version ?? "",
|
|
257
|
+
features: (spec.features ?? []).length,
|
|
258
|
+
priority: spec.priority ?? "medium",
|
|
259
|
+
labels: spec.labels ?? [],
|
|
260
|
+
business_value: spec.business_value,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// ---------------------------------------------------------------------------
|
|
265
|
+
// Feature
|
|
266
|
+
// ---------------------------------------------------------------------------
|
|
267
|
+
class FeatureKind extends KindBase {
|
|
268
|
+
apiVersion = API_VERSION;
|
|
269
|
+
scope = TenantScope.GLOBAL; // SDLC primitives are project-level
|
|
270
|
+
kind = "Feature";
|
|
271
|
+
alias = "sdlc-feature";
|
|
272
|
+
scopeInheritable = false;
|
|
273
|
+
origin = "github.com/ruinosus/dna/sdlc";
|
|
274
|
+
isPromptTarget = false;
|
|
275
|
+
promptTargetPriority = 0;
|
|
276
|
+
flattenInContext = false;
|
|
277
|
+
plane = "record";
|
|
278
|
+
storage = SD.yaml("features");
|
|
279
|
+
graphStyle = { fill: "#10B981", stroke: "#059669", textColor: "#fff" };
|
|
280
|
+
asciiIcon = "🚀";
|
|
281
|
+
displayLabel = "Features";
|
|
282
|
+
docs = "A Feature is a shippable unit. It implements one or more " +
|
|
283
|
+
"UseCases, decomposes into Stories, and is owned by an Actor. " +
|
|
284
|
+
"Its status reflects the development pipeline: discovery → " +
|
|
285
|
+
"in-development → done.";
|
|
286
|
+
depFilters() {
|
|
287
|
+
return {
|
|
288
|
+
stories: "sdlc-story",
|
|
289
|
+
use_cases: "helix-usecase",
|
|
290
|
+
owner: "helix-actor",
|
|
291
|
+
epic: "sdlc-epic",
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
schema() {
|
|
295
|
+
return {
|
|
296
|
+
type: "object",
|
|
297
|
+
required: ["description", "status"],
|
|
298
|
+
additionalProperties: true,
|
|
299
|
+
properties: {
|
|
300
|
+
title: { type: "string", description: "Human-readable display name." },
|
|
301
|
+
description: { type: "string" },
|
|
302
|
+
// User-story slots (2026-05-11 UX audit) — Py parity.
|
|
303
|
+
as_a: { type: "string", description: "Role: 'As a <role>'." },
|
|
304
|
+
i_want: { type: "string", description: "Goal: 'I want <goal>'." },
|
|
305
|
+
so_that: { type: "string", description: "Benefit: 'so that <benefit>'." },
|
|
306
|
+
acceptance_criteria: { type: "array", items: { type: "string" } },
|
|
307
|
+
definition_of_done: { type: "array", items: { type: "string" } },
|
|
308
|
+
narrative_line: {
|
|
309
|
+
type: "string",
|
|
310
|
+
description: "One-sentence agent-curated prose summary of what this " +
|
|
311
|
+
"Feature has been DOING (past-tense, semantic) — shown next " +
|
|
312
|
+
"to the Feature in Studio's narrative swimlane. Distinct " +
|
|
313
|
+
"from `description` (intent / problem statement).",
|
|
314
|
+
},
|
|
315
|
+
status: { type: "string", enum: [...FEATURE_STATUSES] },
|
|
316
|
+
epic: { type: "string", description: "Parent Epic name" },
|
|
317
|
+
stories: { type: "array", items: { type: "string" } },
|
|
318
|
+
use_cases: { type: "array", items: { type: "string" } },
|
|
319
|
+
owner: { type: "string", description: "Actor name" },
|
|
320
|
+
estimate: {
|
|
321
|
+
type: "string",
|
|
322
|
+
description: "T-shirt size or story points (free-form)",
|
|
323
|
+
},
|
|
324
|
+
closed_at: { type: "string", format: "date-time" },
|
|
325
|
+
blocked_reason: { type: "string" },
|
|
326
|
+
// v1.5 — board-grade fields.
|
|
327
|
+
priority: { type: "string", enum: [...PRIORITIES] },
|
|
328
|
+
labels: { type: "array", items: { type: "string" } },
|
|
329
|
+
reporter: { type: "string" },
|
|
330
|
+
watchers: { type: "array", items: { type: "string" } },
|
|
331
|
+
journey_phase: { type: "string", enum: [...JOURNEY_PHASES] },
|
|
332
|
+
created_at: { type: "string", format: "date-time" },
|
|
333
|
+
updated_at: { type: "string", format: "date-time" },
|
|
334
|
+
sprint_ref: { type: "string" },
|
|
335
|
+
time_tracking: {
|
|
336
|
+
type: "object",
|
|
337
|
+
additionalProperties: false,
|
|
338
|
+
properties: {
|
|
339
|
+
logged_h: { type: "number", minimum: 0 },
|
|
340
|
+
remaining_h: { type: "number", minimum: 0 },
|
|
341
|
+
original_estimate_h: { type: "number", minimum: 0 },
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
// NB: `definition_of_done` already declared above on line 285;
|
|
345
|
+
// dedupe pra TS1117. business_value/mockups/release_target/
|
|
346
|
+
// timeline ficam aqui na board-grade section.
|
|
347
|
+
business_value: { type: "number", minimum: 0, maximum: 1000 },
|
|
348
|
+
mockups: { type: "array", items: { type: "string" } },
|
|
349
|
+
release_target: { type: "string" },
|
|
350
|
+
produces: producesFieldSchema(),
|
|
351
|
+
timeline: timelineFieldSchema(),
|
|
352
|
+
},
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
summary(doc) {
|
|
356
|
+
const spec = (doc.spec ?? {});
|
|
357
|
+
return {
|
|
358
|
+
status: spec.status ?? "discovery",
|
|
359
|
+
epic: spec.epic ?? "",
|
|
360
|
+
owner: spec.owner ?? "",
|
|
361
|
+
stories: (spec.stories ?? []).length,
|
|
362
|
+
use_cases: (spec.use_cases ?? []).length,
|
|
363
|
+
priority: spec.priority ?? "medium",
|
|
364
|
+
labels: spec.labels ?? [],
|
|
365
|
+
sprint_ref: spec.sprint_ref ?? "",
|
|
366
|
+
business_value: spec.business_value,
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
// ---------------------------------------------------------------------------
|
|
371
|
+
// Story
|
|
372
|
+
// ---------------------------------------------------------------------------
|
|
373
|
+
class StoryKind extends KindBase {
|
|
374
|
+
apiVersion = API_VERSION;
|
|
375
|
+
scope = TenantScope.GLOBAL; // SDLC primitives are project-level
|
|
376
|
+
kind = "Story";
|
|
377
|
+
alias = "sdlc-story";
|
|
378
|
+
scopeInheritable = false;
|
|
379
|
+
origin = "github.com/ruinosus/dna/sdlc";
|
|
380
|
+
isPromptTarget = false;
|
|
381
|
+
promptTargetPriority = 0;
|
|
382
|
+
flattenInContext = false;
|
|
383
|
+
plane = "record";
|
|
384
|
+
storage = SD.yaml("stories");
|
|
385
|
+
graphStyle = { fill: "#F59E0B", stroke: "#D97706", textColor: "#fff" };
|
|
386
|
+
asciiIcon = "📖";
|
|
387
|
+
displayLabel = "Stories";
|
|
388
|
+
docs = "A Story is a granular task: one developer, one PR, one estimate. " +
|
|
389
|
+
"Lists acceptance criteria, dependencies (other Stories that must " +
|
|
390
|
+
"land first), and rolls up to a Feature.";
|
|
391
|
+
depFilters() {
|
|
392
|
+
return {
|
|
393
|
+
feature: "sdlc-feature",
|
|
394
|
+
owner: "helix-actor",
|
|
395
|
+
dependencies: "sdlc-story",
|
|
396
|
+
spec_refs: "sdlc-spec",
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
schema() {
|
|
400
|
+
return {
|
|
401
|
+
type: "object",
|
|
402
|
+
required: ["description", "status"],
|
|
403
|
+
additionalProperties: true,
|
|
404
|
+
properties: {
|
|
405
|
+
title: { type: "string", description: "Human-readable display name." },
|
|
406
|
+
description: { type: "string" },
|
|
407
|
+
// User-story slots (2026-05-11 UX audit) — Py parity.
|
|
408
|
+
as_a: { type: "string", description: "Role: 'As a <role>'." },
|
|
409
|
+
i_want: { type: "string", description: "Goal: 'I want <goal>'." },
|
|
410
|
+
so_that: { type: "string", description: "Benefit: 'so that <benefit>'." },
|
|
411
|
+
status: { type: "string", enum: [...STORY_STATUSES] },
|
|
412
|
+
feature: { type: "string", description: "Parent Feature name" },
|
|
413
|
+
owner: { type: "string", description: "Actor name" },
|
|
414
|
+
estimate: {
|
|
415
|
+
type: "number",
|
|
416
|
+
description: "Fibonacci story points (1, 2, 3, 5, 8, 13, 21)",
|
|
417
|
+
},
|
|
418
|
+
acceptance_criteria: {
|
|
419
|
+
type: "array",
|
|
420
|
+
items: {
|
|
421
|
+
oneOf: [
|
|
422
|
+
{ type: "string" },
|
|
423
|
+
{
|
|
424
|
+
type: "object",
|
|
425
|
+
required: ["text"],
|
|
426
|
+
properties: {
|
|
427
|
+
text: { type: "string" },
|
|
428
|
+
done: { type: "boolean" },
|
|
429
|
+
done_at: { type: "string", format: "date-time" },
|
|
430
|
+
done_by: { type: "string" },
|
|
431
|
+
},
|
|
432
|
+
},
|
|
433
|
+
],
|
|
434
|
+
},
|
|
435
|
+
description: "Acceptance criteria. Legacy: string[]. New " +
|
|
436
|
+
"(s-ac-dod-checklist-state): list of {text, done?, done_at?, " +
|
|
437
|
+
"done_by?} for per-item state tracking.",
|
|
438
|
+
},
|
|
439
|
+
dependencies: {
|
|
440
|
+
type: "array",
|
|
441
|
+
items: { type: "string" },
|
|
442
|
+
description: "Other Story names that must land first",
|
|
443
|
+
},
|
|
444
|
+
spec_refs: {
|
|
445
|
+
type: "array",
|
|
446
|
+
items: { type: "string" },
|
|
447
|
+
description: "Spec docs (kind=Spec) this Story implements. M:N linkage " +
|
|
448
|
+
"between the planning axis (Story) and the design axis (Spec).",
|
|
449
|
+
},
|
|
450
|
+
closed_at: { type: "string", format: "date-time" },
|
|
451
|
+
blocked_reason: { type: "string" },
|
|
452
|
+
// v1.5 — board-grade fields (all opt; back-compat preserved).
|
|
453
|
+
priority: { type: "string", enum: [...PRIORITIES] },
|
|
454
|
+
labels: { type: "array", items: { type: "string" } },
|
|
455
|
+
reporter: { type: "string" },
|
|
456
|
+
watchers: { type: "array", items: { type: "string" } },
|
|
457
|
+
journey_phase: { type: "string", enum: [...JOURNEY_PHASES] },
|
|
458
|
+
created_at: { type: "string", format: "date-time" },
|
|
459
|
+
updated_at: { type: "string", format: "date-time" },
|
|
460
|
+
sprint_ref: { type: "string" },
|
|
461
|
+
time_tracking: {
|
|
462
|
+
type: "object",
|
|
463
|
+
additionalProperties: false,
|
|
464
|
+
properties: {
|
|
465
|
+
logged_h: { type: "number", minimum: 0 },
|
|
466
|
+
remaining_h: { type: "number", minimum: 0 },
|
|
467
|
+
original_estimate_h: { type: "number", minimum: 0 },
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
definition_of_done: {
|
|
471
|
+
type: "array",
|
|
472
|
+
items: {
|
|
473
|
+
oneOf: [
|
|
474
|
+
{ type: "string" },
|
|
475
|
+
{
|
|
476
|
+
type: "object",
|
|
477
|
+
required: ["text"],
|
|
478
|
+
properties: {
|
|
479
|
+
text: { type: "string" },
|
|
480
|
+
done: { type: "boolean" },
|
|
481
|
+
done_at: { type: "string", format: "date-time" },
|
|
482
|
+
done_by: { type: "string" },
|
|
483
|
+
},
|
|
484
|
+
},
|
|
485
|
+
],
|
|
486
|
+
},
|
|
487
|
+
description: "Per-Story DoD. Same union shape as acceptance_criteria — " +
|
|
488
|
+
"legacy string[] OR list of {text, done?, done_at?, done_by?}.",
|
|
489
|
+
},
|
|
490
|
+
business_value: { type: "number", minimum: 0, maximum: 1000 },
|
|
491
|
+
mockups: { type: "array", items: { type: "string" } },
|
|
492
|
+
release_target: { type: "string" },
|
|
493
|
+
produces: producesFieldSchema(),
|
|
494
|
+
timeline: timelineFieldSchema(),
|
|
495
|
+
},
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
summary(doc) {
|
|
499
|
+
const spec = (doc.spec ?? {});
|
|
500
|
+
return {
|
|
501
|
+
status: spec.status ?? "todo",
|
|
502
|
+
feature: spec.feature ?? "",
|
|
503
|
+
owner: spec.owner ?? "",
|
|
504
|
+
estimate: spec.estimate,
|
|
505
|
+
spec_refs: (spec.spec_refs ?? []).length,
|
|
506
|
+
priority: spec.priority ?? "medium",
|
|
507
|
+
labels: spec.labels ?? [],
|
|
508
|
+
sprint_ref: spec.sprint_ref ?? "",
|
|
509
|
+
business_value: spec.business_value,
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
// ---------------------------------------------------------------------------
|
|
514
|
+
// Issue
|
|
515
|
+
// ---------------------------------------------------------------------------
|
|
516
|
+
class IssueKind extends KindBase {
|
|
517
|
+
apiVersion = API_VERSION;
|
|
518
|
+
scope = TenantScope.GLOBAL; // SDLC primitives are project-level
|
|
519
|
+
kind = "Issue";
|
|
520
|
+
alias = "sdlc-issue";
|
|
521
|
+
scopeInheritable = false;
|
|
522
|
+
origin = "github.com/ruinosus/dna/sdlc";
|
|
523
|
+
isPromptTarget = false;
|
|
524
|
+
promptTargetPriority = 0;
|
|
525
|
+
flattenInContext = false;
|
|
526
|
+
plane = "record";
|
|
527
|
+
storage = SD.yaml("issues");
|
|
528
|
+
graphStyle = { fill: "#EF4444", stroke: "#DC2626", textColor: "#fff" };
|
|
529
|
+
asciiIcon = "🐞";
|
|
530
|
+
displayLabel = "Issues";
|
|
531
|
+
docs = "An Issue is a human-authored ticket — bug, enhancement, question, " +
|
|
532
|
+
"or task. Tracked across open → triaged → in-progress → resolved. " +
|
|
533
|
+
"Optional links to a parent Feature (work it belongs to) and a " +
|
|
534
|
+
"related Finding (eval-detected origin).";
|
|
535
|
+
depFilters() {
|
|
536
|
+
return {
|
|
537
|
+
related_feature: "sdlc-feature",
|
|
538
|
+
owner: "helix-actor",
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
schema() {
|
|
542
|
+
return {
|
|
543
|
+
type: "object",
|
|
544
|
+
required: ["description", "type", "severity", "status"],
|
|
545
|
+
additionalProperties: true,
|
|
546
|
+
properties: {
|
|
547
|
+
title: { type: "string", description: "Human-readable display name." },
|
|
548
|
+
description: { type: "string" },
|
|
549
|
+
type: { type: "string", enum: [...ISSUE_TYPES] },
|
|
550
|
+
severity: { type: "string", enum: [...ISSUE_SEVERITIES] },
|
|
551
|
+
status: { type: "string", enum: [...ISSUE_STATUSES] },
|
|
552
|
+
owner: { type: "string", description: "Actor name" },
|
|
553
|
+
related_feature: { type: "string", description: "Feature name" },
|
|
554
|
+
related_finding: { type: "string", description: "Finding name" },
|
|
555
|
+
reproduction_steps: { type: "array", items: { type: "string" } },
|
|
556
|
+
expected_behavior: { type: "string" },
|
|
557
|
+
actual_behavior: { type: "string" },
|
|
558
|
+
closed_at: { type: "string", format: "date-time" },
|
|
559
|
+
resolution: { type: "string" },
|
|
560
|
+
// GitHub-bridge provenance (s-github-issues-bridge): an Issue can
|
|
561
|
+
// be PUBLISHED to / IMPORTED from a GitHub issue (`dna sdlc issue
|
|
562
|
+
// publish|import|sync`). These fields are the provenance link —
|
|
563
|
+
// the bridge mirrors WITH provenance, it never replaces the
|
|
564
|
+
// github.com artifact.
|
|
565
|
+
github_number: {
|
|
566
|
+
type: "integer",
|
|
567
|
+
minimum: 1,
|
|
568
|
+
description: "GitHub issue number this doc is bridged to.",
|
|
569
|
+
},
|
|
570
|
+
github_url: {
|
|
571
|
+
type: "string",
|
|
572
|
+
description: "Canonical https URL of the GitHub issue.",
|
|
573
|
+
},
|
|
574
|
+
github_state: {
|
|
575
|
+
type: "string",
|
|
576
|
+
enum: ["open", "closed"],
|
|
577
|
+
description: "Last observed GitHub-side state.",
|
|
578
|
+
},
|
|
579
|
+
github_synced_at: {
|
|
580
|
+
type: "string",
|
|
581
|
+
format: "date-time",
|
|
582
|
+
description: "When the GitHub side was last observed/synced.",
|
|
583
|
+
},
|
|
584
|
+
// v1.5 — board-grade common fields. Issues use `severity`
|
|
585
|
+
// natively; `priority` is orthogonal (severity = how bad,
|
|
586
|
+
// priority = how soon).
|
|
587
|
+
priority: { type: "string", enum: [...PRIORITIES] },
|
|
588
|
+
labels: { type: "array", items: { type: "string" } },
|
|
589
|
+
reporter: { type: "string" },
|
|
590
|
+
watchers: { type: "array", items: { type: "string" } },
|
|
591
|
+
journey_phase: { type: "string", enum: [...JOURNEY_PHASES] },
|
|
592
|
+
created_at: { type: "string", format: "date-time" },
|
|
593
|
+
updated_at: { type: "string", format: "date-time" },
|
|
594
|
+
produces: producesFieldSchema(),
|
|
595
|
+
timeline: timelineFieldSchema(),
|
|
596
|
+
},
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
summary(doc) {
|
|
600
|
+
const spec = (doc.spec ?? {});
|
|
601
|
+
return {
|
|
602
|
+
type: spec.type ?? "bug",
|
|
603
|
+
severity: spec.severity ?? "medium",
|
|
604
|
+
status: spec.status ?? "open",
|
|
605
|
+
owner: spec.owner ?? "",
|
|
606
|
+
related_feature: spec.related_feature ?? "",
|
|
607
|
+
priority: spec.priority ?? "medium",
|
|
608
|
+
labels: spec.labels ?? [],
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
// ---------------------------------------------------------------------------
|
|
613
|
+
// Spec — pattern-agnostic pointer to design doc
|
|
614
|
+
// ---------------------------------------------------------------------------
|
|
615
|
+
// ADR-style status (Nygard). Plan reuses the same enum.
|
|
616
|
+
const ARTIFACT_STATUSES = ["draft", "proposed", "accepted", "deprecated", "superseded"];
|
|
617
|
+
// Spec.phase — Superpowers/Spec-Kit phase progression. Orthogonal to status.
|
|
618
|
+
const SPEC_PHASES = ["brainstorm", "spec", "plan_ready", "implementing", "done"];
|
|
619
|
+
class SpecKind extends KindBase {
|
|
620
|
+
apiVersion = API_VERSION;
|
|
621
|
+
scope = TenantScope.GLOBAL; // SDLC primitives are project-level
|
|
622
|
+
kind = "Spec";
|
|
623
|
+
alias = "sdlc-spec";
|
|
624
|
+
origin = "github.com/ruinosus/dna/sdlc";
|
|
625
|
+
isPromptTarget = false;
|
|
626
|
+
promptTargetPriority = 0;
|
|
627
|
+
flattenInContext = false;
|
|
628
|
+
plane = "record";
|
|
629
|
+
storage = SD.bundle("specs", "SPEC.md", "text", "body");
|
|
630
|
+
// Embeddable (s-spec-embeddable): the markdown body is the design's
|
|
631
|
+
// substance — Plan/Issue/Epic/Doc/Research already embed; Spec was the
|
|
632
|
+
// lone SDLC-artifact gap so `dna cognitive search` missed design docs.
|
|
633
|
+
embedFields = ["title", "summary", "body"];
|
|
634
|
+
graphStyle = { fill: "#6366F1", stroke: "#4F46E5", textColor: "#fff" };
|
|
635
|
+
asciiIcon = "📐";
|
|
636
|
+
displayLabel = "Specs";
|
|
637
|
+
docs = "A Spec is a top-level design artifact. Cross-cutting by default — " +
|
|
638
|
+
"linkage to work items happens via Story.spec_refs[] (M:N). " +
|
|
639
|
+
"Pattern-agnostic: superpowers, BMAD, droid, RFC, ADR, Spec Kit. " +
|
|
640
|
+
"ADR-style status; phase tracks the orthogonal SDLC view.";
|
|
641
|
+
depFilters() {
|
|
642
|
+
return { epic: "sdlc-epic", supersedes: "sdlc-spec" };
|
|
643
|
+
}
|
|
644
|
+
schema() {
|
|
645
|
+
return {
|
|
646
|
+
type: "object",
|
|
647
|
+
required: ["title", "date", "status"],
|
|
648
|
+
additionalProperties: true,
|
|
649
|
+
properties: {
|
|
650
|
+
title: { type: "string" },
|
|
651
|
+
date: { type: "string", format: "date" },
|
|
652
|
+
status: { type: "string", enum: [...ARTIFACT_STATUSES] },
|
|
653
|
+
phase: {
|
|
654
|
+
type: "string",
|
|
655
|
+
enum: [...SPEC_PHASES],
|
|
656
|
+
description: "Where in the SDLC this spec's work sits. Orthogonal to status.",
|
|
657
|
+
},
|
|
658
|
+
pattern: { type: "string" },
|
|
659
|
+
body: { type: "string" }, origin: { type: "string" },
|
|
660
|
+
epic: { type: "string" },
|
|
661
|
+
authors: { type: "array", items: { type: "string" } },
|
|
662
|
+
tags: { type: "array", items: { type: "string" } },
|
|
663
|
+
supersedes: { type: "string" },
|
|
664
|
+
summary: { type: "string" },
|
|
665
|
+
},
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
summary(doc) {
|
|
669
|
+
const spec = (doc.spec ?? {});
|
|
670
|
+
return {
|
|
671
|
+
title: (spec.title ?? "").slice(0, 80),
|
|
672
|
+
date: spec.date ?? "",
|
|
673
|
+
status: spec.status ?? "draft",
|
|
674
|
+
phase: spec.phase ?? "",
|
|
675
|
+
pattern: spec.pattern ?? "",
|
|
676
|
+
epic: spec.epic ?? "",
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
class PlanKind extends KindBase {
|
|
681
|
+
apiVersion = API_VERSION;
|
|
682
|
+
scope = TenantScope.GLOBAL; // SDLC primitives are project-level
|
|
683
|
+
kind = "Plan";
|
|
684
|
+
alias = "sdlc-plan";
|
|
685
|
+
scopeInheritable = false;
|
|
686
|
+
origin = "github.com/ruinosus/dna/sdlc";
|
|
687
|
+
isPromptTarget = false;
|
|
688
|
+
promptTargetPriority = 0;
|
|
689
|
+
flattenInContext = false;
|
|
690
|
+
plane = "record";
|
|
691
|
+
storage = SD.bundle("plans", "PLAN.md", "text", "body");
|
|
692
|
+
graphStyle = { fill: "#06B6D4", stroke: "#0891B2", textColor: "#fff" };
|
|
693
|
+
asciiIcon = "📋";
|
|
694
|
+
displayLabel = "Plans";
|
|
695
|
+
docs = "A Plan is a pointer to an implementation plan. Usually descends " +
|
|
696
|
+
"from a Spec via spec_ref. Pattern-agnostic.";
|
|
697
|
+
depFilters() {
|
|
698
|
+
return {
|
|
699
|
+
spec_ref: "sdlc-spec",
|
|
700
|
+
epic: "sdlc-epic",
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
schema() {
|
|
704
|
+
return {
|
|
705
|
+
type: "object",
|
|
706
|
+
required: ["title", "date", "status"],
|
|
707
|
+
additionalProperties: true,
|
|
708
|
+
properties: {
|
|
709
|
+
title: { type: "string" },
|
|
710
|
+
date: { type: "string", format: "date" },
|
|
711
|
+
status: { type: "string", enum: [...ARTIFACT_STATUSES] },
|
|
712
|
+
pattern: { type: "string" },
|
|
713
|
+
body: { type: "string" }, origin: { type: "string" },
|
|
714
|
+
spec_ref: { type: "string" },
|
|
715
|
+
epic: { type: "string" },
|
|
716
|
+
authors: { type: "array", items: { type: "string" } },
|
|
717
|
+
tags: { type: "array", items: { type: "string" } },
|
|
718
|
+
summary: { type: "string" },
|
|
719
|
+
// Parity with the Py twin (PlanKind.schema): journey_phase lights the
|
|
720
|
+
// derived `plan` phase; methodology records which planning method
|
|
721
|
+
// produced the plan (superpowers/bmad/...) — opt-in, agnostic.
|
|
722
|
+
journey_phase: { type: "string", enum: [...JOURNEY_PHASES] },
|
|
723
|
+
methodology: { type: "string", enum: [...JOURNEY_METHODOLOGIES] },
|
|
724
|
+
},
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
summary(doc) {
|
|
728
|
+
const spec = (doc.spec ?? {});
|
|
729
|
+
return {
|
|
730
|
+
title: (spec.title ?? "").slice(0, 80),
|
|
731
|
+
date: spec.date ?? "",
|
|
732
|
+
status: spec.status ?? "draft",
|
|
733
|
+
pattern: spec.pattern ?? "",
|
|
734
|
+
spec_ref: spec.spec_ref ?? "",
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
// ---------------------------------------------------------------------------
|
|
739
|
+
// AgentSession — chat dev↔AI as versioned project artifact (Karpathy 2025)
|
|
740
|
+
// ---------------------------------------------------------------------------
|
|
741
|
+
class AgentSessionKind extends KindBase {
|
|
742
|
+
apiVersion = API_VERSION;
|
|
743
|
+
scope = TenantScope.GLOBAL; // SDLC primitives are project-level
|
|
744
|
+
kind = "AgentSession";
|
|
745
|
+
alias = "sdlc-agent-session";
|
|
746
|
+
origin = "github.com/ruinosus/dna/sdlc";
|
|
747
|
+
isPromptTarget = false;
|
|
748
|
+
promptTargetPriority = 0;
|
|
749
|
+
flattenInContext = false;
|
|
750
|
+
plane = "record";
|
|
751
|
+
storage = SD.bundle("agent-sessions", "SESSION.md", "text", "body");
|
|
752
|
+
graphStyle = { fill: "#EC4899", stroke: "#DB2777", textColor: "#fff" };
|
|
753
|
+
asciiIcon = "📜";
|
|
754
|
+
displayLabel = "Vibe Sessions";
|
|
755
|
+
docs = "A AgentSession captures a developer↔AI coding conversation as a " +
|
|
756
|
+
"versioned project artifact. Tool-agnostic (Claude Code, Cursor, " +
|
|
757
|
+
"Cline, Codex, Aider) via per-tool adapters.";
|
|
758
|
+
depFilters() {
|
|
759
|
+
return { participants: "helix-actor" };
|
|
760
|
+
}
|
|
761
|
+
schema() {
|
|
762
|
+
return {
|
|
763
|
+
type: "object",
|
|
764
|
+
required: ["title", "tool", "session_id", "started_at"],
|
|
765
|
+
additionalProperties: true,
|
|
766
|
+
properties: {
|
|
767
|
+
title: { type: "string" },
|
|
768
|
+
tool: {
|
|
769
|
+
type: "string",
|
|
770
|
+
description: "claude-code | cursor | cline | codex | aider | specstory | other",
|
|
771
|
+
},
|
|
772
|
+
tool_version: { type: "string" },
|
|
773
|
+
session_id: { type: "string" },
|
|
774
|
+
model: { type: "string" },
|
|
775
|
+
workspace_path: { type: "string" },
|
|
776
|
+
started_at: { type: "string", format: "date-time" },
|
|
777
|
+
ended_at: { type: "string", format: "date-time" },
|
|
778
|
+
participants: { type: "array", items: { type: "string" } },
|
|
779
|
+
produced_artifacts: {
|
|
780
|
+
type: "array",
|
|
781
|
+
items: {
|
|
782
|
+
type: "object",
|
|
783
|
+
required: ["kind", "name"],
|
|
784
|
+
properties: {
|
|
785
|
+
kind: { type: "string" },
|
|
786
|
+
name: { type: "string" },
|
|
787
|
+
},
|
|
788
|
+
},
|
|
789
|
+
},
|
|
790
|
+
applied_commits: { type: "array", items: { type: "string" } },
|
|
791
|
+
file_changes: { type: "array", items: { type: "string" } },
|
|
792
|
+
token_usage: { type: "object" },
|
|
793
|
+
cost_usd: { type: "number" },
|
|
794
|
+
summary: { type: "string" },
|
|
795
|
+
body: { type: "string" },
|
|
796
|
+
raw_source: { type: "string" },
|
|
797
|
+
tool_specific: { type: "object" },
|
|
798
|
+
},
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
summary(doc) {
|
|
802
|
+
const spec = (doc.spec ?? {});
|
|
803
|
+
return {
|
|
804
|
+
title: (spec.title ?? "").slice(0, 80),
|
|
805
|
+
tool: spec.tool ?? "",
|
|
806
|
+
model: spec.model ?? "",
|
|
807
|
+
started_at: spec.started_at ?? "",
|
|
808
|
+
produced_artifacts: (spec.produced_artifacts ?? []).length,
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
// ---------------------------------------------------------------------------
|
|
813
|
+
// Narrative — agent-curated project storytelling (1:1 twin of Py)
|
|
814
|
+
// ---------------------------------------------------------------------------
|
|
815
|
+
// Narrative — F3 lote-2 (spec 2026-06-10-kinds-descriptor-f3): the twin NarrativeKind classes (Py+TS) were
|
|
816
|
+
// DELETED — synthesized from kinds/narrative.kind.yaml (parity-critical
|
|
817
|
+
// package data, byte-identical Py↔TS) via the loadDescriptors loop in
|
|
818
|
+
// register(). Equivalence with the extinct class frozen in
|
|
819
|
+
// tests/test_lote2_descriptor_equivalence.py (golden:
|
|
820
|
+
// tests/goldens/lote2/Narrative.golden.json).
|
|
821
|
+
// ---------------------------------------------------------------------------
|
|
822
|
+
// Bug / Task / Spike — granular work items (split from Issue umbrella)
|
|
823
|
+
// ---------------------------------------------------------------------------
|
|
824
|
+
const BUG_SEVERITY = ["low", "medium", "high", "critical"];
|
|
825
|
+
const BUG_STATUSES = ["open", "triaged", "in-progress", "resolved", "wont-fix", "duplicate", "regression"];
|
|
826
|
+
const TASK_STATUSES = ["todo", "in-progress", "done", "blocked", "cancelled"];
|
|
827
|
+
const SPIKE_STATUSES = ["proposed", "in-progress", "answered", "abandoned"];
|
|
828
|
+
class BugKind extends KindBase {
|
|
829
|
+
apiVersion = API_VERSION;
|
|
830
|
+
scope = TenantScope.GLOBAL;
|
|
831
|
+
kind = "Bug";
|
|
832
|
+
alias = "sdlc-bug";
|
|
833
|
+
origin = "github.com/ruinosus/dna/sdlc";
|
|
834
|
+
isPromptTarget = false;
|
|
835
|
+
promptTargetPriority = 0;
|
|
836
|
+
flattenInContext = false;
|
|
837
|
+
plane = "record";
|
|
838
|
+
storage = SD.bundle("bugs", "BUG.md", "text", "body");
|
|
839
|
+
graphStyle = { fill: "#DC2626", stroke: "#991B1B", textColor: "#fff" };
|
|
840
|
+
asciiIcon = "🐛";
|
|
841
|
+
displayLabel = "Bugs";
|
|
842
|
+
docs = "Defeito factual com repro + severity. Schema dedicado " +
|
|
843
|
+
"(repro_steps, environment, root_cause, fix_summary).";
|
|
844
|
+
depFilters() {
|
|
845
|
+
return {
|
|
846
|
+
related_story: "sdlc-story",
|
|
847
|
+
related_feature: "sdlc-feature",
|
|
848
|
+
fix_adr: "sdlc-adr",
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
schema() {
|
|
852
|
+
return {
|
|
853
|
+
type: "object",
|
|
854
|
+
required: ["title", "severity", "status"],
|
|
855
|
+
additionalProperties: true,
|
|
856
|
+
properties: {
|
|
857
|
+
title: { type: "string" },
|
|
858
|
+
description: { type: "string" },
|
|
859
|
+
severity: { type: "string", enum: [...BUG_SEVERITY] },
|
|
860
|
+
status: { type: "string", enum: [...BUG_STATUSES] },
|
|
861
|
+
repro_steps: { type: "array", items: { type: "string" } },
|
|
862
|
+
expected: { type: "string" },
|
|
863
|
+
actual: { type: "string" },
|
|
864
|
+
environment: { type: "string" },
|
|
865
|
+
root_cause: { type: "string" },
|
|
866
|
+
fix_summary: { type: "string" },
|
|
867
|
+
fix_adr: { type: "string" },
|
|
868
|
+
related_story: { type: "string" },
|
|
869
|
+
related_feature: { type: "string" },
|
|
870
|
+
related_finding: { type: "string" },
|
|
871
|
+
reporter: { type: "string" },
|
|
872
|
+
owner: { type: "string" },
|
|
873
|
+
found_at: { type: "string", format: "date-time" },
|
|
874
|
+
resolved_at: { type: "string", format: "date-time" },
|
|
875
|
+
labels: { type: "array", items: { type: "string" } },
|
|
876
|
+
priority: { type: "string", enum: [...PRIORITIES] },
|
|
877
|
+
body: { type: "string" },
|
|
878
|
+
produces: producesFieldSchema(),
|
|
879
|
+
timeline: timelineFieldSchema(),
|
|
880
|
+
created_at: { type: "string", format: "date-time" },
|
|
881
|
+
updated_at: { type: "string", format: "date-time" },
|
|
882
|
+
},
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
summary(doc) {
|
|
886
|
+
const spec = (doc.spec ?? {});
|
|
887
|
+
return {
|
|
888
|
+
title: spec.title ?? "",
|
|
889
|
+
severity: spec.severity ?? "",
|
|
890
|
+
status: spec.status ?? "",
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
class TaskKind extends KindBase {
|
|
895
|
+
apiVersion = API_VERSION;
|
|
896
|
+
scope = TenantScope.GLOBAL;
|
|
897
|
+
kind = "Task";
|
|
898
|
+
alias = "sdlc-task";
|
|
899
|
+
origin = "github.com/ruinosus/dna/sdlc";
|
|
900
|
+
isPromptTarget = false;
|
|
901
|
+
promptTargetPriority = 0;
|
|
902
|
+
flattenInContext = false;
|
|
903
|
+
plane = "record";
|
|
904
|
+
storage = SD.bundle("tasks", "TASK.md", "text", "body");
|
|
905
|
+
graphStyle = { fill: "#3B82F6", stroke: "#1D4ED8", textColor: "#fff" };
|
|
906
|
+
asciiIcon = "✅";
|
|
907
|
+
displayLabel = "Tasks";
|
|
908
|
+
docs = "Work item granular (horas-dias). Sub-item de Story (Atlassian " +
|
|
909
|
+
"Jira Align hierarchy: Story → Task → Sub-task).";
|
|
910
|
+
depFilters() { return { story_ref: "sdlc-story", owner: "helix-actor" }; }
|
|
911
|
+
schema() {
|
|
912
|
+
return {
|
|
913
|
+
type: "object",
|
|
914
|
+
required: ["title", "status"],
|
|
915
|
+
additionalProperties: true,
|
|
916
|
+
properties: {
|
|
917
|
+
title: { type: "string" },
|
|
918
|
+
description: { type: "string" },
|
|
919
|
+
status: { type: "string", enum: [...TASK_STATUSES] },
|
|
920
|
+
story_ref: { type: "string" },
|
|
921
|
+
owner: { type: "string" },
|
|
922
|
+
estimate_hours: { type: "number", minimum: 0 },
|
|
923
|
+
logged_hours: { type: "number", minimum: 0 },
|
|
924
|
+
due: { type: "string", format: "date" },
|
|
925
|
+
priority: { type: "string", enum: [...PRIORITIES] },
|
|
926
|
+
labels: { type: "array", items: { type: "string" } },
|
|
927
|
+
blocked_reason: { type: "string" },
|
|
928
|
+
closed_at: { type: "string", format: "date-time" },
|
|
929
|
+
body: { type: "string" },
|
|
930
|
+
produces: producesFieldSchema(),
|
|
931
|
+
timeline: timelineFieldSchema(),
|
|
932
|
+
created_at: { type: "string", format: "date-time" },
|
|
933
|
+
updated_at: { type: "string", format: "date-time" },
|
|
934
|
+
},
|
|
935
|
+
};
|
|
936
|
+
}
|
|
937
|
+
summary(doc) {
|
|
938
|
+
const spec = (doc.spec ?? {});
|
|
939
|
+
return {
|
|
940
|
+
title: spec.title ?? "",
|
|
941
|
+
status: spec.status ?? "",
|
|
942
|
+
owner: spec.owner ?? "",
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
class SpikeKind extends KindBase {
|
|
947
|
+
apiVersion = API_VERSION;
|
|
948
|
+
scope = TenantScope.GLOBAL;
|
|
949
|
+
kind = "Spike";
|
|
950
|
+
alias = "sdlc-spike";
|
|
951
|
+
origin = "github.com/ruinosus/dna/sdlc";
|
|
952
|
+
isPromptTarget = false;
|
|
953
|
+
promptTargetPriority = 0;
|
|
954
|
+
flattenInContext = false;
|
|
955
|
+
plane = "record";
|
|
956
|
+
storage = SD.bundle("spikes", "SPIKE.md", "text", "body");
|
|
957
|
+
graphStyle = { fill: "#A855F7", stroke: "#7E22CE", textColor: "#fff" };
|
|
958
|
+
asciiIcon = "🔬";
|
|
959
|
+
displayLabel = "Spikes";
|
|
960
|
+
docs = "Time-boxed technical investigation. ONE question + finite " +
|
|
961
|
+
"time + outcome handoff (findings → Story or ADR).";
|
|
962
|
+
depFilters() {
|
|
963
|
+
return {
|
|
964
|
+
follow_up_story: "sdlc-story",
|
|
965
|
+
follow_up_adr: "sdlc-adr",
|
|
966
|
+
follow_up_spec: "sdlc-spec",
|
|
967
|
+
feature: "sdlc-feature",
|
|
968
|
+
// Multi-ref attachments (2026-05-26 — design-spike workflow).
|
|
969
|
+
references: "sdlc-reference",
|
|
970
|
+
related_spikes: "sdlc-spike",
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
schema() {
|
|
974
|
+
return {
|
|
975
|
+
type: "object",
|
|
976
|
+
required: ["title", "question_to_answer", "status"],
|
|
977
|
+
additionalProperties: true,
|
|
978
|
+
properties: {
|
|
979
|
+
title: { type: "string" },
|
|
980
|
+
question_to_answer: { type: "string" },
|
|
981
|
+
status: { type: "string", enum: [...SPIKE_STATUSES] },
|
|
982
|
+
time_box_hours: { type: "number", minimum: 0, default: 8 },
|
|
983
|
+
logged_hours: { type: "number", minimum: 0 },
|
|
984
|
+
findings: { type: "string" },
|
|
985
|
+
recommendation: { type: "string" },
|
|
986
|
+
follow_up_story: { type: "string" },
|
|
987
|
+
follow_up_adr: { type: "string" },
|
|
988
|
+
follow_up_spec: { type: "string" },
|
|
989
|
+
feature: { type: "string" },
|
|
990
|
+
owner: { type: "string" },
|
|
991
|
+
html_artifacts: { type: "array", items: { type: "string" } },
|
|
992
|
+
research_refs: { type: "array", items: { type: "string" } },
|
|
993
|
+
references: { type: "array", items: { type: "string" } },
|
|
994
|
+
related_spikes: { type: "array", items: { type: "string" } },
|
|
995
|
+
started_at: { type: "string", format: "date-time" },
|
|
996
|
+
completed_at: { type: "string", format: "date-time" },
|
|
997
|
+
labels: { type: "array", items: { type: "string" } },
|
|
998
|
+
body: { type: "string" },
|
|
999
|
+
produces: producesFieldSchema(),
|
|
1000
|
+
timeline: timelineFieldSchema(),
|
|
1001
|
+
created_at: { type: "string", format: "date-time" },
|
|
1002
|
+
updated_at: { type: "string", format: "date-time" },
|
|
1003
|
+
},
|
|
1004
|
+
};
|
|
1005
|
+
}
|
|
1006
|
+
summary(doc) {
|
|
1007
|
+
const spec = (doc.spec ?? {});
|
|
1008
|
+
return {
|
|
1009
|
+
title: spec.title ?? "",
|
|
1010
|
+
status: spec.status ?? "",
|
|
1011
|
+
time_box_hours: spec.time_box_hours ?? null,
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
// ---------------------------------------------------------------------------
|
|
1016
|
+
// Initiative — investment unit (Atlassian Jira Align hierarchy)
|
|
1017
|
+
// ---------------------------------------------------------------------------
|
|
1018
|
+
const INITIATIVE_STATUSES = ["proposed", "in-flight", "done", "cancelled", "deferred"];
|
|
1019
|
+
class InitiativeKind extends KindBase {
|
|
1020
|
+
apiVersion = API_VERSION;
|
|
1021
|
+
scope = TenantScope.GLOBAL;
|
|
1022
|
+
kind = "Initiative";
|
|
1023
|
+
alias = "sdlc-initiative";
|
|
1024
|
+
origin = "github.com/ruinosus/dna/sdlc";
|
|
1025
|
+
isPromptTarget = false;
|
|
1026
|
+
promptTargetPriority = 0;
|
|
1027
|
+
flattenInContext = false;
|
|
1028
|
+
plane = "record";
|
|
1029
|
+
storage = SD.bundle("initiatives", "INITIATIVE.md", "text", "body");
|
|
1030
|
+
graphStyle = { fill: "#0EA5E9", stroke: "#0284C7", textColor: "#fff" };
|
|
1031
|
+
asciiIcon = "🎲";
|
|
1032
|
+
displayLabel = "Initiatives";
|
|
1033
|
+
docs = "Investment-level umbrella (1-2 quarters) between Theme/OKR and " +
|
|
1034
|
+
"Epic. Atlassian Jira Align hierarchy.";
|
|
1035
|
+
depFilters() {
|
|
1036
|
+
return { epics: "sdlc-epic", owner: "helix-actor" };
|
|
1037
|
+
}
|
|
1038
|
+
schema() {
|
|
1039
|
+
return {
|
|
1040
|
+
type: "object",
|
|
1041
|
+
required: ["title", "status"],
|
|
1042
|
+
additionalProperties: true,
|
|
1043
|
+
properties: {
|
|
1044
|
+
title: { type: "string" },
|
|
1045
|
+
description: { type: "string" },
|
|
1046
|
+
status: { type: "string", enum: [...INITIATIVE_STATUSES] },
|
|
1047
|
+
owner: { type: "string" },
|
|
1048
|
+
horizon_start: { type: "string", format: "date" },
|
|
1049
|
+
horizon_end: { type: "string", format: "date" },
|
|
1050
|
+
outcome_metric: { type: "string" },
|
|
1051
|
+
target_value: { type: "string" },
|
|
1052
|
+
epics: { type: "array", items: { type: "string" } },
|
|
1053
|
+
theme_ref: { type: "string" },
|
|
1054
|
+
business_value: { type: "number" },
|
|
1055
|
+
priority: { type: "string", enum: [...PRIORITIES] },
|
|
1056
|
+
labels: { type: "array", items: { type: "string" } },
|
|
1057
|
+
body: { type: "string" },
|
|
1058
|
+
created_at: { type: "string", format: "date-time" },
|
|
1059
|
+
updated_at: { type: "string", format: "date-time" },
|
|
1060
|
+
},
|
|
1061
|
+
};
|
|
1062
|
+
}
|
|
1063
|
+
summary(doc) {
|
|
1064
|
+
const spec = (doc.spec ?? {});
|
|
1065
|
+
return {
|
|
1066
|
+
title: spec.title ?? "",
|
|
1067
|
+
status: spec.status ?? "",
|
|
1068
|
+
epics_count: (spec.epics ?? []).length,
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
// ---------------------------------------------------------------------------
|
|
1073
|
+
// Reference — external citation artifact
|
|
1074
|
+
// ---------------------------------------------------------------------------
|
|
1075
|
+
const REFERENCE_KIND_OFS = ["web", "paper", "book", "file", "internal-doc", "other"];
|
|
1076
|
+
/**
|
|
1077
|
+
* Reference — external citation artifact (web/paper/book/file/internal-doc).
|
|
1078
|
+
*
|
|
1079
|
+
* Wraps external sources with metadata so SDLC docs can cite evidence
|
|
1080
|
+
* durably. Any other Kind (Story, Feature, Spec, Plan, Engram, etc.)
|
|
1081
|
+
* gains an optional `spec.references: list[str]` field naming Reference
|
|
1082
|
+
* doc slugs. CLI `dna sdlc cite` maintains the bidirectional graph
|
|
1083
|
+
* (Reference.spec.cited_by += caller_ref).
|
|
1084
|
+
*
|
|
1085
|
+
* Ported from Python for s-alias-generated-not-typed: Spike.depFilters
|
|
1086
|
+
* points at `sdlc-reference`, and validateDepFilters requires every
|
|
1087
|
+
* builtin dep_filter alias to resolve — the Kind can no longer be
|
|
1088
|
+
* py-only. 1:1 twin of dna.extensions.sdlc.ReferenceKind.
|
|
1089
|
+
*
|
|
1090
|
+
* Spec: docs/superpowers/specs/2026-05-12-f-reference-citation-kind.md
|
|
1091
|
+
*/
|
|
1092
|
+
class ReferenceKind extends KindBase {
|
|
1093
|
+
apiVersion = API_VERSION;
|
|
1094
|
+
scope = TenantScope.GLOBAL;
|
|
1095
|
+
kind = "Reference";
|
|
1096
|
+
alias = "sdlc-reference";
|
|
1097
|
+
origin = "github.com/ruinosus/dna/sdlc";
|
|
1098
|
+
isPromptTarget = false;
|
|
1099
|
+
promptTargetPriority = 0;
|
|
1100
|
+
flattenInContext = false;
|
|
1101
|
+
plane = "record";
|
|
1102
|
+
storage = SD.yaml("references");
|
|
1103
|
+
graphStyle = { fill: "#6366F1", stroke: "#4F46E5", textColor: "#fff" };
|
|
1104
|
+
asciiIcon = "📚";
|
|
1105
|
+
displayLabel = "References";
|
|
1106
|
+
depFilters() {
|
|
1107
|
+
return {};
|
|
1108
|
+
}
|
|
1109
|
+
schema() {
|
|
1110
|
+
return {
|
|
1111
|
+
type: "object",
|
|
1112
|
+
required: ["title", "kind_of", "summary"],
|
|
1113
|
+
additionalProperties: true,
|
|
1114
|
+
properties: {
|
|
1115
|
+
title: { type: "string" },
|
|
1116
|
+
kind_of: { type: "string", enum: [...REFERENCE_KIND_OFS] },
|
|
1117
|
+
url: { type: "string" },
|
|
1118
|
+
fetched_at: { type: "string", format: "date-time" },
|
|
1119
|
+
summary: { type: "string", description: "1-2 sentence what this source says." },
|
|
1120
|
+
key_quotes: { type: "array", items: { type: "string" }, default: [] },
|
|
1121
|
+
relevance: { type: "string", description: "Why this matters for THIS project." },
|
|
1122
|
+
tags: { type: "array", items: { type: "string" }, default: [] },
|
|
1123
|
+
cited_by: {
|
|
1124
|
+
type: "array",
|
|
1125
|
+
items: { type: "string" },
|
|
1126
|
+
default: [],
|
|
1127
|
+
description: "Auto-maintained by `dna sdlc cite`. Don't author by hand.",
|
|
1128
|
+
},
|
|
1129
|
+
content_path: {
|
|
1130
|
+
type: "string",
|
|
1131
|
+
description: "Optional path to rich-content sidecar (e.g. docs/superpowers/research/<slug>.md)",
|
|
1132
|
+
},
|
|
1133
|
+
owner: { type: "string", default: "claude-code" },
|
|
1134
|
+
created_at: { type: "string", format: "date-time" },
|
|
1135
|
+
updated_at: { type: "string", format: "date-time" },
|
|
1136
|
+
},
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1139
|
+
summary(doc) {
|
|
1140
|
+
const spec = (doc.spec ?? {});
|
|
1141
|
+
return {
|
|
1142
|
+
title: spec.title ?? "",
|
|
1143
|
+
kind_of: spec.kind_of ?? "other",
|
|
1144
|
+
url: spec.url ?? "",
|
|
1145
|
+
cited_by_count: (spec.cited_by ?? []).length,
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
// ---------------------------------------------------------------------------
|
|
1150
|
+
// Changelog — Keep a Changelog 1.1.0 + SemVer 2.0
|
|
1151
|
+
// ---------------------------------------------------------------------------
|
|
1152
|
+
// Changelog — F3 lote-2 (spec 2026-06-10-kinds-descriptor-f3): the twin ChangelogKind classes (Py+TS) were
|
|
1153
|
+
// DELETED — synthesized from kinds/changelog.kind.yaml (parity-critical
|
|
1154
|
+
// package data, byte-identical Py↔TS) via the loadDescriptors loop in
|
|
1155
|
+
// register(). Equivalence with the extinct class frozen in
|
|
1156
|
+
// tests/test_lote2_descriptor_equivalence.py (golden:
|
|
1157
|
+
// tests/goldens/lote2/Changelog.golden.json).
|
|
1158
|
+
// ---------------------------------------------------------------------------
|
|
1159
|
+
// Postmortem — Google SRE blameless incident analysis
|
|
1160
|
+
// ---------------------------------------------------------------------------
|
|
1161
|
+
// Postmortem — F3 lote-2 (spec 2026-06-10-kinds-descriptor-f3): the twin PostmortemKind classes (Py+TS) were
|
|
1162
|
+
// DELETED — synthesized from kinds/postmortem.kind.yaml (parity-critical
|
|
1163
|
+
// package data, byte-identical Py↔TS) via the loadDescriptors loop in
|
|
1164
|
+
// register(). Equivalence with the extinct class frozen in
|
|
1165
|
+
// tests/test_lote2_descriptor_equivalence.py (golden:
|
|
1166
|
+
// tests/goldens/lote2/Postmortem.golden.json).
|
|
1167
|
+
// ---------------------------------------------------------------------------
|
|
1168
|
+
// RiskRegister — PMBOK 7 + ISO 31000:2018
|
|
1169
|
+
// ---------------------------------------------------------------------------
|
|
1170
|
+
// RiskRegister — F3 lote-2 (spec 2026-06-10-kinds-descriptor-f3): the twin RiskRegisterKind classes (Py+TS) were
|
|
1171
|
+
// DELETED — synthesized from kinds/risk-register.kind.yaml (parity-critical
|
|
1172
|
+
// package data, byte-identical Py↔TS) via the loadDescriptors loop in
|
|
1173
|
+
// register(). Equivalence with the extinct class frozen in
|
|
1174
|
+
// tests/test_lote2_descriptor_equivalence.py (golden:
|
|
1175
|
+
// tests/goldens/lote2/RiskRegister.golden.json).
|
|
1176
|
+
// ---------------------------------------------------------------------------
|
|
1177
|
+
// ADR — Architecture Decision Record (Nygard 2011 / MADR)
|
|
1178
|
+
// ---------------------------------------------------------------------------
|
|
1179
|
+
// ADR — F3 lote-2 (spec 2026-06-10-kinds-descriptor-f3): the twin ADRKind classes (Py+TS) were
|
|
1180
|
+
// DELETED — synthesized from kinds/adr.kind.yaml (parity-critical
|
|
1181
|
+
// package data, byte-identical Py↔TS) via the loadDescriptors loop in
|
|
1182
|
+
// register(). Equivalence with the extinct class frozen in
|
|
1183
|
+
// tests/test_lote2_descriptor_equivalence.py (golden:
|
|
1184
|
+
// tests/goldens/lote2/ADR.golden.json).
|
|
1185
|
+
// ---------------------------------------------------------------------------
|
|
1186
|
+
// Retrospective — sprint/release/incident retro (Atlassian 4 Ls)
|
|
1187
|
+
// ---------------------------------------------------------------------------
|
|
1188
|
+
// Retrospective — F3 lote-1 (spec 2026-06-10-kinds-descriptor-f3): the twin
|
|
1189
|
+
// RetrospectiveKind classes (Py+TS) were DELETED — synthesized from
|
|
1190
|
+
// kinds/retrospective.kind.yaml (parity-critical package data) via the
|
|
1191
|
+
// loadDescriptors loop in register(). The old TS-only summary()/slim schema
|
|
1192
|
+
// drifted from Py; the descriptor unifies on the canonical (Py) surface.
|
|
1193
|
+
// ---------------------------------------------------------------------------
|
|
1194
|
+
// Extension
|
|
1195
|
+
// ---------------------------------------------------------------------------
|
|
1196
|
+
// ---------------------------------------------------------------------------
|
|
1197
|
+
// WorkflowEvent — append-only ledger of phase transitions (1:1 twin of Py)
|
|
1198
|
+
// ---------------------------------------------------------------------------
|
|
1199
|
+
const JOURNEY_METHODOLOGIES = [
|
|
1200
|
+
"superpowers", "bmad", "spec-kit", "kiro",
|
|
1201
|
+
"rfc", "adr", "ad-hoc", "custom",
|
|
1202
|
+
];
|
|
1203
|
+
// ---------------------------------------------------------------------------
|
|
1204
|
+
// SavedView — named filter+groupBy+sort+layout entity (Linear/Notion pattern)
|
|
1205
|
+
// ---------------------------------------------------------------------------
|
|
1206
|
+
// SavedView — F3 lote-2 (spec 2026-06-10-kinds-descriptor-f3): the twin SavedViewKind classes (Py+TS) were
|
|
1207
|
+
// DELETED — synthesized from kinds/saved-view.kind.yaml (parity-critical
|
|
1208
|
+
// package data, byte-identical Py↔TS) via the loadDescriptors loop in
|
|
1209
|
+
// register(). Equivalence with the extinct class frozen in
|
|
1210
|
+
// tests/test_lote2_descriptor_equivalence.py (golden:
|
|
1211
|
+
// tests/goldens/lote2/SavedView.golden.json).
|
|
1212
|
+
// WorkflowEvent — F3 lote-1: twin classes deleted — synthesized from
|
|
1213
|
+
// kinds/workflow-event.kind.yaml. Old TS summary defaults ("") drifted from
|
|
1214
|
+
// Py (null); the descriptor unifies on the canonical (Py) surface.
|
|
1215
|
+
// Insight — F3 lote-2 (spec 2026-06-10-kinds-descriptor-f3): the twin InsightKind classes (Py+TS) were
|
|
1216
|
+
// DELETED — synthesized from kinds/insight.kind.yaml (parity-critical
|
|
1217
|
+
// package data, byte-identical Py↔TS) via the loadDescriptors loop in
|
|
1218
|
+
// register(). Equivalence with the extinct class frozen in
|
|
1219
|
+
// tests/test_lote2_descriptor_equivalence.py (golden:
|
|
1220
|
+
// tests/goldens/lote2/Insight.golden.json).
|
|
1221
|
+
// StatusReport — F3 lote-2 (spec 2026-06-10-kinds-descriptor-f3): the twin StatusReportKind classes (Py+TS) were
|
|
1222
|
+
// DELETED — synthesized from kinds/status-report.kind.yaml (parity-critical
|
|
1223
|
+
// package data, byte-identical Py↔TS) via the loadDescriptors loop in
|
|
1224
|
+
// register(). Equivalence with the extinct class frozen in
|
|
1225
|
+
// tests/test_lote2_descriptor_equivalence.py (golden:
|
|
1226
|
+
// tests/goldens/lote2/StatusReport.golden.json).
|
|
1227
|
+
// ---------------------------------------------------------------------------
|
|
1228
|
+
// Cognitive Memory Triad (v1.9.0) — LessonLearned + SynthesisRun + ArchiveProposal
|
|
1229
|
+
//
|
|
1230
|
+
// Spec: docs/superpowers/specs/2026-05-11-cognitive-memory-triad.md
|
|
1231
|
+
// Surface labels (pt-BR) in Studio: "Lições Aprendidas" / "Sínteses" / "Arquivamento".
|
|
1232
|
+
// Kind names stay English per repo convention (same pattern as Insight).
|
|
1233
|
+
// ---------------------------------------------------------------------------
|
|
1234
|
+
// REMEMBRANCE_AFFECTS / REMEMBRANCE_SURFACE_TRIGGERS now live ONLY in
|
|
1235
|
+
// kinds/lesson-learned.kind.yaml (F3 lote-1) — the descriptor is the
|
|
1236
|
+
// single source for the LessonLearned enums.
|
|
1237
|
+
// F3 lote-2: the per-Kind enum consts that used to live here
|
|
1238
|
+
// (DREAM_*/FORGETTING_*/ADR_STATUSES/RISK_*/SAVED_VIEW_*/POSTMORTEM_SEVERITY/
|
|
1239
|
+
// INSIGHT_CONFIDENCE_LEVELS) died with the classes — the descriptors under
|
|
1240
|
+
// sdlc/kinds/*.kind.yaml are the single source for the enums; tests read
|
|
1241
|
+
// them from the synthesized port's schema.
|
|
1242
|
+
// LessonLearned — F3 lote-1: twin classes deleted — synthesized from
|
|
1243
|
+
// kinds/lesson-learned.kind.yaml. The old TS class was strict + missing
|
|
1244
|
+
// affect_reason/affect_evidence_refs (real drift); the descriptor unifies
|
|
1245
|
+
// on the canonical (Py) surface.
|
|
1246
|
+
// SynthesisRun — F3 lote-2 (spec 2026-06-10-kinds-descriptor-f3): the twin SynthesisRunKind classes (Py+TS) were
|
|
1247
|
+
// DELETED — synthesized from kinds/synthesis-run.kind.yaml (parity-critical
|
|
1248
|
+
// package data, byte-identical Py↔TS) via the loadDescriptors loop in
|
|
1249
|
+
// register(). Equivalence with the extinct class frozen in
|
|
1250
|
+
// tests/test_lote2_descriptor_equivalence.py (golden:
|
|
1251
|
+
// tests/goldens/lote2/SynthesisRun.golden.json).
|
|
1252
|
+
// ArchiveProposal — F3 lote-2 (spec 2026-06-10-kinds-descriptor-f3): the twin ArchiveProposalKind classes (Py+TS) were
|
|
1253
|
+
// DELETED — synthesized from kinds/archive-proposal.kind.yaml (parity-critical
|
|
1254
|
+
// package data, byte-identical Py↔TS) via the loadDescriptors loop in
|
|
1255
|
+
// register(). Equivalence with the extinct class frozen in
|
|
1256
|
+
// tests/test_lote2_descriptor_equivalence.py (golden:
|
|
1257
|
+
// tests/goldens/lote2/ArchiveProposal.golden.json).
|
|
1258
|
+
// ---------------------------------------------------------------------------
|
|
1259
|
+
// PromptTemplate — expr batch B (plan 2026-06-11-descriptor-expressiveness,
|
|
1260
|
+
// Chunk 4): the twin classes were DELETED; synthesized from
|
|
1261
|
+
// sdlc/kinds/prompt-template.kind.yaml via the loadDescriptors loop in
|
|
1262
|
+
// register().
|
|
1263
|
+
//
|
|
1264
|
+
// s-consolidate-cognitive-policies (f-kind-catalog-governance, 2026-07-07):
|
|
1265
|
+
// the 9 cognitive policy Kinds (RecallPolicy, DecayPolicy, MemoryPolicy, the
|
|
1266
|
+
// old CognitivePolicy, AllocationPolicy, PaginationPolicy,
|
|
1267
|
+
// EngramStrengthPolicy, EmbeddingProfile, AffectPalette) were consolidated
|
|
1268
|
+
// into ONE expanded CognitivePolicy descriptor
|
|
1269
|
+
// (sdlc/kinds/cognitive-policy.kind.yaml) with one top-level spec section per
|
|
1270
|
+
// former Kind. The 8 retired names are pinned in the Py kernel's
|
|
1271
|
+
// _REMOVED_KINDS (+ _REMOVED_KIND_NOTES; the write path is Py-only).
|
|
1272
|
+
// ---------------------------------------------------------------------------
|
|
1273
|
+
// ---------------------------------------------------------------------------
|
|
1274
|
+
// Kaizen — first-class improvement observation (record plane)
|
|
1275
|
+
//
|
|
1276
|
+
// F3 P2 (spec 2026-06-10-kinds-descriptor-f3): the twin KaizenKind classes
|
|
1277
|
+
// (Py + TS) were DELETED — the Kind is now synthesized from the descriptor
|
|
1278
|
+
// sdlc/kinds/kaizen.kind.yaml (parity-critical package data, byte-identical
|
|
1279
|
+
// Py↔TS) via kernel.kindFromDescriptor in register() below. Equivalence with
|
|
1280
|
+
// the old class is frozen in sdk-py tests/test_kaizen_descriptor_equivalence.py
|
|
1281
|
+
// + tests/sdlc.test.ts.
|
|
1282
|
+
// ---------------------------------------------------------------------------
|
|
1283
|
+
export class SdlcExtension {
|
|
1284
|
+
name = "sdlc";
|
|
1285
|
+
// v1.14.0 — s-consolidate-cognitive-policies: the 9 cognitive policy
|
|
1286
|
+
// Kinds consolidated into one expanded CognitivePolicy (TS parity with
|
|
1287
|
+
// Python SdlcExtension v1.14.0).
|
|
1288
|
+
version = "1.14.0";
|
|
1289
|
+
register(kernel) {
|
|
1290
|
+
kernel.kind(new RoadmapKind());
|
|
1291
|
+
kernel.kind(new EpicKind());
|
|
1292
|
+
kernel.kind(new FeatureKind());
|
|
1293
|
+
kernel.kind(new StoryKind());
|
|
1294
|
+
kernel.kind(new IssueKind());
|
|
1295
|
+
kernel.kind(new SpecKind());
|
|
1296
|
+
kernel.kind(new PlanKind());
|
|
1297
|
+
kernel.kind(new AgentSessionKind());
|
|
1298
|
+
kernel.kind(new BugKind());
|
|
1299
|
+
kernel.kind(new TaskKind());
|
|
1300
|
+
kernel.kind(new SpikeKind());
|
|
1301
|
+
kernel.kind(new InitiativeKind());
|
|
1302
|
+
// v1.10.0 — f-reference-citation-kind (ported from Python for
|
|
1303
|
+
// s-alias-generated-not-typed: Spike.depFilters → "sdlc-reference").
|
|
1304
|
+
kernel.kind(new ReferenceKind());
|
|
1305
|
+
// expr batch B: PromptTemplate is a descriptor now — registered via the
|
|
1306
|
+
// loadDescriptors loop below. s-consolidate-cognitive-policies: the
|
|
1307
|
+
// cognitive policy family is ONE descriptor (cognitive-policy.kind.yaml).
|
|
1308
|
+
// F3 P2 (spec 2026-06-10-kinds-descriptor-f3): builtin record Kinds
|
|
1309
|
+
// expressed as descriptors — kinds/*.kind.yaml package data registered
|
|
1310
|
+
// through the SAME funnel as per-scope KindDefinitions (plane lint +
|
|
1311
|
+
// digest idempotency + builtin conflict marker). Structured as a loop
|
|
1312
|
+
// so migration batches just drop files into sdlc/kinds/ — no per-Kind
|
|
1313
|
+
// code. Pilot: Kaizen (v1.13.0 s-kaizen-kind, class twins deleted).
|
|
1314
|
+
for (const raw of loadDescriptors(import.meta.url, "sdlc/kinds")) {
|
|
1315
|
+
kernel.kindFromDescriptor(raw);
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
}
|