@juangcarmona/lighthouse-sdlc 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -2
- package/commands/implement.md +3 -0
- package/commands/integrate.md +3 -0
- package/commands/propose.md +3 -0
- package/commands/refine.md +3 -0
- package/commands/review.md +3 -0
- package/commands/status.md +5 -0
- package/commands/triage.md +3 -0
- package/contract.json +22 -0
- package/gates.json +10 -0
- package/meta-commands/decompose.md +3 -0
- package/meta-commands/ff.md +5 -0
- package/meta-commands/hotfix.md +3 -0
- package/meta-commands/stacked.md +3 -0
- package/package.json +39 -4
- package/routes.json +11 -0
- package/schemas/control-plane.schema.json +27 -0
- package/schemas/gates.schema.json +26 -0
- package/schemas/routes.schema.json +26 -0
- package/schemas/sdlc-contract.schema.json +41 -0
- package/skills/implement/SKILL.md +20 -0
- package/skills/integrate/SKILL.md +20 -0
- package/skills/propose/SKILL.md +20 -0
- package/skills/refine/SKILL.md +20 -0
- package/skills/review/SKILL.md +20 -0
- package/skills/triage/SKILL.md +20 -0
- package/src/sdlc.mjs +68 -0
package/README.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Lighthouse SDLC
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This package provides the provider-neutral delivery contract for Lighthouse adopters.
|
|
4
|
+
|
|
5
|
+
It owns the six lifecycle skills, their command entrypoints, route and gate descriptors, control-plane schema and deterministic package check.
|
|
6
|
+
|
|
7
|
+
It does not run agents, store transcripts, dispatch work between repositories or replace ProductShape, ArcShape, OpenSpec or an agent host.
|
|
8
|
+
|
|
9
|
+
Install it with the Lighthouse CLI or run `lighthouse-sdlc verify` from the package installation to check the distributed contract.
|
|
10
|
+
|
|
11
|
+
The package is a source of lifecycle instructions and contracts; an adopter's host adapter decides where provider-specific projections are installed.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# `/lighthouse:status`
|
|
2
|
+
|
|
3
|
+
Read `.lighthouse/sdlc.json` and report the selected SDLC package, routes, gates, state provider, memory scopes, role mappings and adapter gaps.
|
|
4
|
+
|
|
5
|
+
Read-only completion means the report matches the declared control plane and names the next supported action for every gap.
|
package/contract.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./schemas/sdlc-contract.schema.json",
|
|
3
|
+
"name": "@juangcarmona/lighthouse-sdlc",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"stages": [
|
|
6
|
+
{ "name": "triage", "skill": "skills/triage/SKILL.md", "command": "commands/triage.md", "gate": "triaged" },
|
|
7
|
+
{ "name": "refine", "skill": "skills/refine/SKILL.md", "command": "commands/refine.md", "gate": "ready" },
|
|
8
|
+
{ "name": "propose", "skill": "skills/propose/SKILL.md", "command": "commands/propose.md", "gate": "planned" },
|
|
9
|
+
{ "name": "implement", "skill": "skills/implement/SKILL.md", "command": "commands/implement.md", "gate": "done" },
|
|
10
|
+
{ "name": "integrate", "skill": "skills/integrate/SKILL.md", "command": "commands/integrate.md", "gate": "done" },
|
|
11
|
+
{ "name": "review", "skill": "skills/review/SKILL.md", "command": "commands/review.md", "gate": null }
|
|
12
|
+
],
|
|
13
|
+
"utilities": ["status"],
|
|
14
|
+
"routes": ["supervised", "plan-only", "unattended", "hotfix", "stacked"],
|
|
15
|
+
"metaCommands": ["ff", "hotfix", "decompose", "stacked"],
|
|
16
|
+
"gates": ["triaged", "ready", "planned", "done"],
|
|
17
|
+
"assets": {
|
|
18
|
+
"routes": "routes.json",
|
|
19
|
+
"gates": "gates.json",
|
|
20
|
+
"controlPlaneSchema": "schemas/control-plane.schema.json"
|
|
21
|
+
}
|
|
22
|
+
}
|
package/gates.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./schemas/gates.schema.json",
|
|
3
|
+
"version": 1,
|
|
4
|
+
"gates": [
|
|
5
|
+
{ "id": "triaged", "stage": "triage", "question": "Is the work item understood enough to choose a route?", "decisionOwner": "adopter" },
|
|
6
|
+
{ "id": "ready", "stage": "refine", "question": "Is the problem defined well enough to design a solution?", "decisionOwner": "adopter" },
|
|
7
|
+
{ "id": "planned", "stage": "propose", "question": "Is the solution and its evidence plan ready to implement?", "decisionOwner": "adopter" },
|
|
8
|
+
{ "id": "done", "stage": "implement", "question": "Does the change satisfy its deterministic and named judgement checks?", "decisionOwner": "adopter" }
|
|
9
|
+
]
|
|
10
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# `/lighthouse:ff`
|
|
2
|
+
|
|
3
|
+
Compose the stages declared by a selected route only when its independent review, correction limit and durable evidence are available.
|
|
4
|
+
|
|
5
|
+
Stop at every human-only or forge-protected decision and report the next stage instead of invoking it implicitly.
|
package/package.json
CHANGED
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juangcarmona/lighthouse-sdlc",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Provider-neutral SDLC skills, commands and route contracts for Lighthouse adopters",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/juangcarmona/lighthouse.git",
|
|
9
|
+
"directory": "src/packages/sdlc"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://juangcarmona.github.io/lighthouse/",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/juangcarmona/lighthouse/issues"
|
|
14
|
+
},
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public",
|
|
17
|
+
"provenance": true
|
|
18
|
+
},
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=22"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"commands",
|
|
24
|
+
"contract.json",
|
|
25
|
+
"gates.json",
|
|
26
|
+
"meta-commands",
|
|
27
|
+
"README.md",
|
|
28
|
+
"routes.json",
|
|
29
|
+
"schemas",
|
|
30
|
+
"skills",
|
|
31
|
+
"src"
|
|
32
|
+
],
|
|
33
|
+
"bin": {
|
|
34
|
+
"lighthouse-sdlc": "./src/sdlc.mjs"
|
|
35
|
+
},
|
|
36
|
+
"exports": {
|
|
37
|
+
".": "./src/sdlc.mjs",
|
|
38
|
+
"./contract.json": "./contract.json",
|
|
39
|
+
"./schemas/control-plane.schema.json": "./schemas/control-plane.schema.json"
|
|
40
|
+
}
|
|
41
|
+
}
|
package/routes.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./schemas/routes.schema.json",
|
|
3
|
+
"version": 1,
|
|
4
|
+
"routes": [
|
|
5
|
+
{ "id": "supervised", "stages": ["triage", "refine", "propose", "implement", "integrate", "review"], "humanGates": ["triaged", "ready", "planned", "done"] },
|
|
6
|
+
{ "id": "plan-only", "stages": ["triage", "refine", "propose"], "humanGates": ["triaged", "ready", "planned"] },
|
|
7
|
+
{ "id": "unattended", "stages": ["triage", "refine", "propose", "implement", "integrate", "review"], "humanGates": ["triaged", "ready", "planned", "done"], "requires": ["bounded-agent-run", "independent-review"] },
|
|
8
|
+
{ "id": "hotfix", "stages": ["triage", "implement", "integrate", "review"], "humanGates": ["triaged", "done"], "requires": ["confirmed-defect", "rollback-plan"] },
|
|
9
|
+
{ "id": "stacked", "stages": ["triage", "refine", "propose", "implement", "integrate", "review"], "humanGates": ["triaged", "ready", "planned", "done"], "requires": ["dependency-order", "isolated-change-scope"] }
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/juangcarmona/lighthouse/schemas/lighthouse-sdlc-control-plane.schema.json",
|
|
4
|
+
"title": "Lighthouse SDLC control plane",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["schemaVersion", "package", "routes", "gates", "state", "memory", "roles", "adapters"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"$schema": { "type": "string" },
|
|
10
|
+
"schemaVersion": { "const": 1 },
|
|
11
|
+
"package": {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"additionalProperties": false,
|
|
14
|
+
"required": ["name", "version"],
|
|
15
|
+
"properties": {
|
|
16
|
+
"name": { "const": "@juangcarmona/lighthouse-sdlc" },
|
|
17
|
+
"version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" }
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"routes": { "type": "array", "items": { "type": "string" } },
|
|
21
|
+
"gates": { "type": "array", "items": { "type": "string" } },
|
|
22
|
+
"state": { "type": "object", "additionalProperties": false, "required": ["provider"], "properties": { "provider": { "type": "string" } } },
|
|
23
|
+
"memory": { "type": "object", "additionalProperties": false, "required": ["provider", "scopes"], "properties": { "provider": { "type": "string" }, "scopes": { "type": "array", "items": { "type": "string" } } } },
|
|
24
|
+
"roles": { "type": "object", "additionalProperties": { "type": "string" } },
|
|
25
|
+
"adapters": { "type": "object", "additionalProperties": { "type": "string" } }
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/juangcarmona/lighthouse/schemas/sdlc-gates.schema.json",
|
|
4
|
+
"title": "Lighthouse SDLC gates",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["$schema", "version", "gates"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"$schema": { "type": "string" },
|
|
10
|
+
"version": { "const": 1 },
|
|
11
|
+
"gates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/gate" } }
|
|
12
|
+
},
|
|
13
|
+
"$defs": {
|
|
14
|
+
"gate": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"additionalProperties": false,
|
|
17
|
+
"required": ["id", "stage", "question", "decisionOwner"],
|
|
18
|
+
"properties": {
|
|
19
|
+
"id": { "type": "string" },
|
|
20
|
+
"stage": { "type": "string" },
|
|
21
|
+
"question": { "type": "string" },
|
|
22
|
+
"decisionOwner": { "type": "string" }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/juangcarmona/lighthouse/schemas/sdlc-routes.schema.json",
|
|
4
|
+
"title": "Lighthouse SDLC routes",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["$schema", "version", "routes"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"$schema": { "type": "string" },
|
|
10
|
+
"version": { "const": 1 },
|
|
11
|
+
"routes": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/route" } }
|
|
12
|
+
},
|
|
13
|
+
"$defs": {
|
|
14
|
+
"route": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"additionalProperties": false,
|
|
17
|
+
"required": ["id", "stages", "humanGates"],
|
|
18
|
+
"properties": {
|
|
19
|
+
"id": { "type": "string" },
|
|
20
|
+
"stages": { "type": "array", "minItems": 1, "items": { "type": "string" } },
|
|
21
|
+
"humanGates": { "type": "array", "items": { "type": "string" } },
|
|
22
|
+
"requires": { "type": "array", "items": { "type": "string" } }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/juangcarmona/lighthouse/schemas/sdlc-contract.schema.json",
|
|
4
|
+
"title": "Lighthouse SDLC package contract",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["$schema", "name", "version", "stages", "utilities", "routes", "metaCommands", "gates", "assets"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"$schema": { "type": "string" },
|
|
10
|
+
"name": { "const": "@juangcarmona/lighthouse-sdlc" },
|
|
11
|
+
"version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
|
|
12
|
+
"stages": { "type": "array", "minItems": 6, "items": { "$ref": "#/$defs/stage" } },
|
|
13
|
+
"utilities": { "type": "array", "items": { "type": "string" } },
|
|
14
|
+
"routes": { "type": "array", "items": { "type": "string" } },
|
|
15
|
+
"metaCommands": { "type": "array", "items": { "type": "string" } },
|
|
16
|
+
"gates": { "type": "array", "items": { "type": "string" } },
|
|
17
|
+
"assets": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"additionalProperties": false,
|
|
20
|
+
"required": ["routes", "gates", "controlPlaneSchema"],
|
|
21
|
+
"properties": {
|
|
22
|
+
"routes": { "type": "string" },
|
|
23
|
+
"gates": { "type": "string" },
|
|
24
|
+
"controlPlaneSchema": { "type": "string" }
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"$defs": {
|
|
29
|
+
"stage": {
|
|
30
|
+
"type": "object",
|
|
31
|
+
"additionalProperties": false,
|
|
32
|
+
"required": ["name", "skill", "command", "gate"],
|
|
33
|
+
"properties": {
|
|
34
|
+
"name": { "type": "string" },
|
|
35
|
+
"skill": { "type": "string" },
|
|
36
|
+
"command": { "type": "string" },
|
|
37
|
+
"gate": { "type": ["string", "null"] }
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lighthouse-sdlc-implement
|
|
3
|
+
description: Use when a planned work item is approved for bounded implementation and needs red-green checks, evidence and Definition of Done verification.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Implement
|
|
7
|
+
|
|
8
|
+
Implement one planned slice at a time.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
1. Read the approved plan, slice boundary, allowed paths and Definition of Done.
|
|
13
|
+
2. Start with the smallest failing deterministic check when the stack supports red-green development.
|
|
14
|
+
3. Make the smallest change that turns the check green, then run the required unit, integration and applicable higher-level checks.
|
|
15
|
+
4. Record changed paths, commands, results, evidence and any finding that needs a human decision.
|
|
16
|
+
5. Stop at the `done` gate when the Definition of Done is satisfied.
|
|
17
|
+
|
|
18
|
+
## Completion
|
|
19
|
+
|
|
20
|
+
The slice has reviewable code and evidence for every required check, with no silent scope expansion or automatic transition to integration.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lighthouse-sdlc-integrate
|
|
3
|
+
description: Use when an implemented slice is ready for dependency checks, pull request coordination, tracker synchronization and merge preparation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Integrate
|
|
7
|
+
|
|
8
|
+
Prepare a completed slice for the project's forge and branch policy.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
1. Recheck the Done evidence and the declared dependency order.
|
|
13
|
+
2. Verify the branch, commit, pull request and required CI checks against project policy.
|
|
14
|
+
3. Synchronize the work item and pull request state using the project's configured labels.
|
|
15
|
+
4. Prepare the merge or stacked change action and leave protected or human decisions explicit.
|
|
16
|
+
5. Return the integration record without merging unless the selected route and repository policy authorize it.
|
|
17
|
+
|
|
18
|
+
## Completion
|
|
19
|
+
|
|
20
|
+
The change is ready for its configured merge action, every required check is linked and unresolved decisions have an owner.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lighthouse-sdlc-propose
|
|
3
|
+
description: Use when a ready work item needs a solution proposal, OpenSpec change artifacts, test impact and a human-readable change overview.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Propose
|
|
7
|
+
|
|
8
|
+
Describe the smallest implementable solution for a Ready item.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
1. Read the Ready evidence and inspect the current product and architecture authorities.
|
|
13
|
+
2. Create or update the OpenSpec change artifacts through the installed OpenSpec workflow.
|
|
14
|
+
3. Describe the solution, interfaces, data effects, test impact, slices, risks and Definition of Done.
|
|
15
|
+
4. Write `change-overview` prose with the Humanizer skill while preserving facts, links, commands, frontmatter and code.
|
|
16
|
+
5. Stop at the `planned` gate and state the human decision required before implementation.
|
|
17
|
+
|
|
18
|
+
## Completion
|
|
19
|
+
|
|
20
|
+
The change artifacts explain the future state, the slices are dependency ordered, the evidence plan is explicit and the Planned decision remains visible.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lighthouse-sdlc-refine
|
|
3
|
+
description: Use when a triaged work item needs a precise problem, scope, acceptance criteria, dependencies and Definition of Ready.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Refine
|
|
7
|
+
|
|
8
|
+
Turn a triaged item into a problem that can be designed.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
1. Read the triage record, product context and relevant architecture evidence.
|
|
13
|
+
2. State the problem, affected users, constraints, acceptance criteria and explicit out-of-scope work.
|
|
14
|
+
3. Resolve or record dependencies, risks, assumptions and missing evidence.
|
|
15
|
+
4. Check the Definition of Ready and return the evidence that supports each check.
|
|
16
|
+
5. Stop at the `ready` gate and name the next decision.
|
|
17
|
+
|
|
18
|
+
## Completion
|
|
19
|
+
|
|
20
|
+
The work item has a bounded problem statement, testable acceptance criteria, resolved owners for open dependencies and a Ready decision.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lighthouse-sdlc-review
|
|
3
|
+
description: Use after integration to record delivery evidence, findings, follow-up work and process learning for one completed change.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Review
|
|
7
|
+
|
|
8
|
+
Close the delivery record and make the next improvement visible.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
1. Read the change overview, implementation evidence, integration result and review findings.
|
|
13
|
+
2. Classify findings as accepted, deferred, fixed or rejected with an owner and follow-up reference.
|
|
14
|
+
3. Record the evidence, outcome, useful learning and any product or architecture follow-up.
|
|
15
|
+
4. Confirm the work item and pull request have the project's final labels.
|
|
16
|
+
5. End the route with a review record and return the next backlog decision without opening another delivery gate.
|
|
17
|
+
|
|
18
|
+
## Completion
|
|
19
|
+
|
|
20
|
+
The completed change has a durable review record, classified findings and a clear follow-up owner.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lighthouse-sdlc-triage
|
|
3
|
+
description: Use when a work item enters the Lighthouse lifecycle and needs urgency, impact, dependencies, risk, complexity, blast radius and a delivery route.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Triage
|
|
7
|
+
|
|
8
|
+
Classify one work item before refinement.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
1. Read the work item, its linked Product Change and the repository control plane.
|
|
13
|
+
2. Inspect the affected code and architecture evidence with the available repository tools.
|
|
14
|
+
3. Record urgency, impact, dependencies, risk, complexity, blast radius, route and owner with a confidence note for each estimate.
|
|
15
|
+
4. Apply only the project's declared tracker labels and report the label changes.
|
|
16
|
+
5. Return the structured triage record and stop at the `triaged` gate.
|
|
17
|
+
|
|
18
|
+
## Completion
|
|
19
|
+
|
|
20
|
+
The record names the route, owner, labels, estimates, confidence and next decision, and no later stage has started.
|
package/src/sdlc.mjs
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { access, readFile } from 'node:fs/promises';
|
|
3
|
+
import { constants } from 'node:fs';
|
|
4
|
+
import { dirname, resolve } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
8
|
+
const contractPath = resolve(packageRoot, 'contract.json');
|
|
9
|
+
|
|
10
|
+
async function readJson(path) {
|
|
11
|
+
return JSON.parse(await readFile(path, 'utf8'));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async function exists(path) {
|
|
15
|
+
try { await access(path, constants.F_OK); return true; } catch { return false; }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function verifyContract() {
|
|
19
|
+
const problems = [];
|
|
20
|
+
let contract;
|
|
21
|
+
try { contract = await readJson(contractPath); }
|
|
22
|
+
catch (error) { return [`Cannot read contract.json: ${error.message}`]; }
|
|
23
|
+
if (contract.name !== '@juangcarmona/lighthouse-sdlc') problems.push('contract name is incorrect');
|
|
24
|
+
if (!/^\d+\.\d+\.\d+$/.test(contract.version ?? '')) problems.push('contract version must be semver-like');
|
|
25
|
+
const stages = Array.isArray(contract.stages) ? contract.stages : [];
|
|
26
|
+
const expectedStages = ['triage', 'refine', 'propose', 'implement', 'integrate', 'review'];
|
|
27
|
+
if (stages.map((stage) => stage.name).join(',') !== expectedStages.join(',')) problems.push('stages must be triage, refine, propose, implement, integrate, review in order');
|
|
28
|
+
for (const stage of stages) {
|
|
29
|
+
for (const asset of [stage.skill, stage.command]) if (!(await exists(resolve(packageRoot, asset)))) problems.push(`missing stage asset ${asset}`);
|
|
30
|
+
}
|
|
31
|
+
for (const asset of [contract.assets?.routes, contract.assets?.gates, contract.assets?.controlPlaneSchema]) {
|
|
32
|
+
if (!asset || !(await exists(resolve(packageRoot, asset)))) problems.push(`missing contract asset ${asset ?? '(empty)'}`);
|
|
33
|
+
}
|
|
34
|
+
for (const asset of ['routes.json', 'gates.json', 'schemas/routes.schema.json', 'schemas/gates.schema.json', 'schemas/control-plane.schema.json']) {
|
|
35
|
+
if (!(await exists(resolve(packageRoot, asset)))) problems.push(`missing package asset ${asset}`);
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const routes = await readJson(resolve(packageRoot, 'routes.json'));
|
|
39
|
+
const routeIds = routes.routes?.map((route) => route.id) ?? [];
|
|
40
|
+
if (routeIds.join(',') !== contract.routes.join(',')) problems.push('routes.json does not match contract routes');
|
|
41
|
+
} catch (error) { problems.push(`Cannot read routes.json: ${error.message}`); }
|
|
42
|
+
try {
|
|
43
|
+
const gates = await readJson(resolve(packageRoot, 'gates.json'));
|
|
44
|
+
const gateIds = gates.gates?.map((gate) => gate.id) ?? [];
|
|
45
|
+
if (gateIds.join(',') !== contract.gates.join(',')) problems.push('gates.json does not match contract gates');
|
|
46
|
+
} catch (error) { problems.push(`Cannot read gates.json: ${error.message}`); }
|
|
47
|
+
for (const command of ['status', ...expectedStages]) if (!(await exists(resolve(packageRoot, `commands/${command}.md`)))) problems.push(`missing command asset ${command}`);
|
|
48
|
+
for (const metaCommand of contract.metaCommands ?? []) if (!(await exists(resolve(packageRoot, `meta-commands/${metaCommand}.md`)))) problems.push(`missing meta-command asset ${metaCommand}`);
|
|
49
|
+
return problems;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const command = process.argv[2] ?? 'verify';
|
|
53
|
+
if (!['contract', 'verify'].includes(command)) {
|
|
54
|
+
console.error('Usage: lighthouse-sdlc <contract|verify>');
|
|
55
|
+
process.exit(2);
|
|
56
|
+
}
|
|
57
|
+
if (command === 'contract') {
|
|
58
|
+
console.log(await readFile(contractPath, 'utf8'));
|
|
59
|
+
} else {
|
|
60
|
+
const problems = await verifyContract();
|
|
61
|
+
if (problems.length) {
|
|
62
|
+
for (const problem of problems) console.error(problem);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
console.log('Lighthouse SDLC package contract is valid.');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { contractPath, verifyContract };
|