@walwal-harness/cli 6.1.6 → 7.1.1
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/HR-Resource/academic-academic-anthropologist/SKILL.md +142 -0
- package/HR-Resource/academic-academic-geographer/SKILL.md +144 -0
- package/HR-Resource/academic-academic-historian/SKILL.md +140 -0
- package/HR-Resource/academic-academic-narratologist/SKILL.md +135 -0
- package/HR-Resource/academic-academic-psychologist/SKILL.md +135 -0
- package/HR-Resource/brick-office/SKILL.md +20 -0
- package/HR-Resource/cdo/SKILL.md +33 -0
- package/HR-Resource/ceo/SKILL.md +47 -0
- package/HR-Resource/coo/SKILL.md +36 -0
- package/HR-Resource/cqo/SKILL.md +33 -0
- package/HR-Resource/cto/SKILL.md +36 -0
- package/HR-Resource/design-design-brand-guardian/SKILL.md +339 -0
- package/HR-Resource/design-design-image-prompt-engineer/SKILL.md +253 -0
- package/HR-Resource/design-design-inclusive-visuals-specialist/SKILL.md +88 -0
- package/HR-Resource/design-design-ui-designer/SKILL.md +400 -0
- package/HR-Resource/design-design-ux-architect/SKILL.md +486 -0
- package/HR-Resource/design-design-ux-researcher/SKILL.md +346 -0
- package/HR-Resource/design-design-visual-storyteller/SKILL.md +166 -0
- package/HR-Resource/design-design-whimsy-injector/SKILL.md +455 -0
- package/HR-Resource/engineering-engineering-ai-data-remediation-engineer/SKILL.md +227 -0
- package/HR-Resource/engineering-engineering-ai-engineer/SKILL.md +163 -0
- package/HR-Resource/engineering-engineering-autonomous-optimization-architect/SKILL.md +124 -0
- package/HR-Resource/engineering-engineering-backend-architect/SKILL.md +252 -0
- package/HR-Resource/engineering-engineering-cms-developer/SKILL.md +553 -0
- package/HR-Resource/engineering-engineering-code-reviewer/SKILL.md +93 -0
- package/HR-Resource/engineering-engineering-codebase-onboarding-engineer/SKILL.md +190 -0
- package/HR-Resource/engineering-engineering-data-engineer/SKILL.md +323 -0
- package/HR-Resource/engineering-engineering-database-optimizer/SKILL.md +193 -0
- package/HR-Resource/engineering-engineering-devops-automator/SKILL.md +393 -0
- package/HR-Resource/engineering-engineering-email-intelligence-engineer/SKILL.md +370 -0
- package/HR-Resource/engineering-engineering-embedded-firmware-engineer/SKILL.md +190 -0
- package/HR-Resource/engineering-engineering-feishu-integration-developer/SKILL.md +615 -0
- package/HR-Resource/engineering-engineering-filament-optimization-specialist/SKILL.md +300 -0
- package/HR-Resource/engineering-engineering-frontend-developer/SKILL.md +242 -0
- package/HR-Resource/engineering-engineering-git-workflow-master/SKILL.md +101 -0
- package/HR-Resource/engineering-engineering-incident-response-commander/SKILL.md +461 -0
- package/HR-Resource/engineering-engineering-minimal-change-engineer/SKILL.md +224 -0
- package/HR-Resource/engineering-engineering-mobile-app-builder/SKILL.md +510 -0
- package/HR-Resource/engineering-engineering-rapid-prototyper/SKILL.md +479 -0
- package/HR-Resource/engineering-engineering-security-engineer/SKILL.md +321 -0
- package/HR-Resource/engineering-engineering-senior-developer/SKILL.md +193 -0
- package/HR-Resource/engineering-engineering-software-architect/SKILL.md +98 -0
- package/HR-Resource/engineering-engineering-solidity-smart-contract-engineer/SKILL.md +539 -0
- package/HR-Resource/engineering-engineering-sre/SKILL.md +107 -0
- package/HR-Resource/engineering-engineering-technical-writer/SKILL.md +410 -0
- package/HR-Resource/engineering-engineering-threat-detection-engineer/SKILL.md +551 -0
- package/HR-Resource/engineering-engineering-voice-ai-integration-engineer/SKILL.md +578 -0
- package/HR-Resource/engineering-engineering-wechat-mini-program-developer/SKILL.md +367 -0
- package/HR-Resource/finance-finance-bookkeeper-controller/SKILL.md +277 -0
- package/HR-Resource/finance-finance-financial-analyst/SKILL.md +251 -0
- package/HR-Resource/finance-finance-fpa-analyst/SKILL.md +280 -0
- package/HR-Resource/finance-finance-investment-researcher/SKILL.md +289 -0
- package/HR-Resource/finance-finance-tax-strategist/SKILL.md +256 -0
- package/HR-Resource/game-development-blender-blender-addon-engineer/SKILL.md +251 -0
- package/HR-Resource/game-development-game-audio-engineer/SKILL.md +281 -0
- package/HR-Resource/game-development-game-designer/SKILL.md +184 -0
- package/HR-Resource/game-development-godot-godot-gameplay-scripter/SKILL.md +351 -0
- package/HR-Resource/game-development-godot-godot-multiplayer-engineer/SKILL.md +314 -0
- package/HR-Resource/game-development-godot-godot-shader-developer/SKILL.md +283 -0
- package/HR-Resource/game-development-level-designer/SKILL.md +225 -0
- package/HR-Resource/game-development-narrative-designer/SKILL.md +260 -0
- package/HR-Resource/game-development-roblox-studio-roblox-avatar-creator/SKILL.md +314 -0
- package/HR-Resource/game-development-roblox-studio-roblox-experience-designer/SKILL.md +322 -0
- package/HR-Resource/game-development-roblox-studio-roblox-systems-scripter/SKILL.md +342 -0
- package/HR-Resource/game-development-technical-artist/SKILL.md +246 -0
- package/HR-Resource/game-development-unity-unity-architect/SKILL.md +288 -0
- package/HR-Resource/game-development-unity-unity-editor-tool-developer/SKILL.md +327 -0
- package/HR-Resource/game-development-unity-unity-multiplayer-engineer/SKILL.md +338 -0
- package/HR-Resource/game-development-unity-unity-shader-graph-artist/SKILL.md +286 -0
- package/HR-Resource/game-development-unreal-engine-unreal-multiplayer-architect/SKILL.md +330 -0
- package/HR-Resource/game-development-unreal-engine-unreal-systems-engineer/SKILL.md +327 -0
- package/HR-Resource/game-development-unreal-engine-unreal-technical-artist/SKILL.md +273 -0
- package/HR-Resource/game-development-unreal-engine-unreal-world-builder/SKILL.md +290 -0
- package/HR-Resource/hiring/SKILL.md +28 -0
- package/HR-Resource/index.json +747 -0
- package/HR-Resource/integrations-mcp-memory-backend-architect-with-memory/SKILL.md +264 -0
- package/HR-Resource/marketing-marketing-agentic-search-optimizer/SKILL.md +328 -0
- package/HR-Resource/marketing-marketing-ai-citation-strategist/SKILL.md +187 -0
- package/HR-Resource/marketing-marketing-app-store-optimizer/SKILL.md +338 -0
- package/HR-Resource/marketing-marketing-baidu-seo-specialist/SKILL.md +243 -0
- package/HR-Resource/marketing-marketing-bilibili-content-strategist/SKILL.md +216 -0
- package/HR-Resource/marketing-marketing-book-co-author/SKILL.md +127 -0
- package/HR-Resource/marketing-marketing-carousel-growth-engine/SKILL.md +216 -0
- package/HR-Resource/marketing-marketing-china-ecommerce-operator/SKILL.md +300 -0
- package/HR-Resource/marketing-marketing-china-market-localization-strategist/SKILL.md +300 -0
- package/HR-Resource/marketing-marketing-content-creator/SKILL.md +71 -0
- package/HR-Resource/marketing-marketing-cross-border-ecommerce/SKILL.md +276 -0
- package/HR-Resource/marketing-marketing-douyin-strategist/SKILL.md +166 -0
- package/HR-Resource/marketing-marketing-growth-hacker/SKILL.md +71 -0
- package/HR-Resource/marketing-marketing-instagram-curator/SKILL.md +130 -0
- package/HR-Resource/marketing-marketing-kuaishou-strategist/SKILL.md +240 -0
- package/HR-Resource/marketing-marketing-linkedin-content-creator/SKILL.md +230 -0
- package/HR-Resource/marketing-marketing-livestream-commerce-coach/SKILL.md +322 -0
- package/HR-Resource/marketing-marketing-podcast-strategist/SKILL.md +294 -0
- package/HR-Resource/marketing-marketing-private-domain-operator/SKILL.md +325 -0
- package/HR-Resource/marketing-marketing-reddit-community-builder/SKILL.md +140 -0
- package/HR-Resource/marketing-marketing-seo-specialist/SKILL.md +338 -0
- package/HR-Resource/marketing-marketing-short-video-editing-coach/SKILL.md +429 -0
- package/HR-Resource/marketing-marketing-social-media-strategist/SKILL.md +142 -0
- package/HR-Resource/marketing-marketing-tiktok-strategist/SKILL.md +142 -0
- package/HR-Resource/marketing-marketing-twitter-engager/SKILL.md +143 -0
- package/HR-Resource/marketing-marketing-video-optimization-specialist/SKILL.md +136 -0
- package/HR-Resource/marketing-marketing-wechat-official-account/SKILL.md +162 -0
- package/HR-Resource/marketing-marketing-weibo-strategist/SKILL.md +257 -0
- package/HR-Resource/marketing-marketing-xiaohongshu-specialist/SKILL.md +155 -0
- package/HR-Resource/marketing-marketing-zhihu-strategist/SKILL.md +179 -0
- package/HR-Resource/ops/SKILL.md +46 -0
- package/HR-Resource/paid-media-paid-media-auditor/SKILL.md +88 -0
- package/HR-Resource/paid-media-paid-media-creative-strategist/SKILL.md +88 -0
- package/HR-Resource/paid-media-paid-media-paid-social-strategist/SKILL.md +88 -0
- package/HR-Resource/paid-media-paid-media-ppc-strategist/SKILL.md +88 -0
- package/HR-Resource/paid-media-paid-media-programmatic-buyer/SKILL.md +88 -0
- package/HR-Resource/paid-media-paid-media-search-query-analyst/SKILL.md +88 -0
- package/HR-Resource/paid-media-paid-media-tracking-specialist/SKILL.md +88 -0
- package/HR-Resource/product-product-behavioral-nudge-engine/SKILL.md +97 -0
- package/HR-Resource/product-product-feedback-synthesizer/SKILL.md +136 -0
- package/HR-Resource/product-product-manager/SKILL.md +486 -0
- package/HR-Resource/product-product-sprint-prioritizer/SKILL.md +171 -0
- package/HR-Resource/product-product-trend-researcher/SKILL.md +176 -0
- package/HR-Resource/project-management-project-management-experiment-tracker/SKILL.md +215 -0
- package/HR-Resource/project-management-project-management-jira-workflow-steward/SKILL.md +247 -0
- package/HR-Resource/project-management-project-management-project-shepherd/SKILL.md +211 -0
- package/HR-Resource/project-management-project-management-studio-operations/SKILL.md +217 -0
- package/HR-Resource/project-management-project-management-studio-producer/SKILL.md +220 -0
- package/HR-Resource/project-management-project-manager-senior/SKILL.md +152 -0
- package/HR-Resource/resource-manager/SKILL.md +23 -0
- package/HR-Resource/sales-sales-account-strategist/SKILL.md +244 -0
- package/HR-Resource/sales-sales-coach/SKILL.md +288 -0
- package/HR-Resource/sales-sales-deal-strategist/SKILL.md +197 -0
- package/HR-Resource/sales-sales-discovery-coach/SKILL.md +242 -0
- package/HR-Resource/sales-sales-engineer/SKILL.md +199 -0
- package/HR-Resource/sales-sales-outbound-strategist/SKILL.md +218 -0
- package/HR-Resource/sales-sales-pipeline-analyst/SKILL.md +284 -0
- package/HR-Resource/sales-sales-proposal-strategist/SKILL.md +234 -0
- package/HR-Resource/spatial-computing-macos-spatial-metal-engineer/SKILL.md +354 -0
- package/HR-Resource/spatial-computing-terminal-integration-specialist/SKILL.md +87 -0
- package/HR-Resource/spatial-computing-visionos-spatial-engineer/SKILL.md +71 -0
- package/HR-Resource/spatial-computing-xr-cockpit-interaction-specialist/SKILL.md +49 -0
- package/HR-Resource/spatial-computing-xr-immersive-developer/SKILL.md +49 -0
- package/HR-Resource/spatial-computing-xr-interface-architect/SKILL.md +49 -0
- package/HR-Resource/specialized-accounts-payable-agent/SKILL.md +202 -0
- package/HR-Resource/specialized-agentic-identity-trust/SKILL.md +404 -0
- package/HR-Resource/specialized-agents-orchestrator/SKILL.md +384 -0
- package/HR-Resource/specialized-automation-governance-architect/SKILL.md +233 -0
- package/HR-Resource/specialized-blockchain-security-auditor/SKILL.md +480 -0
- package/HR-Resource/specialized-compliance-auditor/SKILL.md +175 -0
- package/HR-Resource/specialized-corporate-training-designer/SKILL.md +209 -0
- package/HR-Resource/specialized-customer-service/SKILL.md +415 -0
- package/HR-Resource/specialized-data-consolidation-agent/SKILL.md +77 -0
- package/HR-Resource/specialized-government-digital-presales-consultant/SKILL.md +380 -0
- package/HR-Resource/specialized-healthcare-customer-service/SKILL.md +406 -0
- package/HR-Resource/specialized-healthcare-marketing-compliance/SKILL.md +412 -0
- package/HR-Resource/specialized-hospitality-guest-services/SKILL.md +620 -0
- package/HR-Resource/specialized-hr-onboarding/SKILL.md +468 -0
- package/HR-Resource/specialized-identity-graph-operator/SKILL.md +277 -0
- package/HR-Resource/specialized-language-translator/SKILL.md +281 -0
- package/HR-Resource/specialized-legal-billing-time-tracking/SKILL.md +586 -0
- package/HR-Resource/specialized-legal-client-intake/SKILL.md +509 -0
- package/HR-Resource/specialized-legal-document-review/SKILL.md +471 -0
- package/HR-Resource/specialized-loan-officer-assistant/SKILL.md +572 -0
- package/HR-Resource/specialized-lsp-index-engineer/SKILL.md +331 -0
- package/HR-Resource/specialized-real-estate-buyer-seller/SKILL.md +613 -0
- package/HR-Resource/specialized-recruitment-specialist/SKILL.md +526 -0
- package/HR-Resource/specialized-report-distribution-agent/SKILL.md +82 -0
- package/HR-Resource/specialized-retail-customer-returns/SKILL.md +583 -0
- package/HR-Resource/specialized-sales-data-extraction-agent/SKILL.md +84 -0
- package/HR-Resource/specialized-sales-outreach/SKILL.md +442 -0
- package/HR-Resource/specialized-specialized-chief-of-staff/SKILL.md +296 -0
- package/HR-Resource/specialized-specialized-civil-engineer/SKILL.md +373 -0
- package/HR-Resource/specialized-specialized-cultural-intelligence-strategist/SKILL.md +105 -0
- package/HR-Resource/specialized-specialized-developer-advocate/SKILL.md +334 -0
- package/HR-Resource/specialized-specialized-document-generator/SKILL.md +72 -0
- package/HR-Resource/specialized-specialized-french-consulting-market/SKILL.md +209 -0
- package/HR-Resource/specialized-specialized-korean-business-navigator/SKILL.md +233 -0
- package/HR-Resource/specialized-specialized-mcp-builder/SKILL.md +265 -0
- package/HR-Resource/specialized-specialized-model-qa/SKILL.md +505 -0
- package/HR-Resource/specialized-specialized-salesforce-architect/SKILL.md +197 -0
- package/HR-Resource/specialized-specialized-workflow-architect/SKILL.md +614 -0
- package/HR-Resource/specialized-study-abroad-advisor/SKILL.md +299 -0
- package/HR-Resource/specialized-supply-chain-strategist/SKILL.md +599 -0
- package/HR-Resource/specialized-zk-steward/SKILL.md +228 -0
- package/HR-Resource/support-support-analytics-reporter/SKILL.md +382 -0
- package/HR-Resource/support-support-executive-summary-generator/SKILL.md +229 -0
- package/HR-Resource/support-support-finance-tracker/SKILL.md +459 -0
- package/HR-Resource/support-support-infrastructure-maintainer/SKILL.md +635 -0
- package/HR-Resource/support-support-legal-compliance-checker/SKILL.md +605 -0
- package/HR-Resource/support-support-support-responder/SKILL.md +602 -0
- package/HR-Resource/testing-testing-accessibility-auditor/SKILL.md +333 -0
- package/HR-Resource/testing-testing-api-tester/SKILL.md +323 -0
- package/HR-Resource/testing-testing-evidence-collector/SKILL.md +227 -0
- package/HR-Resource/testing-testing-performance-benchmarker/SKILL.md +285 -0
- package/HR-Resource/testing-testing-reality-checker/SKILL.md +253 -0
- package/HR-Resource/testing-testing-test-results-analyzer/SKILL.md +322 -0
- package/HR-Resource/testing-testing-tool-evaluator/SKILL.md +411 -0
- package/HR-Resource/testing-testing-workflow-optimizer/SKILL.md +467 -0
- package/assets/templates/config.json +36 -2
- package/bin/init.js +292 -110
- package/commands/goal.md +25 -0
- package/commands/hot-fix.md +25 -0
- package/commands/play-harness.md +22 -0
- package/commands/release-harness.md +22 -0
- package/commands/stop-harness.md +21 -0
- package/conventions/README.md +14 -88
- package/conventions/brick-office.md +5 -0
- package/conventions/cdo.md +6 -0
- package/conventions/ceo.md +9 -0
- package/conventions/coo.md +6 -0
- package/conventions/cqo.md +6 -23
- package/conventions/cto.md +5 -23
- package/conventions/hiring.md +7 -0
- package/conventions/ops.md +9 -0
- package/conventions/resource-manager.md +6 -0
- package/conventions/shared.md +29 -58
- package/gotchas/README.md +14 -82
- package/gotchas/brick-office.md +9 -0
- package/gotchas/cdo.md +9 -0
- package/gotchas/ceo.md +9 -0
- package/gotchas/coo.md +9 -0
- package/gotchas/cqo.md +6 -19
- package/gotchas/cto.md +6 -19
- package/gotchas/hiring.md +9 -0
- package/gotchas/ops.md +17 -0
- package/gotchas/resource-manager.md +9 -0
- package/gotchas/shared.md +13 -0
- package/init.sh +208 -0
- package/package.json +12 -17
- package/scripts/harness-runtime-stop.sh +58 -0
- package/scripts/harness-service-ops-monitor.sh +160 -16
- package/scripts/harness-stop.sh +18 -0
- package/scripts/harness-worker-evidence-validate.sh +59 -0
- package/scripts/import-agency-agents.js +102 -0
- package/scripts/play.sh +104 -0
- package/scripts/release.sh +89 -0
- package/conventions/conductor.md +0 -24
- package/conventions/coo-developer.md +0 -24
- package/conventions/dispatcher.md +0 -24
- package/conventions/documentationer.md +0 -24
- package/conventions/evaluator-architecture.md +0 -24
- package/conventions/evaluator-code-quality.md +0 -24
- package/conventions/evaluator-functional.md +0 -24
- package/conventions/evaluator-security.md +0 -24
- package/conventions/evaluator-visual.md +0 -24
- package/conventions/generator-backend.md +0 -24
- package/conventions/generator-designer.md +0 -24
- package/conventions/generator-devops.md +0 -24
- package/conventions/generator-frontend.md +0 -24
- package/conventions/meeting-manager.md +0 -24
- package/conventions/planner.md +0 -24
- package/conventions/service-ops.md +0 -24
- package/gotchas/conductor.md +0 -38
- package/gotchas/coo-developer.md +0 -22
- package/gotchas/dispatcher.md +0 -38
- package/gotchas/documentationer.md +0 -22
- package/gotchas/evaluator-architecture.md +0 -22
- package/gotchas/evaluator-code-quality.md +0 -22
- package/gotchas/evaluator-functional.md +0 -22
- package/gotchas/evaluator-security.md +0 -22
- package/gotchas/evaluator-visual.md +0 -22
- package/gotchas/generator-backend-laravel.md +0 -19
- package/gotchas/generator-backend.md +0 -22
- package/gotchas/generator-designer.md +0 -22
- package/gotchas/generator-devops.md +0 -22
- package/gotchas/generator-frontend.md +0 -22
- package/gotchas/meeting-manager.md +0 -30
- package/gotchas/planner.md +0 -22
- package/gotchas/service-ops.md +0 -30
- package/skills/_shared/dynamic-registration.md +0 -120
- package/skills/brainstorming/SKILL.md +0 -220
- package/skills/brainstorming/references/attribution.md +0 -109
- package/skills/brainstorming/references/spec-document-reviewer-prompt.md +0 -49
- package/skills/brainstorming/references/visual-companion.md +0 -287
- package/skills/brainstorming/scripts/frame-template.html +0 -214
- package/skills/brainstorming/scripts/helper.js +0 -88
- package/skills/brainstorming/scripts/server.cjs +0 -354
- package/skills/brainstorming/scripts/start-server.sh +0 -148
- package/skills/brainstorming/scripts/stop-server.sh +0 -56
- package/skills/conductor/SKILL.md +0 -336
- package/skills/coo-developer/SKILL.md +0 -72
- package/skills/cqo/SKILL.md +0 -146
- package/skills/cto/SKILL.md +0 -141
- package/skills/dispatcher/SKILL.md +0 -298
- package/skills/dispatcher/persona-ceo.md +0 -169
- package/skills/dispatcher/references/convention-flow.md +0 -111
- package/skills/dispatcher/references/gotcha-flow.md +0 -79
- package/skills/dispatcher/references/initialization.md +0 -53
- package/skills/dispatcher/references/pipeline-definitions.md +0 -151
- package/skills/documentationer/SKILL.md +0 -92
- package/skills/evaluator-architecture/SKILL.md +0 -173
- package/skills/evaluator-code-quality/SKILL.md +0 -218
- package/skills/evaluator-code-quality/references/scoring-rubric.md +0 -104
- package/skills/evaluator-functional/SKILL.md +0 -271
- package/skills/evaluator-functional/references/ia-compliance.md +0 -37
- package/skills/evaluator-functional/references/playwright-tools.md +0 -43
- package/skills/evaluator-functional/references/scoring-rubric.md +0 -52
- package/skills/evaluator-security/SKILL.md +0 -172
- package/skills/evaluator-visual/SKILL.md +0 -165
- package/skills/evaluator-visual/references/responsive-checklist.md +0 -44
- package/skills/evaluator-visual/references/scoring-rubric.md +0 -59
- package/skills/generator-backend/SKILL.md +0 -153
- package/skills/generator-backend/references/nestjs-msa-patterns.md +0 -69
- package/skills/generator-backend/references/sprint-contract-be.md +0 -32
- package/skills/generator-designer/SKILL.md +0 -219
- package/skills/generator-devops/SKILL.md +0 -201
- package/skills/generator-frontend/SKILL.md +0 -155
- package/skills/generator-frontend/references/_web-react-legacy/ai-forbidden-patterns.md +0 -89
- package/skills/generator-frontend/references/_web-react-legacy/component-patterns.md +0 -52
- package/skills/generator-frontend/references/_web-react-legacy/design-system-rules.md +0 -139
- package/skills/generator-frontend/references/_web-react-legacy/vercel-best-practices.md +0 -54
- package/skills/meeting-manager/SKILL.md +0 -419
- package/skills/planner/SKILL.md +0 -243
- package/skills/planner/hr-onboard.md +0 -134
- package/skills/planner/hr-recruit.md +0 -99
- package/skills/planner/persona-coo-hr.md +0 -182
- package/skills/planner/references/api-contract-schema.md +0 -34
- package/skills/planner/references/fe-stack-detection.md +0 -164
- package/skills/planner/references/ia-map-guide.md +0 -31
- package/skills/planner/references/plan-template.md +0 -51
- package/skills/service-ops/SKILL.md +0 -295
package/bin/init.js
CHANGED
|
@@ -53,6 +53,9 @@ function resolveProjectRoot() {
|
|
|
53
53
|
const PROJECT_ROOT = resolveProjectRoot();
|
|
54
54
|
const HARNESS_DIR = path.join(PROJECT_ROOT, '.harness');
|
|
55
55
|
const CLAUDE_SKILLS_DIR = path.join(PROJECT_ROOT, '.claude', 'skills');
|
|
56
|
+
const CLAUDE_COMMANDS_DIR = path.join(PROJECT_ROOT, '.claude', 'commands');
|
|
57
|
+
const CODEX_SKILLS_DIR = path.join(PROJECT_ROOT, '.codex', 'skills');
|
|
58
|
+
const CODEX_COMMANDS_DIR = path.join(PROJECT_ROOT, '.codex', 'commands');
|
|
56
59
|
|
|
57
60
|
// ─────────────────────────────────────────
|
|
58
61
|
// Utility
|
|
@@ -86,10 +89,170 @@ function fileExists(p) {
|
|
|
86
89
|
return fs.existsSync(p);
|
|
87
90
|
}
|
|
88
91
|
|
|
92
|
+
function deepMerge(base, override) {
|
|
93
|
+
if (!override || typeof override !== 'object' || Array.isArray(override)) return base;
|
|
94
|
+
const out = { ...(base || {}) };
|
|
95
|
+
for (const [key, value] of Object.entries(override)) {
|
|
96
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
97
|
+
out[key] = deepMerge(out[key] || {}, value);
|
|
98
|
+
} else {
|
|
99
|
+
out[key] = value;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
104
|
+
|
|
89
105
|
function log(msg) {
|
|
90
106
|
console.log(`[walwal-harness] ${msg}`);
|
|
91
107
|
}
|
|
92
108
|
|
|
109
|
+
function readClaudeSettings() {
|
|
110
|
+
const settingsPath = path.join(PROJECT_ROOT, '.claude', 'settings.json');
|
|
111
|
+
if (!fileExists(settingsPath)) return {};
|
|
112
|
+
try {
|
|
113
|
+
return JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
114
|
+
} catch (e) {
|
|
115
|
+
log('WARNING: Could not parse existing .claude/settings.json, creating new');
|
|
116
|
+
return {};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function writeClaudeSettings(settings) {
|
|
121
|
+
const settingsPath = path.join(PROJECT_ROOT, '.claude', 'settings.json');
|
|
122
|
+
ensureDir(path.dirname(settingsPath));
|
|
123
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function mergeClaudePermissionAllow(settings, entries) {
|
|
127
|
+
if (!settings.permissions || typeof settings.permissions !== 'object') {
|
|
128
|
+
settings.permissions = {};
|
|
129
|
+
}
|
|
130
|
+
if (!Array.isArray(settings.permissions.allow)) {
|
|
131
|
+
settings.permissions.allow = [];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
let changed = false;
|
|
135
|
+
for (const entry of entries) {
|
|
136
|
+
if (!settings.permissions.allow.includes(entry)) {
|
|
137
|
+
settings.permissions.allow.push(entry);
|
|
138
|
+
changed = true;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return changed;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const V7_REMOVED_CONVENTION_FILES = [
|
|
145
|
+
'conductor.md',
|
|
146
|
+
'coo-developer.md',
|
|
147
|
+
'dispatcher.md',
|
|
148
|
+
'documentationer.md',
|
|
149
|
+
'evaluator-architecture.md',
|
|
150
|
+
'evaluator-code-quality.md',
|
|
151
|
+
'evaluator-functional.md',
|
|
152
|
+
'evaluator-security.md',
|
|
153
|
+
'evaluator-visual.md',
|
|
154
|
+
'generator-backend.md',
|
|
155
|
+
'generator-designer.md',
|
|
156
|
+
'generator-devops.md',
|
|
157
|
+
'generator-frontend.md',
|
|
158
|
+
'meeting-manager.md',
|
|
159
|
+
'planner.md',
|
|
160
|
+
'service-ops.md',
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
const V7_REMOVED_GOTCHA_FILES = [
|
|
164
|
+
...V7_REMOVED_CONVENTION_FILES,
|
|
165
|
+
'generator-backend-laravel.md',
|
|
166
|
+
];
|
|
167
|
+
|
|
168
|
+
const LEGACY_V7_FILE_OWNER = {
|
|
169
|
+
'conductor.md': 'ceo.md',
|
|
170
|
+
'dispatcher.md': 'ceo.md',
|
|
171
|
+
'coo-developer.md': 'coo.md',
|
|
172
|
+
'planner.md': 'coo.md',
|
|
173
|
+
'documentationer.md': 'coo.md',
|
|
174
|
+
'generator-frontend.md': 'cto.md',
|
|
175
|
+
'generator-backend.md': 'cto.md',
|
|
176
|
+
'generator-backend-laravel.md': 'cto.md',
|
|
177
|
+
'generator-devops.md': 'cto.md',
|
|
178
|
+
'evaluator-architecture.md': 'cto.md',
|
|
179
|
+
'generator-designer.md': 'cdo.md',
|
|
180
|
+
'evaluator-visual.md': 'cdo.md',
|
|
181
|
+
'evaluator-functional.md': 'cqo.md',
|
|
182
|
+
'evaluator-code-quality.md': 'cqo.md',
|
|
183
|
+
'evaluator-security.md': 'cqo.md',
|
|
184
|
+
'meeting-manager.md': 'ops.md',
|
|
185
|
+
'service-ops.md': 'ops.md',
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
function removeLegacyV7Files(dir, files) {
|
|
189
|
+
for (const file of files) {
|
|
190
|
+
const target = path.join(dir, file);
|
|
191
|
+
if (fs.existsSync(target)) {
|
|
192
|
+
fs.rmSync(target, { force: true });
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function extractMarkdownEntryBlocks(md, prefix) {
|
|
198
|
+
const escapedPrefix = prefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
199
|
+
const re = new RegExp(
|
|
200
|
+
`^#{2,3}\\s+\\[(${escapedPrefix}-[A-Z0-9_-]+)\\][\\s\\S]*?(?=^#{2,3}\\s+\\[${escapedPrefix}-|$(?![\\s\\S]))`,
|
|
201
|
+
'gm',
|
|
202
|
+
);
|
|
203
|
+
const blocks = [];
|
|
204
|
+
let match;
|
|
205
|
+
while ((match = re.exec(md)) !== null) {
|
|
206
|
+
blocks.push({ id: match[1], body: match[0].trimEnd() });
|
|
207
|
+
}
|
|
208
|
+
return blocks;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function migrateLegacyRoleEntries(dir, files, kind) {
|
|
212
|
+
const prefix = kind === 'gotchas' ? 'G' : 'C';
|
|
213
|
+
const migrated = [];
|
|
214
|
+
const backupDir = path.join(HARNESS_DIR, 'archive', 'pre-v7-role-migration');
|
|
215
|
+
for (const file of files) {
|
|
216
|
+
const sourcePath = path.join(dir, file);
|
|
217
|
+
if (!fs.existsSync(sourcePath)) continue;
|
|
218
|
+
|
|
219
|
+
const content = fs.readFileSync(sourcePath, 'utf8');
|
|
220
|
+
const blocks = extractMarkdownEntryBlocks(content, prefix);
|
|
221
|
+
if (!blocks.length) continue;
|
|
222
|
+
|
|
223
|
+
const targetFile = LEGACY_V7_FILE_OWNER[file] || 'shared.md';
|
|
224
|
+
const targetPath = path.join(dir, targetFile);
|
|
225
|
+
const targetOriginal = fs.existsSync(targetPath) ? fs.readFileSync(targetPath, 'utf8') : '';
|
|
226
|
+
const targetIds = new Set(
|
|
227
|
+
kind === 'gotchas'
|
|
228
|
+
? extractGotchaEntryIds(targetOriginal)
|
|
229
|
+
: extractConventionEntryIds(targetOriginal),
|
|
230
|
+
);
|
|
231
|
+
const appendBlocks = [];
|
|
232
|
+
for (const block of blocks) {
|
|
233
|
+
if (targetIds.has(block.id)) continue;
|
|
234
|
+
appendBlocks.push([
|
|
235
|
+
block.body,
|
|
236
|
+
'',
|
|
237
|
+
`- **Migration source**: ${kind}/${file}`,
|
|
238
|
+
].join('\n'));
|
|
239
|
+
targetIds.add(block.id);
|
|
240
|
+
}
|
|
241
|
+
if (!appendBlocks.length) continue;
|
|
242
|
+
|
|
243
|
+
ensureDir(backupDir);
|
|
244
|
+
fs.writeFileSync(path.join(backupDir, `${kind}-${file}`), content);
|
|
245
|
+
const sep = targetOriginal.trim() ? '\n\n' : '';
|
|
246
|
+
fs.writeFileSync(targetPath, targetOriginal.replace(/\s*$/, '') + sep + appendBlocks.join('\n\n') + '\n');
|
|
247
|
+
migrated.push(`${file} → ${targetFile} (${appendBlocks.length})`);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (migrated.length) {
|
|
251
|
+
log(`${kind} legacy role entries migrated: ${migrated.join(', ')}`);
|
|
252
|
+
log(`Legacy role migration backup: ${backupDir}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
93
256
|
// ─────────────────────────────────────────
|
|
94
257
|
// First-install migration — extract Convention/Gotcha-shaped sections from
|
|
95
258
|
// existing CLAUDE.md / AGENTS.md into .harness/conventions and .harness/gotchas.
|
|
@@ -114,12 +277,15 @@ function migrateExistingDocs() {
|
|
|
114
277
|
|
|
115
278
|
const scopeFor = (body) => {
|
|
116
279
|
const b = body.toLowerCase();
|
|
117
|
-
if (/\b(
|
|
118
|
-
if (/\b(
|
|
119
|
-
if (/\b(
|
|
120
|
-
if (/\b(
|
|
121
|
-
if (/\b(
|
|
122
|
-
if (/\b(
|
|
280
|
+
if (/\b(ceo|dispatcher|owner|goal|hot-?fix|mission)\b/.test(b)) return 'ceo';
|
|
281
|
+
if (/\b(coo|planning|research|hypothesis|backtest|reference)\b/.test(b)) return 'coo';
|
|
282
|
+
if (/\b(cdo|design|brand|ui|ux|mock|visual)\b/.test(b)) return 'cdo';
|
|
283
|
+
if (/\b(cto|architecture|backend|frontend|api|platform|account|devops|implementation)\b/.test(b)) return 'cto';
|
|
284
|
+
if (/\b(cqo|quality|regression|e2e|test|archive|memory|gotcha)\b/.test(b)) return 'cqo';
|
|
285
|
+
if (/\b(ops|operation|service|log|incident|deploy|launch)\b/.test(b)) return 'ops';
|
|
286
|
+
if (/\b(hiring|hire|recruit|hr-resource|worker)\b/.test(b)) return 'hiring';
|
|
287
|
+
if (/\b(resource-manager|resource manager|alias|keyword|wording)\b/.test(b)) return 'resource-manager';
|
|
288
|
+
if (/\b(brick-office|dashboard)\b/.test(b)) return 'brick-office';
|
|
123
289
|
return 'shared';
|
|
124
290
|
};
|
|
125
291
|
|
|
@@ -187,13 +353,12 @@ function migrateExistingDocs() {
|
|
|
187
353
|
report.push(`[${id}] "${sec.title}" → conventions/${scope}.md (from ${sourceRef})`);
|
|
188
354
|
} else {
|
|
189
355
|
const scope = scopeFor(sec.title + '\n' + body);
|
|
190
|
-
const agent = scope === 'shared' ? 'planner' : scope; // default shared-gotchas to planner
|
|
191
356
|
extractedGotcha.counter += 1;
|
|
192
357
|
const id = `G-${String(extractedGotcha.counter).padStart(3, '0')}`;
|
|
193
|
-
const target = path.join(HARNESS_DIR, 'gotchas', `${
|
|
358
|
+
const target = path.join(HARNESS_DIR, 'gotchas', `${scope}.md`);
|
|
194
359
|
appendEntry(target, id, 'gotcha', sec.title, body, sourceRef);
|
|
195
|
-
extractedGotcha.byAgent[
|
|
196
|
-
report.push(`[${id}] "${sec.title}" → gotchas/${
|
|
360
|
+
extractedGotcha.byAgent[scope] = (extractedGotcha.byAgent[scope] || 0) + 1;
|
|
361
|
+
report.push(`[${id}] "${sec.title}" → gotchas/${scope}.md (from ${sourceRef})`);
|
|
197
362
|
}
|
|
198
363
|
}
|
|
199
364
|
}
|
|
@@ -246,13 +411,40 @@ function scaffoldHarness() {
|
|
|
246
411
|
ensureDir(path.join(HARNESS_DIR, 'archive'));
|
|
247
412
|
ensureDir(path.join(HARNESS_DIR, 'gotchas'));
|
|
248
413
|
ensureDir(path.join(HARNESS_DIR, 'conventions'));
|
|
414
|
+
ensureDir(path.join(HARNESS_DIR, 'documents'));
|
|
415
|
+
ensureDir(path.join(HARNESS_DIR, 'logs'));
|
|
416
|
+
ensureDir(path.join(HARNESS_DIR, 'memories'));
|
|
417
|
+
ensureDir(path.join(HARNESS_DIR, 'shared'));
|
|
418
|
+
|
|
419
|
+
migrateLegacyRoleEntries(path.join(HARNESS_DIR, 'conventions'), V7_REMOVED_CONVENTION_FILES, 'conventions');
|
|
420
|
+
migrateLegacyRoleEntries(path.join(HARNESS_DIR, 'gotchas'), V7_REMOVED_GOTCHA_FILES, 'gotchas');
|
|
421
|
+
|
|
422
|
+
removeLegacyV7Files(path.join(HARNESS_DIR, 'conventions'), V7_REMOVED_CONVENTION_FILES);
|
|
423
|
+
removeLegacyV7Files(path.join(HARNESS_DIR, 'gotchas'), V7_REMOVED_GOTCHA_FILES);
|
|
424
|
+
|
|
425
|
+
const hrResourceSrc = path.join(PKG_ROOT, 'HR-Resource');
|
|
426
|
+
const hrResourceDest = path.join(HARNESS_DIR, 'shared', 'HR-Resource');
|
|
427
|
+
if (fs.existsSync(hrResourceSrc) && (!fs.existsSync(hrResourceDest) || isForce)) {
|
|
428
|
+
copyDir(hrResourceSrc, hrResourceDest);
|
|
429
|
+
log('HR-Resource copied to .harness/shared/HR-Resource');
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
const rosterPath = path.join(HARNESS_DIR, 'shared', 'hr-roster.json');
|
|
433
|
+
if (!fileExists(rosterPath) || isForce) {
|
|
434
|
+
fs.writeFileSync(rosterPath, JSON.stringify({ hired: [] }, null, 2) + '\n');
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
const resourceIndexPath = path.join(HARNESS_DIR, 'shared', 'resource-index.json');
|
|
438
|
+
if (!fileExists(resourceIndexPath) || isForce) {
|
|
439
|
+
fs.writeFileSync(resourceIndexPath, JSON.stringify({ aliases: {}, keywords: {} }, null, 2) + '\n');
|
|
440
|
+
}
|
|
249
441
|
|
|
250
442
|
// Copy gotchas — preserve any existing file that has accumulated entries.
|
|
251
443
|
// Dispatcher appends `### [G-NNN] ...` entries directly; we must NEVER overwrite
|
|
252
444
|
// a file that has such entries, or user learning history is lost.
|
|
253
445
|
const gotchasSrc = path.join(PKG_ROOT, 'gotchas');
|
|
254
446
|
if (fs.existsSync(gotchasSrc)) {
|
|
255
|
-
const ENTRY_PATTERN = /^### \[G
|
|
447
|
+
const ENTRY_PATTERN = /^### \[G-[A-Z0-9_-]+\]/m; // Gotcha entry heading
|
|
256
448
|
const CUSTOM_MARKER = '## Custom Gotchas'; // Legacy marker still supported
|
|
257
449
|
const files = fs.readdirSync(gotchasSrc);
|
|
258
450
|
for (const file of files) {
|
|
@@ -372,6 +564,7 @@ function scaffoldHarness() {
|
|
|
372
564
|
// Preserve user customizations
|
|
373
565
|
const userPreserve = {
|
|
374
566
|
behavior: existing.behavior,
|
|
567
|
+
runtime: existing.runtime,
|
|
375
568
|
'flow.pre_eval_gate.frontend_cwd': existing?.flow?.pre_eval_gate?.frontend_cwd,
|
|
376
569
|
'flow.pre_eval_gate.backend_cwd': existing?.flow?.pre_eval_gate?.backend_cwd,
|
|
377
570
|
'flow.pre_eval_gate.frontend_checks': existing?.flow?.pre_eval_gate?.frontend_checks,
|
|
@@ -382,6 +575,9 @@ function scaffoldHarness() {
|
|
|
382
575
|
// Re-apply preserved user settings
|
|
383
576
|
const merged = JSON.parse(fs.readFileSync(configDest, 'utf8'));
|
|
384
577
|
if (userPreserve.behavior) merged.behavior = userPreserve.behavior;
|
|
578
|
+
if (userPreserve.runtime) {
|
|
579
|
+
merged.runtime = deepMerge(merged.runtime || {}, userPreserve.runtime);
|
|
580
|
+
}
|
|
385
581
|
if (userPreserve['flow.pre_eval_gate.frontend_cwd']) {
|
|
386
582
|
merged.flow.pre_eval_gate.frontend_cwd = userPreserve['flow.pre_eval_gate.frontend_cwd'];
|
|
387
583
|
}
|
|
@@ -405,6 +601,8 @@ function scaffoldHarness() {
|
|
|
405
601
|
}
|
|
406
602
|
}
|
|
407
603
|
|
|
604
|
+
ensureHarnessEnv();
|
|
605
|
+
|
|
408
606
|
// HARNESS.md — ALWAYS update
|
|
409
607
|
const harnessMdSrc = path.join(PKG_ROOT, 'assets', 'templates', 'HARNESS.md');
|
|
410
608
|
const harnessMdDest = path.join(HARNESS_DIR, 'HARNESS.md');
|
|
@@ -443,38 +641,57 @@ function scaffoldHarness() {
|
|
|
443
641
|
log('.harness/ scaffolding complete');
|
|
444
642
|
}
|
|
445
643
|
|
|
644
|
+
function ensureHarnessEnv() {
|
|
645
|
+
const envPath = path.join(PROJECT_ROOT, '.env');
|
|
646
|
+
const marker = 'HARNESS_BASE_PORT';
|
|
647
|
+
const re = new RegExp(`^${marker}`, 'm');
|
|
648
|
+
|
|
649
|
+
let content = '';
|
|
650
|
+
if (fileExists(envPath)) {
|
|
651
|
+
content = fs.readFileSync(envPath, 'utf8');
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
if (re.test(content)) return;
|
|
655
|
+
|
|
656
|
+
const prefix = content && !content.endsWith('\n') ? '\n' : '';
|
|
657
|
+
const block = `${prefix}${content ? '\n' : ''}# Walwal Harness — CEO must agree on a {xx}000 base port with the Owner.\n# Set HARNESS_BASE_PORT before CXX agents allocate any service ports.\n# HARNESS_BASE_PORT=\n`;
|
|
658
|
+
fs.writeFileSync(envPath, content + block);
|
|
659
|
+
log('.env: HARNESS_BASE_PORT placeholder added — set value with Owner approval before starting services');
|
|
660
|
+
}
|
|
661
|
+
|
|
446
662
|
// ─────────────────────────────────────────
|
|
447
663
|
// 2. Skills → .claude/skills/
|
|
448
664
|
// ─────────────────────────────────────────
|
|
449
665
|
function installSkills() {
|
|
450
|
-
log('Installing skills to .claude/skills/...');
|
|
666
|
+
log('Installing skills to .claude/skills/ and .codex/skills/...');
|
|
451
667
|
|
|
452
|
-
const
|
|
453
|
-
|
|
454
|
-
log('WARNING: skills/ directory not found in package');
|
|
455
|
-
return;
|
|
456
|
-
}
|
|
668
|
+
const hrSrc = path.join(PKG_ROOT, 'HR-Resource');
|
|
669
|
+
const destinations = [CLAUDE_SKILLS_DIR, CODEX_SKILLS_DIR];
|
|
457
670
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
const existing = fs.readdirSync(
|
|
671
|
+
for (const destRoot of destinations) {
|
|
672
|
+
ensureDir(destRoot);
|
|
673
|
+
const existing = fs.readdirSync(destRoot, { withFileTypes: true });
|
|
461
674
|
for (const entry of existing) {
|
|
462
675
|
if (entry.isDirectory() && entry.name.startsWith('harness-')) {
|
|
463
|
-
fs.rmSync(path.join(
|
|
676
|
+
fs.rmSync(path.join(destRoot, entry.name), { recursive: true, force: true });
|
|
464
677
|
}
|
|
465
678
|
}
|
|
466
|
-
log(' Cleared existing harness-* skills');
|
|
467
679
|
}
|
|
680
|
+
log(' Cleared existing harness-* skills');
|
|
468
681
|
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
|
|
682
|
+
const installSkillDir = (src, destName) => {
|
|
683
|
+
for (const destRoot of destinations) {
|
|
684
|
+
copyDir(src, path.join(destRoot, destName));
|
|
685
|
+
}
|
|
686
|
+
log(` Installed: ${destName}`);
|
|
687
|
+
};
|
|
472
688
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
|
|
689
|
+
const coreHrSkills = ['ceo', 'coo', 'cdo', 'cto', 'cqo', 'ops', 'hiring', 'resource-manager', 'brick-office'];
|
|
690
|
+
if (fs.existsSync(hrSrc)) {
|
|
691
|
+
for (const skill of coreHrSkills) {
|
|
692
|
+
const src = path.join(hrSrc, skill);
|
|
693
|
+
if (fs.existsSync(src)) installSkillDir(src, `harness-${skill}`);
|
|
694
|
+
}
|
|
478
695
|
}
|
|
479
696
|
|
|
480
697
|
log('Skills installation complete');
|
|
@@ -520,7 +737,7 @@ function installScripts() {
|
|
|
520
737
|
// 3a. Commands → .claude/commands/
|
|
521
738
|
// ─────────────────────────────────────────
|
|
522
739
|
function installCommands() {
|
|
523
|
-
log('Installing commands to .claude/commands/...');
|
|
740
|
+
log('Installing commands to .claude/commands/ and .codex/commands/...');
|
|
524
741
|
|
|
525
742
|
const commandsSrc = path.join(PKG_ROOT, 'commands');
|
|
526
743
|
if (!fs.existsSync(commandsSrc)) {
|
|
@@ -528,24 +745,26 @@ function installCommands() {
|
|
|
528
745
|
return;
|
|
529
746
|
}
|
|
530
747
|
|
|
531
|
-
const
|
|
532
|
-
ensureDir
|
|
748
|
+
const commandDests = [CLAUDE_COMMANDS_DIR, CODEX_COMMANDS_DIR];
|
|
749
|
+
commandDests.forEach(ensureDir);
|
|
533
750
|
|
|
534
751
|
// Remove existing harness-* commands to prevent stale files
|
|
535
|
-
|
|
752
|
+
for (const commandsDest of commandDests) {
|
|
536
753
|
const existing = fs.readdirSync(commandsDest);
|
|
537
754
|
for (const f of existing) {
|
|
538
|
-
if (f.startsWith('harness-')) {
|
|
755
|
+
if (f.startsWith('harness-') || ['goal.md', 'hot-fix.md', 'play-harness.md', 'release-harness.md', 'stop-harness.md', 'brick-office.md', 'hiring.md', 'resource-manager.md', 'ceo.md', 'coo.md', 'cdo.md', 'cto.md', 'cqo.md', 'ops.md'].includes(f)) {
|
|
539
756
|
fs.unlinkSync(path.join(commandsDest, f));
|
|
540
757
|
}
|
|
541
758
|
}
|
|
542
|
-
log(' Cleared existing harness-* commands');
|
|
543
759
|
}
|
|
760
|
+
log(' Cleared existing harness commands');
|
|
544
761
|
|
|
545
762
|
// Copy all command files
|
|
546
763
|
const files = fs.readdirSync(commandsSrc).filter(f => f.endsWith('.md'));
|
|
547
764
|
for (const file of files) {
|
|
548
|
-
|
|
765
|
+
for (const commandsDest of commandDests) {
|
|
766
|
+
copyFile(path.join(commandsSrc, file), path.join(commandsDest, file));
|
|
767
|
+
}
|
|
549
768
|
log(` Installed: /${file.replace('.md', '')}`);
|
|
550
769
|
}
|
|
551
770
|
|
|
@@ -559,18 +778,10 @@ function installSessionHook() {
|
|
|
559
778
|
log('Installing SessionStart hook...');
|
|
560
779
|
|
|
561
780
|
const settingsDir = path.join(PROJECT_ROOT, '.claude');
|
|
562
|
-
const settingsFile = path.join(settingsDir, 'settings.json');
|
|
563
781
|
|
|
564
782
|
ensureDir(settingsDir);
|
|
565
783
|
|
|
566
|
-
let settings =
|
|
567
|
-
if (fileExists(settingsFile)) {
|
|
568
|
-
try {
|
|
569
|
-
settings = JSON.parse(fs.readFileSync(settingsFile, 'utf8'));
|
|
570
|
-
} catch (e) {
|
|
571
|
-
log('WARNING: Could not parse existing .claude/settings.json, creating new');
|
|
572
|
-
}
|
|
573
|
-
}
|
|
784
|
+
let settings = readClaudeSettings();
|
|
574
785
|
|
|
575
786
|
// Ensure hooks.SessionStart array exists
|
|
576
787
|
if (!settings.hooks) settings.hooks = {};
|
|
@@ -608,10 +819,10 @@ function installSessionHook() {
|
|
|
608
819
|
matcher: '',
|
|
609
820
|
hooks: [{ type: 'command', command: hookCmd }]
|
|
610
821
|
});
|
|
611
|
-
|
|
822
|
+
writeClaudeSettings(settings);
|
|
612
823
|
log('SessionStart hook installed in .claude/settings.json');
|
|
613
824
|
} else if (migrated) {
|
|
614
|
-
|
|
825
|
+
writeClaudeSettings(settings);
|
|
615
826
|
log('SessionStart hook migrated to matcher + hooks-array format');
|
|
616
827
|
} else {
|
|
617
828
|
log('SessionStart hook already installed');
|
|
@@ -625,18 +836,10 @@ function installStatusline() {
|
|
|
625
836
|
log('Installing statusline...');
|
|
626
837
|
|
|
627
838
|
const settingsDir = path.join(PROJECT_ROOT, '.claude');
|
|
628
|
-
const settingsFile = path.join(settingsDir, 'settings.json');
|
|
629
839
|
|
|
630
840
|
ensureDir(settingsDir);
|
|
631
841
|
|
|
632
|
-
let settings =
|
|
633
|
-
if (fileExists(settingsFile)) {
|
|
634
|
-
try {
|
|
635
|
-
settings = JSON.parse(fs.readFileSync(settingsFile, 'utf8'));
|
|
636
|
-
} catch (e) {
|
|
637
|
-
log('WARNING: Could not parse existing .claude/settings.json, creating new');
|
|
638
|
-
}
|
|
639
|
-
}
|
|
842
|
+
let settings = readClaudeSettings();
|
|
640
843
|
|
|
641
844
|
// Check if statusLine is already configured
|
|
642
845
|
if (settings.statusLine && settings.statusLine.command &&
|
|
@@ -651,7 +854,7 @@ function installStatusline() {
|
|
|
651
854
|
refreshInterval: 3
|
|
652
855
|
};
|
|
653
856
|
|
|
654
|
-
|
|
857
|
+
writeClaudeSettings(settings);
|
|
655
858
|
log('Statusline installed — persistent status bar at terminal bottom');
|
|
656
859
|
}
|
|
657
860
|
|
|
@@ -662,18 +865,10 @@ function installUserPromptSubmitHook() {
|
|
|
662
865
|
log('Installing UserPromptSubmit hook (auto dispatcher routing)...');
|
|
663
866
|
|
|
664
867
|
const settingsDir = path.join(PROJECT_ROOT, '.claude');
|
|
665
|
-
const settingsFile = path.join(settingsDir, 'settings.json');
|
|
666
868
|
|
|
667
869
|
ensureDir(settingsDir);
|
|
668
870
|
|
|
669
|
-
let settings =
|
|
670
|
-
if (fileExists(settingsFile)) {
|
|
671
|
-
try {
|
|
672
|
-
settings = JSON.parse(fs.readFileSync(settingsFile, 'utf8'));
|
|
673
|
-
} catch (e) {
|
|
674
|
-
log('WARNING: Could not parse existing .claude/settings.json, creating new');
|
|
675
|
-
}
|
|
676
|
-
}
|
|
871
|
+
let settings = readClaudeSettings();
|
|
677
872
|
|
|
678
873
|
if (!settings.hooks) settings.hooks = {};
|
|
679
874
|
if (!settings.hooks.UserPromptSubmit) settings.hooks.UserPromptSubmit = [];
|
|
@@ -699,7 +894,7 @@ function installUserPromptSubmitHook() {
|
|
|
699
894
|
matcher: '',
|
|
700
895
|
hooks: [{ type: 'command', command: hookCmd }]
|
|
701
896
|
});
|
|
702
|
-
|
|
897
|
+
writeClaudeSettings(settings);
|
|
703
898
|
log('UserPromptSubmit hook installed in .claude/settings.json');
|
|
704
899
|
log(' → All prompts will be routed through harness-dispatcher');
|
|
705
900
|
log(' → Opt-out per message: say "harness skip" or "without harness"');
|
|
@@ -716,18 +911,10 @@ function installStopHook() {
|
|
|
716
911
|
log('Installing Stop hook (auto-chain conductor tick)...');
|
|
717
912
|
|
|
718
913
|
const settingsDir = path.join(PROJECT_ROOT, '.claude');
|
|
719
|
-
const settingsFile = path.join(settingsDir, 'settings.json');
|
|
720
914
|
|
|
721
915
|
ensureDir(settingsDir);
|
|
722
916
|
|
|
723
|
-
let settings =
|
|
724
|
-
if (fileExists(settingsFile)) {
|
|
725
|
-
try {
|
|
726
|
-
settings = JSON.parse(fs.readFileSync(settingsFile, 'utf8'));
|
|
727
|
-
} catch (e) {
|
|
728
|
-
log('WARNING: Could not parse existing .claude/settings.json, creating new');
|
|
729
|
-
}
|
|
730
|
-
}
|
|
917
|
+
let settings = readClaudeSettings();
|
|
731
918
|
|
|
732
919
|
if (!settings.hooks) settings.hooks = {};
|
|
733
920
|
if (!settings.hooks.Stop) settings.hooks.Stop = [];
|
|
@@ -752,7 +939,7 @@ function installStopHook() {
|
|
|
752
939
|
matcher: '',
|
|
753
940
|
hooks: [{ type: 'command', command: hookCmd }]
|
|
754
941
|
});
|
|
755
|
-
|
|
942
|
+
writeClaudeSettings(settings);
|
|
756
943
|
log('Stop hook installed in .claude/settings.json');
|
|
757
944
|
log(' → Conductor 가 running 인 동안 turn 종료 시 자동으로 다음 tick 으로 연쇄');
|
|
758
945
|
log(' → 비활성: .harness/config.json behavior.auto_chain_on_stop = false');
|
|
@@ -769,11 +956,7 @@ function installStopHook() {
|
|
|
769
956
|
// 3d. Agent Teams env var
|
|
770
957
|
// ─────────────────────────────────────────
|
|
771
958
|
function installAgentTeamsEnv() {
|
|
772
|
-
|
|
773
|
-
let settings = {};
|
|
774
|
-
if (fileExists(settingsPath)) {
|
|
775
|
-
try { settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8')); } catch (e) {}
|
|
776
|
-
}
|
|
959
|
+
let settings = readClaudeSettings();
|
|
777
960
|
|
|
778
961
|
let changed = false;
|
|
779
962
|
|
|
@@ -787,26 +970,24 @@ function installAgentTeamsEnv() {
|
|
|
787
970
|
log('Agent Teams already enabled');
|
|
788
971
|
}
|
|
789
972
|
|
|
790
|
-
// Add
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
973
|
+
// Add Claude Code permissions required for harness-driven edits, scripts,
|
|
974
|
+
// and parallel worker isolation. Existing permissions are preserved.
|
|
975
|
+
const harnessPerms = [
|
|
976
|
+
'Bash(*)',
|
|
977
|
+
'Write(*)',
|
|
978
|
+
'Edit(*)',
|
|
979
|
+
'Read(*)',
|
|
980
|
+
'MultiEdit(*)',
|
|
794
981
|
'Bash(git worktree *)',
|
|
795
982
|
'Bash(git checkout *)',
|
|
796
983
|
'Bash(git merge *)',
|
|
797
984
|
'Bash(git branch *)'
|
|
798
985
|
];
|
|
799
|
-
|
|
800
|
-
if (!settings.permissions.allow.includes(perm)) {
|
|
801
|
-
settings.permissions.allow.push(perm);
|
|
802
|
-
changed = true;
|
|
803
|
-
}
|
|
804
|
-
}
|
|
986
|
+
changed = mergeClaudePermissionAllow(settings, harnessPerms) || changed;
|
|
805
987
|
|
|
806
988
|
if (changed) {
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
log('Git worktree permissions added for parallel worker isolation');
|
|
989
|
+
writeClaudeSettings(settings);
|
|
990
|
+
log('Claude settings merged: harness permissions/env preserved with existing settings');
|
|
810
991
|
}
|
|
811
992
|
}
|
|
812
993
|
|
|
@@ -957,8 +1138,8 @@ function showHelp() {
|
|
|
957
1138
|
╚══════════════════════════════════════╝
|
|
958
1139
|
|
|
959
1140
|
Usage:
|
|
960
|
-
npx walwal-harness
|
|
961
|
-
npx walwal-harness --force
|
|
1141
|
+
npx walwal-harness init Initialize project for harness engineering
|
|
1142
|
+
npx walwal-harness init --force Re-initialize (overwrites existing harness files)
|
|
962
1143
|
npx walwal-harness migrate Apply migration (always-on company mode)
|
|
963
1144
|
npx walwal-harness migrate --dry-run Preview migration changes without applying
|
|
964
1145
|
npx walwal-harness verify Verify install integrity
|
|
@@ -971,18 +1152,18 @@ Runtime (always-on company mode):
|
|
|
971
1152
|
- Owner 입력은 GOAL 모호성, escalation, 결과 보고에만 필요합니다.
|
|
972
1153
|
|
|
973
1154
|
What it does:
|
|
974
|
-
1. Scaffolds .harness/
|
|
975
|
-
2. Installs
|
|
976
|
-
3.
|
|
1155
|
+
1. Scaffolds project-local .harness/ runtime state
|
|
1156
|
+
2. Installs commands to .claude/commands/ and .codex/commands/
|
|
1157
|
+
3. Installs CXX and harness skills to .claude/skills/ and .codex/skills/
|
|
1158
|
+
4. Copies HR-Resource to .harness/shared/HR-Resource for hiring
|
|
977
1159
|
4. Registers SessionStart + UserPromptSubmit + Stop hooks
|
|
978
1160
|
5. Installs statusline (persistent 1-line status bar)
|
|
979
|
-
6. Creates AGENTS.md + CLAUDE.md symlink
|
|
1161
|
+
6. Creates AGENTS.md + CLAUDE.md symlink when needed
|
|
980
1162
|
|
|
981
1163
|
After init:
|
|
982
|
-
1. Restart Claude
|
|
983
|
-
2.
|
|
984
|
-
3.
|
|
985
|
-
4. (선택) bash scripts/harness-wake-install.sh install . — 1시간마다 자동 wake.
|
|
1164
|
+
1. Restart Claude/Codex session if command discovery needs refresh.
|
|
1165
|
+
2. Use /goal or /hot-fix.
|
|
1166
|
+
3. Internal agents must call hired agents/skills, not slash commands.
|
|
986
1167
|
`);
|
|
987
1168
|
}
|
|
988
1169
|
|
|
@@ -1192,11 +1373,13 @@ function runMigrate(opts = {}) {
|
|
|
1192
1373
|
const dryRun = opts.dryRun || false;
|
|
1193
1374
|
const flags = detectMigrationNeeded();
|
|
1194
1375
|
const gotchaMissingTotal = Object.values(flags.gotchaMissingEntries || {}).reduce((n, a) => n + a.length, 0);
|
|
1376
|
+
const conventionMissingTotal = Object.values(flags.conventionMissingEntries || {}).reduce((n, a) => n + a.length, 0);
|
|
1195
1377
|
if (
|
|
1196
1378
|
!flags.progressV3toV4 &&
|
|
1197
1379
|
!flags.configMissingCompanyMode &&
|
|
1198
1380
|
(!flags.memoryMissingSystemEntries || flags.memoryMissingSystemEntries.length === 0) &&
|
|
1199
1381
|
gotchaMissingTotal === 0 &&
|
|
1382
|
+
conventionMissingTotal === 0 &&
|
|
1200
1383
|
!flags.bundleVersionStale
|
|
1201
1384
|
) {
|
|
1202
1385
|
console.log('');
|
|
@@ -1539,7 +1722,6 @@ function main() {
|
|
|
1539
1722
|
console.log('╚══════════════════════════════════════════════════════════╝');
|
|
1540
1723
|
console.log(' bash scripts/harness-dashboard-up.sh');
|
|
1541
1724
|
console.log(' → http://localhost:3001 에서 .harness/ 상태 실시간 시각화');
|
|
1542
|
-
console.log(' → 첫 실행 시 git sparse-checkout 으로 ~5MB 만 가져옵니다.');
|
|
1543
1725
|
console.log('');
|
|
1544
1726
|
|
|
1545
1727
|
console.log('');
|
|
@@ -1557,9 +1739,9 @@ function main() {
|
|
|
1557
1739
|
log('╚═══════════════════════════════════════════════════════════╝');
|
|
1558
1740
|
} else {
|
|
1559
1741
|
log('Next steps:');
|
|
1560
|
-
log(' 1. Restart Claude
|
|
1561
|
-
log(' 2.
|
|
1562
|
-
log(' 3.
|
|
1742
|
+
log(' 1. Restart Claude/Codex if command discovery needs refresh.');
|
|
1743
|
+
log(' 2. Use /goal or /hot-fix.');
|
|
1744
|
+
log(' 3. Internal agents call hired agents/skills, not slash commands.');
|
|
1563
1745
|
}
|
|
1564
1746
|
console.log('');
|
|
1565
1747
|
}
|
package/commands/goal.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Set, revise, or extend a company mission goal.
|
|
3
|
+
argument-hint: "<goal request>"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /goal
|
|
7
|
+
|
|
8
|
+
Route the Owner request to the installed `harness-ceo` agent/skill.
|
|
9
|
+
|
|
10
|
+
Required flow:
|
|
11
|
+
1. Create or update a mission under `.harness/documents/{mission_name}/`.
|
|
12
|
+
2. Record CEO decisions in `.harness/documents/{mission_name}/ceo.md`.
|
|
13
|
+
3. CEO decides whether brainstorming is needed or whether CXX questions can be issued immediately.
|
|
14
|
+
4. CEO asks COO, CDO, CTO, and CQO only the questions needed for this goal.
|
|
15
|
+
5. CXX roles must start in a fresh session context. Do not let the default model impersonate a missing worker.
|
|
16
|
+
6. CXX roles must not directly execute specialist deliverables. They must use hired workers for research, planning, design, implementation, QA, ops checks, and documentation.
|
|
17
|
+
7. If a required CXX or worker skill is missing, CEO must invoke the installed `harness-hiring` skill before assigning the work.
|
|
18
|
+
8. CEO must require worker report paths under `.harness/documents/{mission_name}/workers/` before accepting CXX completion.
|
|
19
|
+
9. Do not invoke internal roles through slash commands; commands are Owner entrypoints only.
|
|
20
|
+
|
|
21
|
+
Owner request:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
$ARGUMENTS
|
|
25
|
+
```
|