@geraldmaron/construct 1.0.5 → 1.0.6
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 +8 -4
- package/agents/prompts/cx-accessibility.md +3 -3
- package/agents/prompts/cx-ai-engineer.md +7 -7
- package/agents/prompts/cx-architect.md +6 -6
- package/agents/prompts/cx-business-strategist.md +6 -6
- package/agents/prompts/cx-data-analyst.md +7 -7
- package/agents/prompts/cx-data-engineer.md +3 -3
- package/agents/prompts/cx-debugger.md +6 -6
- package/agents/prompts/cx-designer.md +5 -5
- package/agents/prompts/cx-devil-advocate.md +4 -4
- package/agents/prompts/cx-docs-keeper.md +5 -5
- package/agents/prompts/cx-engineer.md +5 -5
- package/agents/prompts/cx-evaluator.md +2 -2
- package/agents/prompts/cx-explorer.md +8 -8
- package/agents/prompts/cx-legal-compliance.md +2 -2
- package/agents/prompts/cx-operations.md +5 -5
- package/agents/prompts/cx-orchestrator.md +10 -10
- package/agents/prompts/cx-platform-engineer.md +5 -5
- package/agents/prompts/cx-product-manager.md +4 -4
- package/agents/prompts/cx-qa.md +8 -8
- package/agents/prompts/cx-rd-lead.md +9 -9
- package/agents/prompts/cx-release-manager.md +5 -5
- package/agents/prompts/cx-researcher.md +22 -22
- package/agents/prompts/cx-reviewer.md +7 -7
- package/agents/prompts/cx-security.md +10 -10
- package/agents/prompts/cx-sre.md +7 -7
- package/agents/prompts/cx-test-automation.md +3 -3
- package/agents/prompts/cx-trace-reviewer.md +8 -8
- package/agents/prompts/cx-ux-researcher.md +3 -3
- package/bin/construct +235 -21
- package/commands/build/feature.md +4 -4
- package/commands/build/fix.md +8 -8
- package/commands/design/access.md +3 -3
- package/commands/design/flow.md +3 -3
- package/commands/design/ui.md +4 -4
- package/commands/measure/experiment.md +5 -5
- package/commands/measure/metrics.md +3 -3
- package/commands/measure/results.md +4 -4
- package/commands/plan/api.md +3 -3
- package/commands/plan/challenge.md +3 -3
- package/commands/plan/decide.md +3 -3
- package/commands/plan/feature.md +7 -7
- package/commands/plan/requirements.md +3 -3
- package/commands/remember/context.md +5 -5
- package/commands/remember/handoff.md +3 -3
- package/commands/remember/runbook.md +3 -3
- package/commands/review/code.md +8 -8
- package/commands/review/quality.md +4 -4
- package/commands/review/security.md +3 -3
- package/commands/ship/ready.md +3 -3
- package/commands/ship/release.md +3 -3
- package/commands/ship/status.md +4 -4
- package/commands/understand/docs.md +3 -3
- package/commands/understand/this.md +4 -4
- package/commands/understand/why.md +8 -8
- package/commands/work/clean.md +14 -14
- package/commands/work/drive.md +10 -10
- package/commands/work/optimize-prompts.md +9 -9
- package/commands/work/parallel-review.md +8 -8
- package/db/schema/006_graph.sql +24 -0
- package/examples/provider-plugin/README.md +7 -7
- package/examples/seed-observations/README.md +6 -6
- package/examples/seed-observations/anti-patterns.md +14 -14
- package/examples/seed-observations/decisions.md +4 -4
- package/examples/seed-observations/patterns.md +14 -14
- package/lib/auto-docs.mjs +8 -3
- package/lib/cli-commands.mjs +2 -2
- package/lib/flavors/loader.mjs +1 -1
- package/lib/knowledge/graph.mjs +213 -0
- package/lib/mcp/server.mjs +187 -1
- package/lib/mcp/tools/profile.mjs +270 -0
- package/package.json +1 -1
- package/platforms/claude/CLAUDE.md +6 -6
- package/rules/common/agents.md +2 -2
- package/rules/common/beads-hygiene.md +11 -11
- package/rules/common/code-review.md +1 -1
- package/rules/common/coding-style.md +1 -1
- package/rules/common/comments.md +8 -8
- package/rules/common/commit-approval.md +4 -4
- package/rules/common/cx-agent-routing.md +2 -2
- package/rules/common/cx-skill-routing.md +2 -2
- package/rules/common/development-workflow.md +1 -1
- package/rules/common/doc-ownership.md +2 -2
- package/rules/common/efficiency.md +3 -3
- package/rules/common/framing.md +1 -1
- package/rules/common/git-workflow.md +1 -1
- package/rules/common/patterns.md +1 -1
- package/rules/common/performance.md +1 -1
- package/rules/common/release-gates.md +7 -7
- package/rules/common/research.md +4 -4
- package/rules/common/security.md +1 -1
- package/rules/common/skill-composition.md +8 -8
- package/rules/common/testing.md +1 -1
- package/rules/golang/coding-style.md +2 -2
- package/rules/golang/hooks.md +1 -1
- package/rules/golang/patterns.md +1 -1
- package/rules/golang/security.md +1 -1
- package/rules/golang/testing.md +1 -1
- package/rules/python/coding-style.md +1 -1
- package/rules/python/hooks.md +1 -1
- package/rules/python/patterns.md +1 -1
- package/rules/python/security.md +1 -1
- package/rules/python/testing.md +1 -1
- package/rules/swift/coding-style.md +3 -3
- package/rules/swift/hooks.md +2 -2
- package/rules/swift/patterns.md +2 -2
- package/rules/swift/security.md +4 -4
- package/rules/swift/testing.md +2 -2
- package/rules/typescript/coding-style.md +1 -1
- package/rules/typescript/hooks.md +1 -1
- package/rules/typescript/patterns.md +1 -1
- package/rules/typescript/security.md +1 -1
- package/rules/typescript/testing.md +1 -1
- package/rules/web/coding-style.md +1 -1
- package/rules/web/design-quality.md +1 -1
- package/rules/web/hooks.md +1 -1
- package/rules/web/patterns.md +1 -1
- package/rules/web/performance.md +1 -1
- package/rules/web/security.md +1 -1
- package/rules/web/testing.md +1 -1
- package/skills/ai/agent-dev.md +1 -1
- package/skills/ai/llm-security.md +1 -1
- package/skills/ai/ml-ops.md +6 -6
- package/skills/ai/orchestration-workflow.md +1 -1
- package/skills/ai/prompt-and-eval.md +1 -1
- package/skills/ai/prompt-optimizer.md +13 -13
- package/skills/ai/rag-system.md +1 -1
- package/skills/architecture/api-design.md +1 -1
- package/skills/architecture/caching.md +1 -1
- package/skills/architecture/cloud-native.md +1 -1
- package/skills/architecture/message-queue.md +1 -1
- package/skills/architecture/security-arch.md +1 -1
- package/skills/compliance/ai-disclosure.md +1 -1
- package/skills/compliance/data-privacy.md +1 -1
- package/skills/compliance/license-audit.md +2 -2
- package/skills/compliance/regulatory-review.md +1 -1
- package/skills/development/cpp.md +1 -1
- package/skills/development/go.md +1 -1
- package/skills/development/java.md +1 -1
- package/skills/development/kotlin.md +9 -9
- package/skills/development/mobile-crossplatform.md +13 -13
- package/skills/development/python.md +1 -1
- package/skills/development/rust.md +1 -1
- package/skills/development/shell.md +1 -1
- package/skills/development/swift.md +6 -6
- package/skills/development/typescript.md +1 -1
- package/skills/devops/ci-cd.md +5 -5
- package/skills/devops/containerization.md +9 -9
- package/skills/devops/cost-optimization.md +1 -1
- package/skills/devops/data-engineering.md +2 -2
- package/skills/devops/database.md +1 -1
- package/skills/devops/dependency-management.md +3 -3
- package/skills/devops/devsecops.md +1 -1
- package/skills/devops/git-workflow.md +1 -1
- package/skills/devops/incident-response.md +18 -18
- package/skills/devops/monorepo.md +5 -5
- package/skills/devops/observability.md +1 -1
- package/skills/devops/performance.md +1 -1
- package/skills/devops/testing.md +1 -1
- package/skills/docs/adr-workflow.md +2 -2
- package/skills/docs/backlog-proposal-workflow.md +1 -1
- package/skills/docs/customer-profile-workflow.md +1 -1
- package/skills/docs/document-ingest-workflow.md +1 -1
- package/skills/docs/evidence-ingest-workflow.md +1 -1
- package/skills/docs/init-docs.md +15 -15
- package/skills/docs/init-project.md +1 -1
- package/skills/docs/prd-workflow.md +3 -3
- package/skills/docs/prfaq-workflow.md +1 -1
- package/skills/docs/product-intelligence-review.md +1 -1
- package/skills/docs/product-intelligence-workflow.md +1 -1
- package/skills/docs/product-signal-workflow.md +9 -9
- package/skills/docs/research-workflow.md +10 -10
- package/skills/docs/runbook-workflow.md +2 -2
- package/skills/docs/strategy-workflow.md +3 -3
- package/skills/exploration/repo-map.md +11 -11
- package/skills/frameworks/django.md +15 -15
- package/skills/frameworks/nextjs.md +16 -16
- package/skills/frameworks/react.md +12 -12
- package/skills/frameworks/spring-boot.md +12 -12
- package/skills/frontend-design/accessibility.md +6 -6
- package/skills/frontend-design/component-patterns.md +1 -1
- package/skills/frontend-design/engineering.md +1 -1
- package/skills/frontend-design/state-management.md +1 -1
- package/skills/frontend-design/ui-aesthetics.md +1 -1
- package/skills/frontend-design/ux-principles.md +1 -1
- package/skills/operating/orchestration-reference.md +27 -27
- package/skills/quality-gates/review-work.md +3 -3
- package/skills/quality-gates/verify-change.md +1 -1
- package/skills/quality-gates/verify-module.md +1 -1
- package/skills/quality-gates/verify-quality.md +1 -1
- package/skills/quality-gates/verify-security.md +1 -1
- package/skills/routing.md +14 -14
- package/skills/security/blue-team.md +1 -1
- package/skills/security/code-audit.md +1 -1
- package/skills/security/pentest.md +1 -1
- package/skills/security/red-team.md +1 -1
- package/skills/security/threat-intel.md +1 -1
- package/skills/security/vuln-research.md +1 -1
- package/skills/utility/clean-code.md +2 -2
- package/templates/docs/changelog-entry.md +1 -1
- package/templates/docs/construct_guide.md +13 -13
- package/templates/docs/meta-prd.md +16 -16
- package/templates/docs/one-pager.md +1 -1
- package/templates/docs/prd-business.md +1 -1
- package/templates/docs/prd-platform.md +1 -1
- package/templates/docs/prd.md +17 -17
- package/templates/docs/research-brief.md +8 -8
- package/templates/docs/rfc.md +1 -1
- package/templates/docs/strategy.md +1 -1
package/bin/construct
CHANGED
|
@@ -3994,18 +3994,85 @@ const handlers = new Map([
|
|
|
3994
3994
|
}
|
|
3995
3995
|
if (sub === 'set') {
|
|
3996
3996
|
const id = args[1];
|
|
3997
|
-
if (!id) {
|
|
3997
|
+
if (!id) {
|
|
3998
|
+
errorln('Usage: construct profile set <id> [--yes] [--dry-run]');
|
|
3999
|
+
process.exit(1);
|
|
4000
|
+
}
|
|
3998
4001
|
const target = loadProfile(id);
|
|
3999
4002
|
if (!target) {
|
|
4000
4003
|
errorln(`Unknown profile: ${id}. Available: ${listProfiles().join(', ')}`);
|
|
4001
4004
|
process.exit(1);
|
|
4002
4005
|
}
|
|
4006
|
+
const skipConfirm = args.includes('--yes') || args.includes('-y') || args.includes('--non-interactive');
|
|
4007
|
+
const dryRun = args.includes('--dry-run');
|
|
4008
|
+
const isTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
4009
|
+
|
|
4003
4010
|
const { findProjectConfigPath, loadProjectConfig, writeProjectConfig, PROJECT_CONFIG_FILENAME } = await import('../lib/config/project-config.mjs');
|
|
4004
|
-
const fsMod = await import('node:fs');
|
|
4005
4011
|
const pathMod = await import('node:path');
|
|
4006
4012
|
const found = findProjectConfigPath(process.cwd());
|
|
4007
4013
|
const cfgPath = found || pathMod.join(process.cwd(), PROJECT_CONFIG_FILENAME);
|
|
4008
|
-
|
|
4014
|
+
// loadProjectConfig returns a wrapper { path, raw, config, source, errors };
|
|
4015
|
+
// operate on the raw user-authored object so the write call sees the
|
|
4016
|
+
// version field that validateProjectConfig requires.
|
|
4017
|
+
const loaded = found ? loadProjectConfig(process.cwd()) : null;
|
|
4018
|
+
const cfg = loaded?.raw ? structuredClone(loaded.raw) : { version: 1 };
|
|
4019
|
+
if (!cfg.version) cfg.version = 1;
|
|
4020
|
+
|
|
4021
|
+
const currentId = cfg.profile || 'rnd';
|
|
4022
|
+
if (currentId === id) {
|
|
4023
|
+
println(`Profile already set to ${id} (${target.displayName}). Nothing to do.`);
|
|
4024
|
+
return;
|
|
4025
|
+
}
|
|
4026
|
+
const current = loadProfile(currentId) || { id: currentId, displayName: currentId, roles: [], intake: { types: [], stages: [] }, departments: [] };
|
|
4027
|
+
|
|
4028
|
+
// Render a structural diff so the operator sees what loop they are switching into.
|
|
4029
|
+
const setDiff = (label, before, after) => {
|
|
4030
|
+
const b = new Set(before || []);
|
|
4031
|
+
const a = new Set(after || []);
|
|
4032
|
+
const added = [...a].filter((x) => !b.has(x));
|
|
4033
|
+
const removed = [...b].filter((x) => !a.has(x));
|
|
4034
|
+
const unchanged = [...a].filter((x) => b.has(x));
|
|
4035
|
+
println(` ${label}:`);
|
|
4036
|
+
if (added.length) println(` + ${added.join(', ')}`);
|
|
4037
|
+
if (removed.length) println(` - ${removed.join(', ')}`);
|
|
4038
|
+
if (!added.length && !removed.length) println(` (no change, ${unchanged.length} entr${unchanged.length === 1 ? 'y' : 'ies'})`);
|
|
4039
|
+
};
|
|
4040
|
+
|
|
4041
|
+
println('');
|
|
4042
|
+
println(`About to switch active profile:`);
|
|
4043
|
+
println(` from: ${currentId} (${current.displayName})`);
|
|
4044
|
+
println(` to: ${id} (${target.displayName})`);
|
|
4045
|
+
println('');
|
|
4046
|
+
println(`Structural diff:`);
|
|
4047
|
+
setDiff('roles', current.roles, target.roles);
|
|
4048
|
+
setDiff('intake.types', current.intake?.types, target.intake?.types);
|
|
4049
|
+
setDiff('intake.stages', current.intake?.stages, target.intake?.stages);
|
|
4050
|
+
const cDept = (current.departments || []).map((d) => d.id);
|
|
4051
|
+
const tDept = (target.departments || []).map((d) => d.id);
|
|
4052
|
+
setDiff('departments', cDept, tDept);
|
|
4053
|
+
println('');
|
|
4054
|
+
println(`Files that will change:`);
|
|
4055
|
+
println(` ${pathMod.relative(process.cwd(), cfgPath)} (profile field: ${currentId} -> ${id})`);
|
|
4056
|
+
println('');
|
|
4057
|
+
println(`The change only writes the profile field. No specialists are added or removed.`);
|
|
4058
|
+
println(`Sync runs against the new profile on next \`construct sync\`.`);
|
|
4059
|
+
println('');
|
|
4060
|
+
|
|
4061
|
+
if (dryRun) {
|
|
4062
|
+
println(`[dry-run] No files were written.`);
|
|
4063
|
+
return;
|
|
4064
|
+
}
|
|
4065
|
+
if (!skipConfirm && isTTY) {
|
|
4066
|
+
const readline = await import('node:readline');
|
|
4067
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
4068
|
+
const answer = await new Promise((res) => rl.question(`Switch profile to ${id}? (Y/n) `, (a) => res(a.trim().toLowerCase())));
|
|
4069
|
+
rl.close();
|
|
4070
|
+
if (answer && answer !== 'y' && answer !== 'yes') {
|
|
4071
|
+
println('Aborted. No config was changed.');
|
|
4072
|
+
return;
|
|
4073
|
+
}
|
|
4074
|
+
}
|
|
4075
|
+
|
|
4009
4076
|
cfg.profile = id;
|
|
4010
4077
|
writeProjectConfig(cfgPath, cfg, { validate: true });
|
|
4011
4078
|
process.stdout.write(`✓ profile set to ${id} (${target.displayName})\n`);
|
|
@@ -4014,36 +4081,111 @@ const handlers = new Map([
|
|
|
4014
4081
|
if (sub === 'create') {
|
|
4015
4082
|
const id = args[1];
|
|
4016
4083
|
if (!id) {
|
|
4017
|
-
errorln('Usage: construct profile create <id> [--display="..."] [--role=<id>...] [--department=<id>:<displayName>...]');
|
|
4084
|
+
errorln('Usage: construct profile create <id> [--display="..."] [--role=<id>...] [--department=<id>:<displayName>...] [--yes]');
|
|
4085
|
+
errorln(' Run with no flags for interactive mode; pass --yes to skip the confirmation prompt.');
|
|
4018
4086
|
process.exit(1);
|
|
4019
4087
|
}
|
|
4088
|
+
if (!/^[a-z][a-z0-9-]{1,30}$/.test(id)) {
|
|
4089
|
+
errorln(`Invalid id "${id}". Must match ^[a-z][a-z0-9-]{1,30}$.`);
|
|
4090
|
+
process.exit(1);
|
|
4091
|
+
}
|
|
4092
|
+
|
|
4020
4093
|
const displayArg = args.find((a) => a.startsWith('--display='));
|
|
4021
|
-
const
|
|
4022
|
-
const
|
|
4094
|
+
const skipConfirm = args.includes('--yes') || args.includes('-y') || args.includes('--non-interactive');
|
|
4095
|
+
const dryRun = args.includes('--dry-run');
|
|
4096
|
+
const isTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
4097
|
+
|
|
4098
|
+
let displayName = displayArg ? displayArg.split('=')[1] : null;
|
|
4099
|
+
let seedRoles = args
|
|
4023
4100
|
.filter((a) => a.startsWith('--role='))
|
|
4024
4101
|
.map((a) => a.slice('--role='.length))
|
|
4025
4102
|
.filter(Boolean);
|
|
4026
|
-
|
|
4103
|
+
let seedDepartments = args
|
|
4027
4104
|
.filter((a) => a.startsWith('--department='))
|
|
4028
4105
|
.map((a) => a.slice('--department='.length))
|
|
4029
4106
|
.map((spec) => {
|
|
4030
4107
|
const [deptId, deptDisplay] = spec.split(':');
|
|
4031
4108
|
return { id: deptId, displayName: deptDisplay || deptId };
|
|
4032
4109
|
});
|
|
4110
|
+
|
|
4111
|
+
// Interactive gather. Only prompt when stdin is a real terminal and the
|
|
4112
|
+
// operator did not pass enough flags to scaffold without input. A
|
|
4113
|
+
// non-TTY invocation with no flags falls through to an empty scaffold
|
|
4114
|
+
// so scripts and CI can still create drafts non-interactively.
|
|
4115
|
+
const needsInteractive = isTTY && !skipConfirm && (!displayName || (seedRoles.length === 0 && seedDepartments.length === 0));
|
|
4116
|
+
if (needsInteractive) {
|
|
4117
|
+
const readline = await import('node:readline');
|
|
4118
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
4119
|
+
const ask = (q, def = '') => new Promise((res) => rl.question(`${q}${def ? ` [${def}]` : ''} `, (a) => res(a.trim() || def)));
|
|
4120
|
+
|
|
4121
|
+
println('');
|
|
4122
|
+
println(`Scaffolding a new profile draft. Three questions, then a preview.`);
|
|
4123
|
+
println(`Background: docs/concepts/persona-research.md and docs/concepts/profile-lifecycle.md`);
|
|
4124
|
+
println('');
|
|
4125
|
+
if (!displayName) displayName = await ask('Display name?', id);
|
|
4126
|
+
if (seedDepartments.length === 0) {
|
|
4127
|
+
const dInput = await ask('Departments (id:Name, id:Name, ...)?', '');
|
|
4128
|
+
if (dInput) seedDepartments = dInput.split(',').map((s) => s.trim()).filter(Boolean).map((spec) => {
|
|
4129
|
+
const [dId, dName] = spec.split(':').map((x) => x.trim());
|
|
4130
|
+
return { id: dId, displayName: dName || dId };
|
|
4131
|
+
});
|
|
4132
|
+
}
|
|
4133
|
+
if (seedRoles.length === 0) {
|
|
4134
|
+
const rInput = await ask('Roles (role-id, role-id, ...)?', '');
|
|
4135
|
+
if (rInput) seedRoles = rInput.split(',').map((s) => s.trim()).filter(Boolean);
|
|
4136
|
+
}
|
|
4137
|
+
rl.close();
|
|
4138
|
+
}
|
|
4139
|
+
if (!displayName) displayName = id;
|
|
4140
|
+
|
|
4141
|
+
const pathMod = await import('node:path');
|
|
4142
|
+
const draftRoot = pathMod.join(process.cwd(), '.cx', 'profiles', `draft-${id}`);
|
|
4143
|
+
|
|
4144
|
+
println('');
|
|
4145
|
+
println(`About to scaffold a draft profile:`);
|
|
4146
|
+
println(` id: ${id}`);
|
|
4147
|
+
println(` displayName: ${displayName}`);
|
|
4148
|
+
println(` departments: ${seedDepartments.length}${seedDepartments.length ? ` (${seedDepartments.map((d) => d.id).join(', ')})` : ''}`);
|
|
4149
|
+
println(` roles: ${seedRoles.length}${seedRoles.length ? ` (${seedRoles.join(', ')})` : ''}`);
|
|
4150
|
+
println('');
|
|
4151
|
+
println(`Files that will be written under ${pathMod.relative(process.cwd(), draftRoot)}/:`);
|
|
4152
|
+
println(` profile.json structural manifest`);
|
|
4153
|
+
println(` requirements.md research brief naming each cx-* specialist`);
|
|
4154
|
+
for (const r of seedRoles) println(` personas/${r}.md`.padEnd(40) + ` persona artifact (filled during discover)`);
|
|
4155
|
+
for (const d of seedDepartments) println(` departments/${d.id}.md`.padEnd(40) + ` department charter (filled during frame)`);
|
|
4156
|
+
println('');
|
|
4157
|
+
println(`Nothing else is touched. No config is changed, no active profile is switched.`);
|
|
4158
|
+
println(`To activate this profile after promotion: construct profile set ${id}`);
|
|
4159
|
+
println('');
|
|
4160
|
+
|
|
4161
|
+
if (dryRun) {
|
|
4162
|
+
println(`[dry-run] No files were written.`);
|
|
4163
|
+
return;
|
|
4164
|
+
}
|
|
4165
|
+
if (!skipConfirm && isTTY) {
|
|
4166
|
+
const readline = await import('node:readline');
|
|
4167
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
4168
|
+
const answer = await new Promise((res) => rl.question('Create draft? (Y/n) ', (a) => res(a.trim().toLowerCase())));
|
|
4169
|
+
rl.close();
|
|
4170
|
+
if (answer && answer !== 'y' && answer !== 'yes') {
|
|
4171
|
+
println('Aborted. Nothing was written.');
|
|
4172
|
+
return;
|
|
4173
|
+
}
|
|
4174
|
+
}
|
|
4175
|
+
|
|
4033
4176
|
const { createDraftProfile } = await import('../lib/profiles/lifecycle.mjs');
|
|
4034
4177
|
try {
|
|
4035
4178
|
const result = createDraftProfile({ cwd: process.cwd(), id, displayName, seedRoles, seedDepartments });
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
process.stdout.write(` 4. Validate: dispatch cx-evaluator to run persona-eval and classifier-eval against representative signals.\n`);
|
|
4179
|
+
println('');
|
|
4180
|
+
println(`✓ draft created at ${pathMod.relative(process.cwd(), result.dir)}`);
|
|
4181
|
+
println('');
|
|
4182
|
+
println(`Next steps (in order, per docs/concepts/profile-lifecycle.md):`);
|
|
4183
|
+
println(` 1. Discover (cx-ux-researcher): fill personas/<role>.md from interviews + primary sources.`);
|
|
4184
|
+
println(` 2. Frame (cx-product-manager): fill departments/<dept>.md charters and intake taxonomy.`);
|
|
4185
|
+
println(` 3. Architect (cx-architect): reconcile role reuse vs new; populate departments[] in profile.json.`);
|
|
4186
|
+
println(` 4. Validate (cx-evaluator): run persona-eval and classifier-eval against representative signals.`);
|
|
4187
|
+
println('');
|
|
4188
|
+
println(`Inspect the brief: open ${pathMod.relative(process.cwd(), result.briefPath)}`);
|
|
4047
4189
|
return;
|
|
4048
4190
|
} catch (err) {
|
|
4049
4191
|
errorln(err.message);
|
|
@@ -4063,12 +4205,84 @@ const handlers = new Map([
|
|
|
4063
4205
|
if (sub === 'archive') {
|
|
4064
4206
|
const id = args[1];
|
|
4065
4207
|
const reasonArg = args.find((a) => a.startsWith('--reason='));
|
|
4066
|
-
|
|
4067
|
-
if (!id) {
|
|
4208
|
+
let reason = reasonArg ? reasonArg.split('=')[1] : '';
|
|
4209
|
+
if (!id) {
|
|
4210
|
+
errorln('Usage: construct profile archive <id> --reason="..." [--yes] [--dry-run]');
|
|
4211
|
+
process.exit(1);
|
|
4212
|
+
}
|
|
4213
|
+
const skipConfirm = args.includes('--yes') || args.includes('-y') || args.includes('--non-interactive');
|
|
4214
|
+
const dryRun = args.includes('--dry-run');
|
|
4215
|
+
const isTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
4216
|
+
|
|
4217
|
+
const pathMod = await import('node:path');
|
|
4218
|
+
const fsMod = await import('node:fs');
|
|
4219
|
+
const target = loadProfile(id);
|
|
4220
|
+
if (!target) {
|
|
4221
|
+
errorln(`Unknown profile: ${id}. Curated catalog: ${listProfiles().join(', ')}`);
|
|
4222
|
+
process.exit(1);
|
|
4223
|
+
}
|
|
4224
|
+
const fileURL = await import('node:url');
|
|
4225
|
+
const moduleDir = pathMod.dirname(fileURL.fileURLToPath(import.meta.url));
|
|
4226
|
+
const repoRoot = pathMod.resolve(moduleDir, '..');
|
|
4227
|
+
const srcProfile = pathMod.join(repoRoot, 'profiles', `${id}.json`);
|
|
4228
|
+
const tableRel = typeof target?.intake?.classificationTable === 'string' ? target.intake.classificationTable : null;
|
|
4229
|
+
const srcTable = tableRel ? pathMod.join(repoRoot, tableRel) : null;
|
|
4230
|
+
const dstDir = pathMod.join(repoRoot, 'archive', 'profiles', id);
|
|
4231
|
+
|
|
4232
|
+
// Gather reason interactively if missing. The lifecycle module already
|
|
4233
|
+
// enforces a >= 8 char reason, but the operator should see why before
|
|
4234
|
+
// the call fails.
|
|
4235
|
+
if (!reason && isTTY && !skipConfirm) {
|
|
4236
|
+
const readline = await import('node:readline');
|
|
4237
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
4238
|
+
reason = await new Promise((res) => rl.question('Archive reason (>= 8 chars): ', (a) => res(a.trim())));
|
|
4239
|
+
rl.close();
|
|
4240
|
+
}
|
|
4241
|
+
if (!reason || reason.trim().length < 8) {
|
|
4242
|
+
errorln('A substantive --reason (>= 8 chars) is required. Archiving is permanent in repo history; the reason becomes the archive note.');
|
|
4243
|
+
process.exit(1);
|
|
4244
|
+
}
|
|
4245
|
+
|
|
4246
|
+
println('');
|
|
4247
|
+
println(`About to archive curated profile:`);
|
|
4248
|
+
println(` id: ${id}`);
|
|
4249
|
+
println(` displayName: ${target.displayName || id}`);
|
|
4250
|
+
println(` reason: ${reason}`);
|
|
4251
|
+
println('');
|
|
4252
|
+
println(`Files that will move:`);
|
|
4253
|
+
println(` ${pathMod.relative(process.cwd(), srcProfile)}`);
|
|
4254
|
+
println(` -> ${pathMod.relative(process.cwd(), pathMod.join(dstDir, `${id}.json`))}`);
|
|
4255
|
+
if (srcTable && fsMod.existsSync(srcTable)) {
|
|
4256
|
+
println(` ${pathMod.relative(process.cwd(), srcTable)}`);
|
|
4257
|
+
println(` -> ${pathMod.relative(process.cwd(), pathMod.join(dstDir, pathMod.basename(srcTable)))}`);
|
|
4258
|
+
}
|
|
4259
|
+
println(` ${pathMod.relative(process.cwd(), pathMod.join(dstDir, 'archive-note.md'))} (new)`);
|
|
4260
|
+
println('');
|
|
4261
|
+
println(`What stays:`);
|
|
4262
|
+
println(` Observations under .cx/observations/ are not touched.`);
|
|
4263
|
+
println(` Outcomes under .cx/outcomes/ are not touched.`);
|
|
4264
|
+
println(` Any project still configured with profile=${id} will fall back to rnd on next load.`);
|
|
4265
|
+
println('');
|
|
4266
|
+
|
|
4267
|
+
if (dryRun) {
|
|
4268
|
+
println(`[dry-run] No files were moved.`);
|
|
4269
|
+
return;
|
|
4270
|
+
}
|
|
4271
|
+
if (!skipConfirm && isTTY) {
|
|
4272
|
+
const readline = await import('node:readline');
|
|
4273
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
4274
|
+
const answer = await new Promise((res) => rl.question(`Archive ${id}? (y/N) `, (a) => res(a.trim().toLowerCase())));
|
|
4275
|
+
rl.close();
|
|
4276
|
+
if (answer !== 'y' && answer !== 'yes') {
|
|
4277
|
+
println('Aborted. Nothing was archived.');
|
|
4278
|
+
return;
|
|
4279
|
+
}
|
|
4280
|
+
}
|
|
4281
|
+
|
|
4068
4282
|
const { archiveProfile } = await import('../lib/profiles/lifecycle.mjs');
|
|
4069
4283
|
try {
|
|
4070
4284
|
const { archived } = archiveProfile({ id, reason });
|
|
4071
|
-
process.stdout.write(`✓ archived ${id} to ${archived}\n`);
|
|
4285
|
+
process.stdout.write(`✓ archived ${id} to ${pathMod.relative(process.cwd(), archived)}\n`);
|
|
4072
4286
|
return;
|
|
4073
4287
|
} catch (err) {
|
|
4074
4288
|
errorln(err.message);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
commands/build/feature.md
|
|
2
|
+
commands/build/feature.md (Build a feature) implement it end to end, tested and ready to ship
|
|
3
3
|
|
|
4
|
-
Build a feature
|
|
4
|
+
Build a feature: implement it end to end, tested and ready to ship
|
|
5
5
|
-->
|
|
6
6
|
---
|
|
7
|
-
description: Build a feature
|
|
7
|
+
description: Build a feature: implement it end to end, tested and ready to ship
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
You are Construct. Build the following: $ARGUMENTS
|
|
@@ -18,4 +18,4 @@ produces no output or tool activity within two minutes, surface it to the user w
|
|
|
18
18
|
agent description and elapsed time rather than waiting silently. Do not re-dispatch until
|
|
19
19
|
the user confirms the prior invocation is not still running.
|
|
20
20
|
|
|
21
|
-
Verification protocol is owned by `cx-engineer
|
|
21
|
+
Verification protocol is owned by `cx-engineer`: apply its checklist before declaring done.
|
package/commands/build/fix.md
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
commands/build/fix.md
|
|
2
|
+
commands/build/fix.md (Fix something broken) reproduce, find the root cause, apply the smallest safe change
|
|
3
3
|
|
|
4
|
-
Fix something broken
|
|
4
|
+
Fix something broken: reproduce, find the root cause, apply the smallest safe change
|
|
5
5
|
-->
|
|
6
6
|
---
|
|
7
|
-
description: Fix something broken
|
|
7
|
+
description: Fix something broken: reproduce, find the root cause, apply the smallest safe change
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
You are Construct.
|
|
11
11
|
|
|
12
12
|
Debugging protocol for: $ARGUMENTS
|
|
13
13
|
|
|
14
|
-
1. Reproduce
|
|
15
|
-
2. Isolate
|
|
16
|
-
3. Trace
|
|
17
|
-
4. Root cause
|
|
18
|
-
5. Fix
|
|
14
|
+
1. Reproduce: confirm the failure is real and consistent
|
|
15
|
+
2. Isolate: narrow to the smallest failing case
|
|
16
|
+
3. Trace: follow execution to where the invariant breaks
|
|
17
|
+
4. Root cause: the one upstream cause that prevents the failure when fixed
|
|
18
|
+
5. Fix: the smallest safe change that restores the invariant
|
|
19
19
|
|
|
20
20
|
Do not propose a fix until root cause is confirmed. After 3 failed attempts, stop and escalate.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
commands/design/access.md
|
|
2
|
+
commands/design/access.md (Accessibility audit) WCAG 2.1 AA, keyboard, screen readers, contrast, motion
|
|
3
3
|
|
|
4
|
-
Accessibility audit
|
|
4
|
+
Accessibility audit: WCAG 2.1 AA, keyboard, screen readers, contrast, motion
|
|
5
5
|
-->
|
|
6
6
|
---
|
|
7
|
-
description: Accessibility audit
|
|
7
|
+
description: Accessibility audit: WCAG 2.1 AA, keyboard, screen readers, contrast, motion
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
You are Construct. Audit: $ARGUMENTS
|
package/commands/design/flow.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
commands/design/flow.md
|
|
2
|
+
commands/design/flow.md (Map the user flow) entry to success, friction points, jobs-to-be-done
|
|
3
3
|
|
|
4
|
-
Map the user flow
|
|
4
|
+
Map the user flow: entry to success, friction points, jobs-to-be-done
|
|
5
5
|
-->
|
|
6
6
|
---
|
|
7
|
-
description: Map the user flow
|
|
7
|
+
description: Map the user flow: entry to success, friction points, jobs-to-be-done
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
You are Construct. Map the user flow for: $ARGUMENTS
|
package/commands/design/ui.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
commands/design/ui.md
|
|
2
|
+
commands/design/ui.md (Design or review UI) visual hierarchy, states, interaction model, accessibility baseline
|
|
3
3
|
|
|
4
|
-
Design or review UI
|
|
4
|
+
Design or review UI: visual hierarchy, states, interaction model, accessibility baseline
|
|
5
5
|
-->
|
|
6
6
|
---
|
|
7
|
-
description: Design or review UI
|
|
7
|
+
description: Design or review UI: visual hierarchy, states, interaction model, accessibility baseline
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
You are Construct. Design or review the UI for: $ARGUMENTS
|
|
11
11
|
|
|
12
12
|
Every meaningful UI surface needs:
|
|
13
|
-
- Clear hierarchy through scale contrast
|
|
13
|
+
- Clear hierarchy through scale contrast: not uniform emphasis
|
|
14
14
|
- Every component state defined: empty, loading, error, success, edge cases
|
|
15
15
|
- Hover, focus, and active states that feel designed
|
|
16
16
|
- WCAG AA baseline: keyboard-navigable, 4.5:1 contrast, visible focus, ARIA labels
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
commands/measure/experiment.md
|
|
2
|
+
commands/measure/experiment.md (Design an experiment) hypothesis, test, evidence threshold, go/no-go decision
|
|
3
3
|
|
|
4
|
-
Design an experiment
|
|
4
|
+
Design an experiment: hypothesis, test, evidence threshold, go/no-go decision
|
|
5
5
|
-->
|
|
6
6
|
---
|
|
7
|
-
description: Design an experiment
|
|
7
|
+
description: Design an experiment: hypothesis, test, evidence threshold, go/no-go decision
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
You are Construct. Design an experiment for: $ARGUMENTS
|
|
@@ -12,7 +12,7 @@ You are Construct. Design an experiment for: $ARGUMENTS
|
|
|
12
12
|
Produce:
|
|
13
13
|
- HYPOTHESIS: "We believe [X] will result in [Y] because [Z]."
|
|
14
14
|
- KEY UNKNOWNS: a small set of questions (typically 3-7) whose answers most change the decision
|
|
15
|
-
- EXPERIMENT: cheapest useful test per unknown
|
|
15
|
+
- EXPERIMENT: cheapest useful test per unknown: inputs, method, output artifact
|
|
16
16
|
- EVIDENCE THRESHOLD: what result confirms or disconfirms? Be specific.
|
|
17
|
-
- RECOMMENDATION: explore | prototype | build | kill
|
|
17
|
+
- RECOMMENDATION: explore | prototype | build | kill: with rationale
|
|
18
18
|
- WHAT NOT TO LOCK IN YET: decisions that must not harden before evidence arrives
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
commands/measure/metrics.md
|
|
2
|
+
commands/measure/metrics.md (Define metrics) what to measure, baselines, success thresholds, instrumentation needed
|
|
3
3
|
|
|
4
|
-
Define metrics
|
|
4
|
+
Define metrics: what to measure, baselines, success thresholds, instrumentation needed
|
|
5
5
|
-->
|
|
6
6
|
---
|
|
7
|
-
description: Define metrics
|
|
7
|
+
description: Define metrics: what to measure, baselines, success thresholds, instrumentation needed
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
You are Construct. Define metrics for: $ARGUMENTS
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
commands/measure/results.md
|
|
2
|
+
commands/measure/results.md (Analyze results) interpret data, separate signal from noise, produce a recommendation
|
|
3
3
|
|
|
4
|
-
Analyze results
|
|
4
|
+
Analyze results: interpret data, separate signal from noise, produce a recommendation
|
|
5
5
|
-->
|
|
6
6
|
---
|
|
7
|
-
description: Analyze results
|
|
7
|
+
description: Analyze results: interpret data, separate signal from noise, produce a recommendation
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
You are Construct. Analyze: $ARGUMENTS
|
|
11
11
|
|
|
12
12
|
For each finding:
|
|
13
13
|
- FINDING: what the data shows (with specific numbers)
|
|
14
|
-
- CONFIDENCE: high / medium / low
|
|
14
|
+
- CONFIDENCE: high / medium / low: based on sample size and data quality
|
|
15
15
|
- INFERENCE: what this means for the decision (clearly labeled as interpretation)
|
|
16
16
|
- GAPS: what additional data would increase confidence
|
|
17
17
|
|
package/commands/plan/api.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
commands/plan/api.md
|
|
2
|
+
commands/plan/api.md (Design an API) contracts, endpoints, error model, data schema
|
|
3
3
|
|
|
4
|
-
Design an API
|
|
4
|
+
Design an API: contracts, endpoints, error model, data schema
|
|
5
5
|
-->
|
|
6
6
|
---
|
|
7
|
-
description: Design an API
|
|
7
|
+
description: Design an API: contracts, endpoints, error model, data schema
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
You are Construct. Design the API for: $ARGUMENTS
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
commands/plan/challenge.md
|
|
2
|
+
commands/plan/challenge.md (Challenge a plan) stress-test assumptions, surface failure modes and risks
|
|
3
3
|
|
|
4
|
-
Challenge a plan
|
|
4
|
+
Challenge a plan: stress-test assumptions, surface failure modes and risks
|
|
5
5
|
-->
|
|
6
6
|
---
|
|
7
|
-
description: Challenge a plan
|
|
7
|
+
description: Challenge a plan: stress-test assumptions, surface failure modes and risks
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
You are Construct. Challenge the following: $ARGUMENTS
|
package/commands/plan/decide.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
commands/plan/decide.md
|
|
2
|
+
commands/plan/decide.md (Record a decision) context, options considered, consequences, what it locks in
|
|
3
3
|
|
|
4
|
-
Record a decision
|
|
4
|
+
Record a decision: context, options considered, consequences, what it locks in
|
|
5
5
|
-->
|
|
6
6
|
---
|
|
7
|
-
description: Record a decision
|
|
7
|
+
description: Record a decision: context, options considered, consequences, what it locks in
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
You are Construct. Document the decision about: $ARGUMENTS
|
package/commands/plan/feature.md
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
commands/plan/feature.md
|
|
2
|
+
commands/plan/feature.md: Plan a feature and turn it into a tracker-linked implementation plan
|
|
3
3
|
|
|
4
4
|
Produces a structured spec using the canonical Construct plan format, saves it
|
|
5
5
|
to .cx/plans/ as a durable planning artifact linked to the active tracker slice.
|
|
6
6
|
-->
|
|
7
7
|
---
|
|
8
|
-
description: Plan a feature
|
|
8
|
+
description: Plan a feature: produce a structured spec and link it to the active tracker-backed plan
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
You are Construct. Plan the following: $ARGUMENTS
|
|
12
12
|
|
|
13
13
|
Use the code-backed orchestration policy for routing/escalation decisions; this prompt only defines the plan artifact shape.
|
|
14
14
|
|
|
15
|
-
## Step 1
|
|
15
|
+
## Step 1: Scope
|
|
16
16
|
Produce:
|
|
17
17
|
- **GOAL**: restate the objective in one sentence
|
|
18
18
|
- **APPROACH**: chosen strategy and why (alternatives considered)
|
|
19
19
|
- **RISKS**: top 3 risks and mitigations
|
|
20
20
|
|
|
21
|
-
## Step 2
|
|
21
|
+
## Step 2: Task breakdown
|
|
22
22
|
|
|
23
23
|
Produce tasks in the canonical Construct plan format:
|
|
24
24
|
|
|
25
25
|
## Tasks
|
|
26
26
|
|
|
27
|
-
### T1
|
|
27
|
+
### T1: {Task title}
|
|
28
28
|
- **Owner**: {cx-specialist}
|
|
29
29
|
- **Phase**: implement
|
|
30
30
|
- **Files**: {comma-separated list of files this task will touch}
|
|
@@ -38,12 +38,12 @@ Produce tasks in the canonical Construct plan format:
|
|
|
38
38
|
(repeat for each task)
|
|
39
39
|
|
|
40
40
|
Rules:
|
|
41
|
-
- Each task is atomic
|
|
41
|
+
- Each task is atomic: one agent, one deliverable
|
|
42
42
|
- Files lists must be disjoint across parallel tasks
|
|
43
43
|
- Acceptance criteria are binary: pass or fail, no "it should be good"
|
|
44
44
|
- Do not change must list every file outside scope that could be accidentally touched
|
|
45
45
|
|
|
46
|
-
## Step 3
|
|
46
|
+
## Step 3: Save and import
|
|
47
47
|
1. Save this full plan to `.cx/plans/{slug}-plan.md`
|
|
48
48
|
2. If the project uses Beads or another external tracker, include the issue id in the plan and keep the current `plan.md` aligned with it
|
|
49
49
|
3. Declare file ownership explicitly so parallel work still follows the single-writer rule
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
commands/plan/requirements.md
|
|
2
|
+
commands/plan/requirements.md (Define requirements) what needs to be true for this to be done
|
|
3
3
|
|
|
4
|
-
Define requirements
|
|
4
|
+
Define requirements: what needs to be true for this to be done
|
|
5
5
|
-->
|
|
6
6
|
---
|
|
7
|
-
description: Define requirements
|
|
7
|
+
description: Define requirements: what needs to be true for this to be done
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
You are Construct. Define requirements for: $ARGUMENTS
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
commands/remember/context.md
|
|
2
|
+
commands/remember/context.md (Save project context) update .cx/context.md so the next session picks up where this one left off
|
|
3
3
|
|
|
4
|
-
Save project context
|
|
4
|
+
Save project context: update .cx/context.md so the next session picks up where this one left off
|
|
5
5
|
-->
|
|
6
6
|
---
|
|
7
|
-
description: Save project context
|
|
7
|
+
description: Save project context: update .cx/context.md so the next session picks up where this one left off
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
You are Construct. Save context for: $ARGUMENTS
|
|
@@ -12,10 +12,10 @@ You are Construct. Save context for: $ARGUMENTS
|
|
|
12
12
|
Update `.cx/context.json` as canonical state and refresh `.cx/context.md` as the readable mirror:
|
|
13
13
|
|
|
14
14
|
## Active Work
|
|
15
|
-
- [title]
|
|
15
|
+
- [title]: [status: in-progress | blocked | in-review]
|
|
16
16
|
|
|
17
17
|
## Recent Decisions
|
|
18
|
-
- [date] [decision]
|
|
18
|
+
- [date] [decision]: [rationale]
|
|
19
19
|
|
|
20
20
|
## Architecture Notes
|
|
21
21
|
- [constraint or invariant future contributors need to know]
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
commands/remember/handoff.md
|
|
2
|
+
commands/remember/handoff.md (Write a handoff) transfer context so the next session or person can continue without loss
|
|
3
3
|
|
|
4
|
-
Write a handoff
|
|
4
|
+
Write a handoff: transfer context so the next session or person can continue without loss
|
|
5
5
|
-->
|
|
6
6
|
---
|
|
7
|
-
description: Write a handoff
|
|
7
|
+
description: Write a handoff: transfer context so the next session or person can continue without loss
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
You are Construct. Write a handoff for: $ARGUMENTS
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
commands/remember/runbook.md
|
|
2
|
+
commands/remember/runbook.md (Write a runbook) step-by-step procedure for a recurring task or incident
|
|
3
3
|
|
|
4
|
-
Write a runbook
|
|
4
|
+
Write a runbook: step-by-step procedure for a recurring task or incident
|
|
5
5
|
-->
|
|
6
6
|
---
|
|
7
|
-
description: Write a runbook
|
|
7
|
+
description: Write a runbook: step-by-step procedure for a recurring task or incident
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
You are Construct. Write a runbook for: $ARGUMENTS
|