@juangcarmona/lighthouse 0.0.0-stage → 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/README.md +32 -2
- package/assets/schemas/lighthouse-manifest.schema.json +20 -0
- package/package.json +24 -4
- package/src/lighthouse.mjs +60 -0
package/README.md
CHANGED
|
@@ -1,3 +1,33 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Lighthouse CLI
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This package is the core Lighthouse harness. It provides the `lighthouse` command, the manifest schema and the generated `LIGHTHOUSE.md` projection.
|
|
4
|
+
|
|
5
|
+
## Initialize a repository
|
|
6
|
+
|
|
7
|
+
Install the exact Lighthouse package artifacts selected for the release, create the project manifest and run `lighthouse init`. Inspect the generated `LIGHTHOUSE.md`, then run `lighthouse verify` before adding project-specific policy or exceptions.
|
|
8
|
+
|
|
9
|
+
The harness package owns the baseline command and verification contract. The SDLC package owns lifecycle skills, commands and metacommands. The UI package owns visual tokens, native recipes and `DESIGN.md`. Stack profiles own their source templates, guidance and checks.
|
|
10
|
+
|
|
11
|
+
ProductShape, ArcShape and OpenSpec keep their own files and commands. Add them through their supported integration routes when the project needs them, and keep their versions and managed paths visible in the project configuration.
|
|
12
|
+
|
|
13
|
+
## New repository
|
|
14
|
+
|
|
15
|
+
1. Select the harness, SDLC, UI and stack profile artifacts required by the application.
|
|
16
|
+
2. Create the manifest with exact package and integration versions.
|
|
17
|
+
3. Run `lighthouse init`, review the generated projection and run `lighthouse verify`.
|
|
18
|
+
4. Add the selected profile checks to the repository verification command and CI workflow.
|
|
19
|
+
5. Record project-owned exceptions with an owner and review date.
|
|
20
|
+
|
|
21
|
+
## Existing repository
|
|
22
|
+
|
|
23
|
+
1. Inventory the current source layout, tools, managed files and CI before editing.
|
|
24
|
+
2. Map existing files to the selected Lighthouse contracts and identify collisions.
|
|
25
|
+
3. Adopt the manifest and verifier first; preserve product-owned guidance and generated outputs.
|
|
26
|
+
4. Add profiles one at a time and measure their checks before making a workflow status required.
|
|
27
|
+
5. Record each exception in the project-owned documentation and remove it when the product is ready.
|
|
28
|
+
|
|
29
|
+
## Current command scope
|
|
30
|
+
|
|
31
|
+
The current command supports `init` and `verify`. It checks the manifest, exact version pins and generated content. Lifecycle stages, tracker operations, agent runs and CodeGraph checks require their own configured integrations.
|
|
32
|
+
|
|
33
|
+
The package does not contain the repository gallery, provider-owned integrations or reference source. Those remain with the source repository or the profile that owns them.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/juangcarmona/lighthouse/schemas/lighthouse-manifest.schema.json",
|
|
4
|
+
"title": "Lighthouse repository manifest",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["schemaVersion", "baseline", "product", "profiles", "integrations", "managed"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"$schema": {"type": "string"},
|
|
10
|
+
"schemaVersion": {"const": 1},
|
|
11
|
+
"baseline": {"const": "0.1.0"},
|
|
12
|
+
"product": {"type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9 ._-]{0,63}$"},
|
|
13
|
+
"profiles": {"type": "array", "items": {"enum": ["node-tooling", "dotnet-backend", "visual-theme"]}, "uniqueItems": true},
|
|
14
|
+
"integrations": {"type": "object", "additionalProperties": false, "required": ["productShape", "arcShape", "agenticSdlc"], "properties": {"productShape": {"$ref": "#/$defs/pin"}, "arcShape": {"$ref": "#/$defs/pin"}, "agenticSdlc": {"$ref": "#/$defs/pin"}}},
|
|
15
|
+
"managed": {"const": ["LIGHTHOUSE.md"]}
|
|
16
|
+
},
|
|
17
|
+
"$defs": {
|
|
18
|
+
"pin": {"type": ["string", "null"], "pattern": "^(?:\\d+\\.\\d+\\.\\d+|[a-f0-9]{40})$"}
|
|
19
|
+
}
|
|
20
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juangcarmona/lighthouse",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Lighthouse adoption and verification CLI",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/juangcarmona/lighthouse.git",
|
|
9
|
+
"directory": "src/packages/cli"
|
|
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": ["src/lighthouse.mjs", "assets", "README.md"],
|
|
23
|
+
"bin": {
|
|
24
|
+
"lighthouse": "./src/lighthouse.mjs"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
|
|
5
|
+
const root = process.cwd();
|
|
6
|
+
const manifestPath = resolve(root, 'lighthouse.json');
|
|
7
|
+
const projection = 'LIGHTHOUSE.md';
|
|
8
|
+
const usage = 'Usage: lighthouse <init|verify>';
|
|
9
|
+
|
|
10
|
+
function render(manifest) {
|
|
11
|
+
return `<!-- Generated by Lighthouse. Edit lighthouse.json and regenerate this file. -->\n\n# ${manifest.product} repository baseline\n\n- Baseline: \`${manifest.baseline}\`\n- Product: \`${manifest.product}\`\n- Profiles: ${manifest.profiles.length ? manifest.profiles.map((x) => `\`${x}\``).join(', ') : 'none'}\n- ProductShape: ${manifest.integrations.productShape ?? 'not adopted'}\n- ArcShape: ${manifest.integrations.arcShape ?? 'not adopted'}\n- Agentic SDLC: ${manifest.integrations.agenticSdlc ?? 'not adopted'}\n\n## How delivery works\n\nUse ProductShape for product intent and Product Changes, and use ArcShape for applicable architecture decisions; they can advance independently. Lighthouse carries the selected authority context through the delivery stages.\n\nA greenfield project initializes both authorities through their supported provider routes. An existing project can adopt them incrementally after its ownership and managed paths are assessed. The adoption contract includes a check of the external CodeGraph MCP service, its current git-root binding and the canonical repository and active worktrees; its index and credentials stay outside the checkout.\n\n1. \`triage\` classifies the work item, estimates complexity and blast radius, records urgency, impact, dependencies and risk, and sets configured workflow labels.\n2. \`refine\` defines the problem and stops at Ready.\n3. \`propose\` creates the solution and stops at Planned.\n4. \`implement\` applies the accepted plan and stops at Done.\n5. \`integrate\` updates the tracker, maintains the PR stack and closes the repository loop.\n6. \`review\` records learning after completion.\n\nThese are lifecycle capabilities. The baseline CLI currently provides \`init\` and \`verify\`; a configured OpenSpec, tracker or agent-host integration supplies the stage commands.\n\nChoose supervised work when a person steers each stage, plan-only work when only the proposal is needed, \`ff\` for a bounded unattended route, \`hotfix\` for a confirmed defect or \`decompose\` for a large item that needs ordered child issues and stacked PRs.\n\nThis file is managed. Put repository-specific policy in its own documentation and keep this projection generated from \`lighthouse.json\`.\n`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function validate(m) {
|
|
15
|
+
const problems = [];
|
|
16
|
+
if (!m || typeof m !== 'object' || Array.isArray(m)) return ['manifest must be an object'];
|
|
17
|
+
const allowed = ['$schema', 'schemaVersion', 'baseline', 'product', 'profiles', 'integrations', 'managed'];
|
|
18
|
+
for (const key of Object.keys(m)) if (!allowed.includes(key)) problems.push(`unknown field ${key}`);
|
|
19
|
+
for (const key of ['schemaVersion', 'baseline', 'product', 'profiles', 'integrations', 'managed']) if (!(key in m)) problems.push(`missing ${key}`);
|
|
20
|
+
if (m.schemaVersion !== 1) problems.push('schemaVersion must be 1');
|
|
21
|
+
if (m.baseline !== '0.1.0') problems.push('this verifier supports baseline 0.1.0');
|
|
22
|
+
if ('$schema' in m && typeof m.$schema !== 'string') problems.push('$schema must be a string');
|
|
23
|
+
if (typeof m.product !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9 ._-]{0,63}$/.test(m.product)) problems.push('product must be a readable name of 1–64 characters');
|
|
24
|
+
const profiles = ['node-tooling', 'dotnet-backend', 'visual-theme'];
|
|
25
|
+
if (!Array.isArray(m.profiles) || m.profiles.some((p) => !profiles.includes(p)) || new Set(m.profiles).size !== m.profiles.length) problems.push('profiles must be unique supported profile names');
|
|
26
|
+
const integrations = m.integrations;
|
|
27
|
+
const keys = ['productShape', 'arcShape', 'agenticSdlc'];
|
|
28
|
+
const pin = /^(?:\d+\.\d+\.\d+|[a-f0-9]{40})$/;
|
|
29
|
+
if (!integrations || typeof integrations !== 'object' || Array.isArray(integrations)
|
|
30
|
+
|| Object.keys(integrations).length !== keys.length
|
|
31
|
+
|| keys.some((k) => !(k in integrations) || (integrations[k] !== null && (typeof integrations[k] !== 'string' || !pin.test(integrations[k])))))
|
|
32
|
+
problems.push('integrations must declare productShape, arcShape and agenticSdlc as exact versions, commit hashes or null');
|
|
33
|
+
if (!Array.isArray(m.managed) || m.managed.length !== 1 || m.managed[0] !== projection) problems.push(`only ${projection} is managed by this version`);
|
|
34
|
+
return problems;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const command = process.argv[2];
|
|
38
|
+
if (!['init', 'verify'].includes(command)) { console.error(usage); process.exit(2); }
|
|
39
|
+
let manifest;
|
|
40
|
+
try { manifest = JSON.parse(await readFile(manifestPath, 'utf8')); }
|
|
41
|
+
catch (error) { console.error(`Cannot read lighthouse.json: ${error.message}`); process.exit(1); }
|
|
42
|
+
const problems = validate(manifest);
|
|
43
|
+
if (problems.length) { console.error(problems.map((p) => `Invalid lighthouse.json: ${p}`).join('\n')); process.exit(1); }
|
|
44
|
+
const expected = render(manifest);
|
|
45
|
+
const target = resolve(root, projection);
|
|
46
|
+
if (command === 'init') {
|
|
47
|
+
try { await readFile(target); console.error(`${projection} already exists; refusing to overwrite it. Review the manifest and manage the file explicitly.`); process.exit(1); }
|
|
48
|
+
catch (error) { if (error.code !== 'ENOENT') throw error; }
|
|
49
|
+
await writeFile(target, expected, { flag: 'wx' });
|
|
50
|
+
console.log(`Created ${projection} from lighthouse.json.`);
|
|
51
|
+
} else {
|
|
52
|
+
try {
|
|
53
|
+
const actual = await readFile(target, 'utf8');
|
|
54
|
+
if (actual !== expected) { console.error(`${projection} has drifted. Regenerate it from lighthouse.json or restore the generated content.`); process.exit(1); }
|
|
55
|
+
} catch (error) {
|
|
56
|
+
if (error.code === 'ENOENT') { console.error(`${projection} is missing; run lighthouse init after reviewing the manifest.`); process.exit(1); }
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
console.log('Lighthouse manifest and managed projection are valid.');
|
|
60
|
+
}
|