diff --git a/README.md b/README.md index 8692073..8f44267 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,19 @@ Already adopted AgentFlow? Use [`docs/assisted-update.md`](docs/assisted-update. node bin/cli.mjs update-prompt --target /path/to/your-project ``` +## Cockpit Goal Command Center + +Cockpit is the optional, first-class Goal Command Center for AgentFlow SDLC. CLI/GitHub workflow remains authoritative and fully usable without starting Cockpit; Cockpit reads durable SDLC records and presents goals, readiness, role flow, releases, approvals, replay, follow-ups, and safe workflow actions. + +Start it when you want visual operations: + +```bash +AGENTFLOW_REPOSITORIES=owner/repo agentflow-sdlc cockpit +agentflow-sdlc cockpit doctor --json +``` + +Read more: [`docs/cockpit.md`](docs/cockpit.md) and [`docs/cockpit-concepts-and-rules.md`](docs/cockpit-concepts-and-rules.md). + ## Documentation map | Need | Go here | @@ -74,6 +87,7 @@ node bin/cli.mjs update-prompt --target /path/to/your-project | Install or evaluate | [`docs/get-started.md`](docs/get-started.md) | | Run issue work or contribute | [`docs/guides/contribution-workflow.md`](docs/guides/contribution-workflow.md) | | Learn intelligent collaboration | [`docs/intelligent-collaboration.md`](docs/intelligent-collaboration.md) | +| Use optional Goal Command Center | [`docs/cockpit.md`](docs/cockpit.md) | | Follow the workflow contract | [`docs/agent-workflow.md`](docs/agent-workflow.md) | | Follow issue rules | [`docs/issue-standards.md`](docs/issue-standards.md) | | Configure a project | [`docs/project-config.md`](docs/project-config.md) | @@ -88,6 +102,7 @@ node bin/cli.mjs update-prompt --target /path/to/your-project - Role-agent packages: `agents/roles/`. - Workflow skills: `agents/workflows/orchestrate/`, `scan/`, and `intelligent-collaboration/`. - Validators and helpers under `scripts/` and `lib/`. +- Optional Cockpit Goal Command Center: `agentflow-sdlc cockpit`. - Examples and eval scaffolding under `docs/examples/` and `agents/evals/`. ## Contributing diff --git a/adapters/agy/manifest.json b/adapters/agy/manifest.json index 0afde86..dcc4ab0 100644 --- a/adapters/agy/manifest.json +++ b/adapters/agy/manifest.json @@ -5,6 +5,10 @@ "harness": "agy", "entry": ".agents/skills", "skills": ["sdlc-definition", "sdlc-migration", "sdlc-audit"], - "commands": ["agentflow-sdlc sdlc validate", "agentflow-sdlc skills sync --harness agy"], + "commands": [ + "agentflow-sdlc sdlc validate", + "agentflow-sdlc skills sync --harness agy", + "agentflow-sdlc cockpit doctor --json" + ], "settings": [".agy/settings.json"] } diff --git a/adapters/claude-code/manifest.json b/adapters/claude-code/manifest.json index d67333d..2852787 100644 --- a/adapters/claude-code/manifest.json +++ b/adapters/claude-code/manifest.json @@ -5,6 +5,10 @@ "harness": "claude-code", "entry": ".claude/skills", "skills": ["sdlc-definition", "sdlc-migration", "sdlc-audit"], - "commands": ["agentflow-sdlc sdlc validate", "agentflow-sdlc skills sync --harness claude-code"], + "commands": [ + "agentflow-sdlc sdlc validate", + "agentflow-sdlc skills sync --harness claude-code", + "agentflow-sdlc cockpit doctor --json" + ], "settings": [".claude/settings.json"] } diff --git a/adapters/codex/manifest.json b/adapters/codex/manifest.json index fe06755..8c13d35 100644 --- a/adapters/codex/manifest.json +++ b/adapters/codex/manifest.json @@ -5,6 +5,10 @@ "harness": "codex", "entry": ".agents/skills", "skills": ["sdlc-definition", "sdlc-migration", "sdlc-audit"], - "commands": ["agentflow-sdlc sdlc validate", "agentflow-sdlc skills sync --harness codex"], + "commands": [ + "agentflow-sdlc sdlc validate", + "agentflow-sdlc skills sync --harness codex", + "agentflow-sdlc cockpit doctor --json" + ], "settings": [".codex/hooks.json"] } diff --git a/adapters/pi/manifest.json b/adapters/pi/manifest.json index 83e56c2..21e0cb7 100644 --- a/adapters/pi/manifest.json +++ b/adapters/pi/manifest.json @@ -5,6 +5,10 @@ "harness": "pi", "entry": ".pi/skills", "skills": ["sdlc-definition", "sdlc-migration", "sdlc-audit"], - "commands": ["agentflow-sdlc sdlc validate", "agentflow-sdlc skills sync --harness pi"], + "commands": [ + "agentflow-sdlc sdlc validate", + "agentflow-sdlc skills sync --harness pi", + "agentflow-sdlc cockpit doctor --json" + ], "settings": [".pi/settings.json"] } diff --git a/bin/cli.mjs b/bin/cli.mjs index 369a6f4..860a1fe 100644 --- a/bin/cli.mjs +++ b/bin/cli.mjs @@ -269,6 +269,31 @@ function handleSettings(rest, targetDir) { process.exit(2) } +function handleCockpit(rest, targetDir) { + const [subcommand] = positionalArgs(rest) + const pass = rest.filter((arg) => arg !== subcommand) + if (subcommand === 'doctor') return runScript('scripts/cockpit-doctor.mjs', pass, targetDir) + if (!subcommand || subcommand === 'start') { + const result = spawnSync( + process.execPath, + [resolve(packageRoot, 'scripts/cockpit-server.mjs')], + { + stdio: 'inherit', + env: { + ...process.env, + AGENTFLOW_REPOSITORIES: + process.env.AGENTFLOW_REPOSITORIES || process.env.COCKPIT_REPOSITORIES || '', + }, + }, + ) + process.exit(result.status ?? 1) + } + process.stderr.write( + `Usage:\n agentflow-sdlc cockpit [start]\n agentflow-sdlc cockpit doctor [--json]\n`, + ) + process.exit(2) +} + function handleExtensions(rest, targetDir) { const [subcommand, selector] = positionalArgs(rest) const json = rest.includes('--json') @@ -373,6 +398,10 @@ function main() { const [command, ...rest] = process.argv.slice(2) const targetDir = resolve(getFlag(rest, '--target', process.cwd())) + if (command === 'cockpit') { + handleCockpit(rest, targetDir) + } + if (command === 'plugins') { handlePlugins(rest, targetDir) } @@ -472,7 +501,7 @@ function main() { } process.stderr.write( - 'Usage: agentflow-sdlc [path] [--target ] [--json]\n', + 'Usage: agentflow-sdlc [path] [--target ] [--json]\n', ) process.exit(2) } diff --git a/docs/cockpit.md b/docs/cockpit.md index 77dfe99..880438b 100644 --- a/docs/cockpit.md +++ b/docs/cockpit.md @@ -2,7 +2,7 @@ AgentFlow Cockpit is the optional Goal Command Center for goal-oriented SDLC delivery. It turns GitHub issues, epics, comments, PRs, role-pass evidence, validation, and follow-ups into goals, evidence health, role flow contributions, graph navigation, next-best-actions, and replayable goal stories. -Cockpit is optional. The CLI/GitHub workflow remains authoritative and fully usable without Cockpit. +Cockpit is optional at runtime and first-class in the AgentFlow SDLC product. The CLI/GitHub workflow remains authoritative and fully usable without Cockpit. `init`, `sync`, `doctor`, validators, skills, plugins, and settings merge must not require a running Cockpit server. For the implemented product vocabulary and rules, see [`docs/cockpit-concepts-and-rules.md`](cockpit-concepts-and-rules.md). Use that document when reviewing SDLC roles, skills, and agents. @@ -16,6 +16,16 @@ For the implemented product vocabulary and rules, see [`docs/cockpit-concepts-an - Follow-up issues are first-class; hidden TODOs are not. - No raw model transcripts, prompts, tool inputs, secrets, or hidden runner state in the UI. +## CLI + +```bash +AGENTFLOW_REPOSITORIES=owner/repo agentflow-sdlc cockpit +agentflow-sdlc cockpit doctor --json +node scripts/cockpit-smoke.mjs +``` + +`cockpit doctor` validates package files and runtime configuration. `cockpit-smoke` is a release gate that starts the server, checks `/healthz`, and verifies packaged assets. + ## MVP authentication Remote-capable Cockpit uses GitHub OAuth as the MVP authentication option. diff --git a/docs/index.md b/docs/index.md index e99133c..4936dcb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,26 +4,28 @@ This index maps the main concepts, defaults, roles, skills/workflows, templates, ## Start here -1. [`../README.md`](../README.md) — concise front door: value, first steps, and document map. -2. [`start-here.md`](start-here.md) — route humans and agents to the right document. -3. [`agentflow-in-5-minutes.md`](agentflow-in-5-minutes.md) — short public explainer for the problem, lifecycle, primary evaluation path, and evidence model. -4. [`get-started.md`](get-started.md) — assisted onboarding, install, configuration, sync, and verification path. -5. [`assisted-onboarding.md`](assisted-onboarding.md) — LLM-assisted setup for existing projects with read-only inspection and explicit approval before changes. -6. [`assisted-update.md`](assisted-update.md) — LLM-assisted update workflow for already-adopted projects using `agent-framework-lock.json`, `doctor`, `sync`, and `mark-merged`. [`deterministic-assisted-update.md`](deterministic-assisted-update.md) documents the proposed deterministic update-plan direction. -7. [`environment-tools.md`](environment-tools.md) — required, recommended, and optional tools compatible with `doctor-env`. -8. [`../AGENTS.md`](../AGENTS.md) — required first-read repository policy. -9. [`project-setup.md`](project-setup.md) — guided setup choices for agents, execution mode, routing, branch strategy, validation, bounded work, and skill provenance. -10. [`agent-workflow.md`](agent-workflow.md) — phase model, role-pass contract, durable evidence, branch strategy, review model, and PR readiness. -11. [`issue-standards.md`](issue-standards.md) — issue titles, labels, body update rules, and lifecycle metadata. -12. [`project-config.md`](project-config.md) — project-local `agent-workflow.config.json` contract. -13. [`execution-targets.md`](execution-targets.md) — `executionTarget`, `transport`, `launcher`, `executor`, and `delegationBoundary` concepts that disambiguate `with claude`/`with agy`/`with pi` requests. -14. [`capabilities.md`](capabilities.md) — portable PLAN/WORKFLOW/LOOP/SUB-AGENTS capability vocabulary, resolution modes, evidence, and adapter links. -15. [`intelligent-collaboration.md`](intelligent-collaboration.md) — collaboration modes, decision budget, smallest-sufficient-collaboration rule, bounded helper intelligence, and compact evidence guidance. -16. [`release-versioning.md`](release-versioning.md) — configurable release strategy, default `main.minor.fix`, release evidence, validators, and preview helpers. -17. [`extension-packs.md`](extension-packs.md) — repository-level contrib-style overlays for opinionated engineering approaches, skills, tools, templates, and validators. -18. [`examples/simple-bugfix-flow.md`](examples/simple-bugfix-flow.md), [`examples/multi-agent-review-flow.md`](examples/multi-agent-review-flow.md), [`examples/high-assurance-flow.md`](examples/high-assurance-flow.md), and [`examples/intelligent-collaboration-flow.md`](examples/intelligent-collaboration-flow.md) — public example flows and evidence excerpts. -19. [`default-skills.md`](default-skills.md) — default skills, recommended companion skills, upstream repositories, and CCPM-sourced skill surfaces. -20. [`../agents/agentflow-sdlc/README.md`](../agents/agentflow-sdlc/README.md) — canonical portable AgentFlow SDLC agent package with maturity, capability, handoff, eval, and improvement-loop contracts. +1. [`../README.md`](../README.md) � concise front door: value, first steps, and document map. +2. [`start-here.md`](start-here.md) � route humans and agents to the right document. +3. [`agentflow-in-5-minutes.md`](agentflow-in-5-minutes.md) � short public explainer for the problem, lifecycle, primary evaluation path, and evidence model. +4. [`get-started.md`](get-started.md) � assisted onboarding, install, configuration, sync, and verification path. +5. [`assisted-onboarding.md`](assisted-onboarding.md) � LLM-assisted setup for existing projects with read-only inspection and explicit approval before changes. +6. [`assisted-update.md`](assisted-update.md) � LLM-assisted update workflow for already-adopted projects using `agent-framework-lock.json`, `doctor`, `sync`, and `mark-merged`. [`deterministic-assisted-update.md`](deterministic-assisted-update.md) documents the proposed deterministic update-plan direction. +7. [`environment-tools.md`](environment-tools.md) � required, recommended, and optional tools compatible with `doctor-env`. +8. [`../AGENTS.md`](../AGENTS.md) � required first-read repository policy. +9. [`project-setup.md`](project-setup.md) � guided setup choices for agents, execution mode, routing, branch strategy, validation, bounded work, and skill provenance. +10. [`agent-workflow.md`](agent-workflow.md) � phase model, role-pass contract, durable evidence, branch strategy, review model, and PR readiness. +11. [`issue-standards.md`](issue-standards.md) � issue titles, labels, body update rules, and lifecycle metadata. +12. [`project-config.md`](project-config.md) � project-local `agent-workflow.config.json` contract. +13. [`execution-targets.md`](execution-targets.md) � `executionTarget`, `transport`, `launcher`, `executor`, and `delegationBoundary` concepts that disambiguate `with claude`/`with agy`/`with pi` requests. +14. [`capabilities.md`](capabilities.md) � portable PLAN/WORKFLOW/LOOP/SUB-AGENTS capability vocabulary, resolution modes, evidence, and adapter links. +15. [`intelligent-collaboration.md`](intelligent-collaboration.md) � collaboration modes, decision budget, smallest-sufficient-collaboration rule, bounded helper intelligence, and compact evidence guidance. +16. [`release-versioning.md`](release-versioning.md) � configurable release strategy, default `main.minor.fix`, release evidence, validators, and preview helpers. +17. [`cockpit.md`](cockpit.md) � optional first-class Goal Command Center for visual goal, readiness, release, replay, and approval operations. +18. [`cockpit-concepts-and-rules.md`](cockpit-concepts-and-rules.md) � Cockpit product language, safety, action, and support-boundary rules. +19. [`extension-packs.md`](extension-packs.md) � repository-level contrib-style overlays for opinionated engineering approaches, skills, tools, templates, and validators. +20. [`examples/simple-bugfix-flow.md`](examples/simple-bugfix-flow.md), [`examples/multi-agent-review-flow.md`](examples/multi-agent-review-flow.md), [`examples/high-assurance-flow.md`](examples/high-assurance-flow.md), and [`examples/intelligent-collaboration-flow.md`](examples/intelligent-collaboration-flow.md) � public example flows and evidence excerpts. +21. [`default-skills.md`](default-skills.md) � default skills, recommended companion skills, upstream repositories, and CCPM-sourced skill surfaces. +22. [`../agents/agentflow-sdlc/README.md`](../agents/agentflow-sdlc/README.md) � canonical portable AgentFlow SDLC agent package with maturity, capability, handoff, eval, and improvement-loop contracts. ## What it is @@ -64,6 +66,8 @@ Intelligent collaboration: [`intelligent-collaboration.md`](intelligent-collabor The framework also supports locally managed skills/tooling in consuming projects. Install workflow skills using your agent/skill manager, then use the sync CLI for hooks, templates, docs, and validators. See [`default-skills.md`](default-skills.md) for upstream source and provenance notes. +Optional visual operations use Cockpit, the first-class Goal Command Center. Cockpit is package-owned and runtime opt-in; `init`, `sync`, `doctor`, validators, skills, plugins, and settings do not require starting it. + ## Defaults | Area | Default | diff --git a/docs/release-publishing.md b/docs/release-publishing.md index 85f038d..328a1ab 100644 --- a/docs/release-publishing.md +++ b/docs/release-publishing.md @@ -52,11 +52,23 @@ agentflow-sdlc settings status --harness all --json The merge engine preserves project-owned keys and only injects the `agentflowSdlc` managed object from `manifests/harness-settings.json`. +## Cockpit gate + +Cockpit is optional at runtime and first-class in the product artifact. It must be packaged, documented, and smoke-tested, but default install must not start a server, require OAuth, or enable write actions. + +Run: + +```bash +AGENTFLOW_REPOSITORIES=owner/repo agentflow-sdlc cockpit doctor --json +node scripts/cockpit-smoke.mjs +``` + ## Full v1 release gate ```bash pnpm test node scripts/sdlc-sandbox-smoke.mjs +node scripts/cockpit-smoke.mjs node scripts/validate-npm-package.mjs agentflow-sdlc plugins validate --harness all --json agentflow-sdlc settings merge --harness all --dry-run diff --git a/docs/sdlc-definition.md b/docs/sdlc-definition.md index 6efdf03..dc2d6d4 100644 --- a/docs/sdlc-definition.md +++ b/docs/sdlc-definition.md @@ -13,22 +13,25 @@ Harness-specific directories such as `.pi`, `.claude`, `.agy`, and `.codex` are ## Core concepts -| Concept | Meaning | Durable sources | -| ---------------------- | ------------------------------------------------------- | ------------------------------------------- | -| Workspace | Configured repository/project boundary | config, Cockpit query state | -| Goal Group | Parent objective/epic | issue body, relationships | -| Goal | Delivery objective with acceptance | issue body, labels, comments | -| Delivery | Implementation and PR activity | PR, commits, checks | -| Role Flow | Ordered role contributions and returns | role-pass, workflow-status, handover | -| Readiness | Path-aware applicable quality state | issue/PR evidence, checks | -| Release | Target, impact, assignment, released/unreleased state | issue fields, milestone, PR/release records | -| Human approval gate | Explicit human decision required by high-assurance work | PR review or gate record | -| Follow-up | Deferred work tracked as issue | follow-up issue links | -| Source | External durable record link | GitHub issue/PR/comment/check URLs | -| Guided workflow action | Preview-first safe update to durable workflow records | Cockpit/action audit | +| Concept | Meaning | Durable sources | +| ---------------------- | ---------------------------------------------------------------------- | ------------------------------------------- | +| Workspace | Configured repository/project boundary | config, Cockpit query state | +| Goal Group | Parent objective/epic | issue body, relationships | +| Goal | Delivery objective with acceptance | issue body, labels, comments | +| Delivery | Implementation and PR activity | PR, commits, checks | +| Role Flow | Ordered role contributions and returns | role-pass, workflow-status, handover | +| Readiness | Path-aware applicable quality state | issue/PR evidence, checks | +| Release | Target, impact, assignment, released/unreleased state | issue fields, milestone, PR/release records | +| Human approval gate | Explicit human decision required by high-assurance work | PR review or gate record | +| Follow-up | Deferred work tracked as issue | follow-up issue links | +| Source | External durable record link | GitHub issue/PR/comment/check URLs | +| Guided workflow action | Preview-first safe update to durable workflow records | Cockpit/action audit | +| Cockpit | Optional first-class Goal Command Center projecting durable SDLC state | package runtime, GitHub/CLI records | GitHub is current storage substrate. Product language leads with AgentFlow concepts. +Cockpit is an official optional projection of this model. It may visualize goals, readiness, role flow, release state, replay, approvals, and follow-ups, but it must not own unique SDLC state or be required by `init`, `sync`, `doctor`, validators, skills, plugins, or settings merge. + ## Paths Canonical workflow profiles: diff --git a/docs/start-here.md b/docs/start-here.md index bbd74eb..deec6d9 100644 --- a/docs/start-here.md +++ b/docs/start-here.md @@ -35,6 +35,7 @@ This page routes humans and agents to the right AgentFlow SDLC document without | Portable capabilities | [`capabilities.md`](capabilities.md) | | Project config | [`project-config.md`](project-config.md) | | Release versioning | [`release-versioning.md`](release-versioning.md) | +| Goal Command Center | [`cockpit.md`](cockpit.md) | ## If you are an agent @@ -47,3 +48,14 @@ Use this deterministic entry sequence: 5. active issue or `SPEC.md` Then use role packages under `agents/roles/` and workflow skills under `agents/workflows/` as needed. + +## If you want visual operations + +Use Cockpit as optional Goal Command Center: + +```bash +AGENTFLOW_REPOSITORIES=owner/repo agentflow-sdlc cockpit +agentflow-sdlc cockpit doctor --json +``` + +Cockpit is first-class in product docs and release gates, but runtime opt-in. Normal SDLC work does not require starting a service, opening a port, or configuring OAuth. diff --git a/lib/framework-files.mjs b/lib/framework-files.mjs index 475085c..41d731a 100644 --- a/lib/framework-files.mjs +++ b/lib/framework-files.mjs @@ -41,6 +41,8 @@ export const FRAMEWORK_FILES = [ 'docs/sdlc-definition.md', 'docs/sdlc-packaging.md', 'docs/release-publishing.md', + 'docs/cockpit.md', + 'docs/cockpit-concepts-and-rules.md', 'docs/agents/agy-routing.md', 'docs/agents/codex-routing.md', 'docs/agents/claude-routing.md', @@ -278,6 +280,8 @@ export const FRAMEWORK_FILES = [ 'scripts/sdlc-audit.mjs', 'scripts/sdlc-migrate.mjs', 'scripts/sdlc-sandbox-smoke.mjs', + 'scripts/cockpit-doctor.mjs', + 'scripts/cockpit-smoke.mjs', 'scripts/validate-npm-package.mjs', 'scripts/validate-extension-packs.mjs', 'scripts/extension-pack.mjs', diff --git a/manifests/npm-package.json b/manifests/npm-package.json index 1b87d04..4829e14 100644 --- a/manifests/npm-package.json +++ b/manifests/npm-package.json @@ -31,7 +31,16 @@ "adapters/claude-code/.claude-plugin/plugin.json", "adapters/agy/plugin.json", "adapters/codex/plugin.json", - "adapters/pi/plugin.json" + "adapters/pi/plugin.json", + "assets/cockpit/agentflow-logo.png", + "scripts/cockpit-server.mjs", + "scripts/cockpit-doctor.mjs", + "scripts/cockpit-smoke.mjs", + "lib/cockpit-ui.mjs", + "lib/cockpit-read-model.mjs", + "lib/cockpit-goal-model.mjs", + "docs/cockpit.md", + "docs/cockpit-concepts-and-rules.md" ], "forbiddenPathPrefixes": [ ".pi/", diff --git a/manifests/product-payload.json b/manifests/product-payload.json index 9d43244..a64ce55 100644 --- a/manifests/product-payload.json +++ b/manifests/product-payload.json @@ -35,6 +35,16 @@ "source": "skills/sdlc-audit/SKILL.md", "target": "skills/sdlc-audit/SKILL.md", "ownership": "managed" + }, + { + "source": "docs/cockpit.md", + "target": "docs/cockpit.md", + "ownership": "managed" + }, + { + "source": "docs/cockpit-concepts-and-rules.md", + "target": "docs/cockpit-concepts-and-rules.md", + "ownership": "managed" } ] } diff --git a/package.json b/package.json index 3c5c482..11836b7 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "format": "prettier --write .", "format:check": "prettier --check .", "validate:npm": "node scripts/validate-npm-package.mjs", - "validate:release": "pnpm test && node scripts/sdlc-sandbox-smoke.mjs && node scripts/validate-npm-package.mjs" + "validate:release": "pnpm test && node scripts/sdlc-sandbox-smoke.mjs && node scripts/cockpit-smoke.mjs && node scripts/validate-npm-package.mjs" }, "devDependencies": { "prettier": "^3.3.3", @@ -47,6 +47,7 @@ "url": "https://github.com/smota/agentflow-sdlc/issues" }, "files": [ + "assets/", "adapters/", "agents/", "bin/", diff --git a/scripts/cockpit-doctor.mjs b/scripts/cockpit-doctor.mjs new file mode 100644 index 0000000..8990789 --- /dev/null +++ b/scripts/cockpit-doctor.mjs @@ -0,0 +1,62 @@ +#!/usr/bin/env node +import { existsSync } from 'node:fs' +import { dirname, join, resolve } from 'node:path' +import { fileURLToPath } from 'node:url' +import { loadCockpitConfig, validateCockpitConfig } from '../lib/cockpit-config.mjs' + +const args = process.argv.slice(2) +const json = args.includes('--json') +const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..') +const config = loadCockpitConfig() +const validation = validateCockpitConfig(config) +const files = [ + 'scripts/cockpit-server.mjs', + 'lib/cockpit-ui.mjs', + 'lib/cockpit-read-model.mjs', + 'lib/cockpit-goal-model.mjs', + 'assets/cockpit/agentflow-logo.png', +] +const missingFiles = files.filter((file) => !existsSync(join(packageRoot, file))) +const findings = [] +if (missingFiles.length) + findings.push( + ...missingFiles.map((file) => ({ + severity: 'blocker', + code: 'cockpit.file', + message: `missing ${file}`, + })), + ) +findings.push( + ...validation.errors.map((message) => ({ severity: 'blocker', code: 'cockpit.config', message })), +) +findings.push( + ...validation.warnings.map((message) => ({ severity: 'info', code: 'cockpit.config', message })), +) +if (config.writeActions && (!config.remote || !config.sessionSecret)) + findings.push({ + severity: 'high', + code: 'cockpit.write-actions', + message: + 'COCKPIT_WRITE_ACTIONS requires hardened remote auth/session configuration for production use', + }) +const report = { + ok: findings.every((item) => !['blocker', 'high'].includes(item.severity)), + enabled: config.enabled, + mode: config.remote ? 'remote' : 'local', + readOnly: !config.writeActions, + chatEnabled: config.chat, + runnerTelemetry: config.runnerTelemetry, + repositories: config.repositories, + port: config.port, + publicUrl: config.publicUrl, + findings, +} +if (json) process.stdout.write(`${JSON.stringify(report, null, 2)}\n`) +else { + process.stdout.write('AgentFlow Cockpit doctor\n') + process.stdout.write(`Mode: ${report.mode}\nRead-only: ${report.readOnly ? 'yes' : 'no'}\n`) + for (const item of findings) + process.stdout.write(` ${item.severity.toUpperCase()} ${item.code}: ${item.message}\n`) + process.stdout.write(`Result: ${report.ok ? 'READY' : 'FAILED'}\n`) +} +process.exit(report.ok ? 0 : 1) diff --git a/scripts/cockpit-server.mjs b/scripts/cockpit-server.mjs index 2e29d4f..d0604e4 100644 --- a/scripts/cockpit-server.mjs +++ b/scripts/cockpit-server.mjs @@ -2,7 +2,8 @@ import { createServer } from 'node:http' import { randomBytes } from 'node:crypto' import { appendFileSync, mkdirSync, readFileSync } from 'node:fs' -import { extname, join, normalize } from 'node:path' +import { dirname, extname, join, normalize, resolve } from 'node:path' +import { fileURLToPath } from 'node:url' import { formatDurableActionBody, parseCockpitIntent, @@ -30,7 +31,12 @@ import { renderIssueView, } from '../lib/cockpit-ui.mjs' +const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..') const config = loadCockpitConfig() +if (!config.enabled) { + console.log('AgentFlow Cockpit disabled by COCKPIT_ENABLED=false') + process.exit(0) +} const validation = validateCockpitConfig(config) if (!validation.ok) { console.error( @@ -392,10 +398,17 @@ function text(res, body, contentType = 'text/plain; charset=utf-8', status = 200 function asset(res, pathname) { const relative = normalize(pathname.replace(/^\/assets\/cockpit\//, '')).replace(/^\.\.[/\\]/, '') - const fullPath = join('assets', 'cockpit', relative) + const fullPath = join(packageRoot, 'assets', 'cockpit', relative) const type = extname(fullPath) === '.png' ? 'image/png' : 'application/octet-stream' - res.writeHead(200, { 'Content-Type': type, ...securityHeaders({ publicUrl: config.publicUrl }) }) - res.end(readFileSync(fullPath)) + try { + res.writeHead(200, { + 'Content-Type': type, + ...securityHeaders({ publicUrl: config.publicUrl }), + }) + res.end(readFileSync(fullPath)) + } catch { + return text(res, 'asset not found', 'text/plain; charset=utf-8', 404) + } } function redirect(res, location) { diff --git a/scripts/cockpit-smoke.mjs b/scripts/cockpit-smoke.mjs new file mode 100644 index 0000000..aed270c --- /dev/null +++ b/scripts/cockpit-smoke.mjs @@ -0,0 +1,43 @@ +#!/usr/bin/env node +import { spawn } from 'node:child_process' + +const port = 49175 +const env = { + ...process.env, + PORT: String(port), + COCKPIT_PORT: String(port), + AGENTFLOW_REPOSITORIES: 'smota/agentflow-sdlc', + COCKPIT_WRITE_ACTIONS: 'false', + COCKPIT_DATA_DIR: '.agent-runs/cockpit-smoke', +} +const child = spawn(process.execPath, ['scripts/cockpit-server.mjs'], { + env, + stdio: ['ignore', 'pipe', 'pipe'], +}) +let output = '' +child.stdout.on('data', (chunk) => (output += chunk.toString())) +child.stderr.on('data', (chunk) => (output += chunk.toString())) +try { + await waitFor(() => output.includes('AgentFlow Cockpit listening'), 5000) + const health = await fetch(`http://127.0.0.1:${port}/healthz`) + if (!health.ok) throw new Error(`/healthz failed: ${health.status}`) + const asset = await fetch(`http://127.0.0.1:${port}/assets/cockpit/agentflow-logo.png`) + if (!asset.ok) throw new Error(`asset failed: ${asset.status}`) + process.stdout.write( + `${JSON.stringify({ ok: true, health: health.status, asset: asset.status }, null, 2)}\n`, + ) +} catch (error) { + process.stdout.write(`${JSON.stringify({ ok: false, error: error.message, output }, null, 2)}\n`) + process.exitCode = 1 +} finally { + child.kill() +} + +async function waitFor(predicate, timeoutMs) { + const start = Date.now() + while (Date.now() - start < timeoutMs) { + if (predicate()) return + await new Promise((resolve) => setTimeout(resolve, 50)) + } + throw new Error('cockpit server did not start') +} diff --git a/scripts/sdlc-sandbox-smoke.mjs b/scripts/sdlc-sandbox-smoke.mjs index 037b1bd..c0d1ba8 100644 --- a/scripts/sdlc-sandbox-smoke.mjs +++ b/scripts/sdlc-sandbox-smoke.mjs @@ -8,13 +8,17 @@ const repoRoot = resolve(process.cwd()) const cli = join(repoRoot, 'bin', 'cli.mjs') const tmp = mkdtempSync(join(tmpdir(), 'agentflow-sdlc-smoke-')) function run(args) { - return execFileSync(process.execPath, [cli, ...args, '--target', tmp], { encoding: 'utf8' }) + return execFileSync(process.execPath, [cli, ...args, '--target', tmp], { + encoding: 'utf8', + env: { ...process.env, AGENTFLOW_REPOSITORIES: 'smota/agentflow-sdlc' }, + }) } execFileSync('git', ['init'], { cwd: tmp, stdio: 'ignore' }) run(['init']) run(['sdlc', 'validate', '--json']) run(['sdlc', 'audit', '--json']) run(['sdlc', 'migrate', '--json']) +run(['cockpit', 'doctor', '--json']) run(['skills', 'sync', '--harness', 'all', '--apply']) run(['skills', 'status', '--harness', 'all', '--json']) run(['plugins', 'validate', '--harness', 'all', '--json']) diff --git a/skills/sdlc-audit/SKILL.md b/skills/sdlc-audit/SKILL.md index e0a8a52..d9c911c 100644 --- a/skills/sdlc-audit/SKILL.md +++ b/skills/sdlc-audit/SKILL.md @@ -27,10 +27,12 @@ Use this skill for read-only SDLC compliance evaluation. node scripts/validate-sdlc-config.mjs --json node scripts/validate-sdlc-role-pass.mjs --path --json node scripts/validate-sdlc-skill.mjs --path /SKILL.md --json + agentflow-sdlc cockpit doctor --json ``` 3. Inspect durable evidence only as needed. -4. Return PASS/FAIL/WARN with fix recommendations. -5. Suggest follow-up issues for non-trivial fixes. +4. Treat Cockpit as optional but first-class: audit packaging, docs, and `cockpit doctor`, but do not require it to be running for SDLC compliance. +5. Return PASS/FAIL/WARN with fix recommendations. +6. Suggest follow-up issues for non-trivial fixes. ## Output diff --git a/skills/sdlc-definition/SKILL.md b/skills/sdlc-definition/SKILL.md index 057ba9d..13114a3 100644 --- a/skills/sdlc-definition/SKILL.md +++ b/skills/sdlc-definition/SKILL.md @@ -26,6 +26,7 @@ Use this skill to define and maintain the canonical AgentFlow SDLC model. - Keep product source harness-neutral. Never create canonical files under `.pi`, `.claude`, `.agy`, or `.codex`. - Preserve high-assurance human approval, role-pass provenance, readiness denominator rules, and no-secret/no-transcript evidence rules. - Use AgentFlow concepts: Goal, Role Flow, Readiness, Release, Human approval gate, Follow-up, Source. +- Treat Cockpit as the optional first-class Goal Command Center: product artifact and release gates include it, runtime startup remains opt-in. - Define extensions only when owner, compatibility, migration behavior, and validator are clear. ## Workflow