@open-mercato/cli 0.6.7-develop.6863.1.61001cf9a8 → 0.6.7
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/.turbo/turbo-build.log +4 -4
- package/build.mjs +7 -24
- package/dist/agentic/claude-code/hooks/entity-migration-check.ts +88 -32
- package/dist/agentic/codex/enforcement-rules.md +16 -2
- package/dist/agentic/cursor/hooks/entity-migration-check.mjs +50 -19
- package/dist/agentic/cursor/rules/entity-guard.mdc +21 -9
- package/dist/agentic/cursor/rules/generated-guard.mdc +5 -3
- package/dist/agentic/cursor/rules/open-mercato.mdc +29 -3
- package/dist/agentic/guides/cache.md +45 -0
- package/dist/agentic/guides/core.md +453 -0
- package/dist/agentic/guides/events.md +117 -0
- package/dist/agentic/guides/module-facts.json +3833 -115419
- package/dist/agentic/guides/module-system.md +127 -12
- package/dist/agentic/guides/modules/ai_assistant.md +28 -227
- package/dist/agentic/guides/modules/api_docs.md +2 -58
- package/dist/agentic/guides/modules/api_keys.md +7 -92
- package/dist/agentic/guides/modules/attachments.md +14 -119
- package/dist/agentic/guides/modules/audit_logs.md +10 -131
- package/dist/agentic/guides/modules/auth.md +33 -276
- package/dist/agentic/guides/modules/business_rules.md +14 -149
- package/dist/agentic/guides/modules/catalog.md +43 -475
- package/dist/agentic/guides/modules/channel_gmail.md +3 -82
- package/dist/agentic/guides/modules/channel_imap.md +3 -82
- package/dist/agentic/guides/modules/checkout.md +27 -299
- package/dist/agentic/guides/modules/communication_channels.md +33 -315
- package/dist/agentic/guides/modules/configs.md +8 -104
- package/dist/agentic/guides/modules/content.md +2 -57
- package/dist/agentic/guides/modules/currencies.md +17 -152
- package/dist/agentic/guides/modules/customer_accounts.md +45 -387
- package/dist/agentic/guides/modules/customers.md +85 -746
- package/dist/agentic/guides/modules/dashboards.md +10 -155
- package/dist/agentic/guides/modules/data_sync.md +16 -149
- package/dist/agentic/guides/modules/dictionaries.md +12 -107
- package/dist/agentic/guides/modules/directory.md +15 -148
- package/dist/agentic/guides/modules/entities.md +13 -145
- package/dist/agentic/guides/modules/events.md +2 -59
- package/dist/agentic/guides/modules/feature_toggles.md +9 -119
- package/dist/agentic/guides/modules/gateway_stripe.md +4 -92
- package/dist/agentic/guides/modules/generators.md +2 -45
- package/dist/agentic/guides/modules/inbox_ops.md +27 -207
- package/dist/agentic/guides/modules/integrations.md +16 -146
- package/dist/agentic/guides/modules/messages.md +24 -223
- package/dist/agentic/guides/modules/notifications.md +8 -96
- package/dist/agentic/guides/modules/onboarding.md +6 -77
- package/dist/agentic/guides/modules/payment_gateways.md +21 -164
- package/dist/agentic/guides/modules/perspectives.md +7 -77
- package/dist/agentic/guides/modules/planner.md +18 -136
- package/dist/agentic/guides/modules/portal.md +2 -93
- package/dist/agentic/guides/modules/progress.md +14 -104
- package/dist/agentic/guides/modules/query_index.md +15 -154
- package/dist/agentic/guides/modules/record_locks.md +21 -206
- package/dist/agentic/guides/modules/resources.md +30 -197
- package/dist/agentic/guides/modules/sales.md +84 -678
- package/dist/agentic/guides/modules/scheduler.md +14 -133
- package/dist/agentic/guides/modules/search.md +6 -170
- package/dist/agentic/guides/modules/security.md +35 -294
- package/dist/agentic/guides/modules/shipping_carriers.md +18 -134
- package/dist/agentic/guides/modules/sso.md +26 -151
- package/dist/agentic/guides/modules/staff.md +57 -369
- package/dist/agentic/guides/modules/storage_s3.md +5 -95
- package/dist/agentic/guides/modules/sync_akeneo.md +3 -85
- package/dist/agentic/guides/modules/sync_excel.md +6 -75
- package/dist/agentic/guides/modules/system_status_overlays.md +2 -60
- package/dist/agentic/guides/modules/translations.md +10 -104
- package/dist/agentic/guides/modules/webhooks.md +24 -203
- package/dist/agentic/guides/modules/wms.md +46 -441
- package/dist/agentic/guides/modules/workflows.md +43 -302
- package/dist/agentic/guides/queue.md +53 -0
- package/dist/agentic/guides/search.md +115 -0
- package/dist/agentic/guides/shared.md +108 -0
- package/dist/agentic/guides/ui.md +347 -0
- package/dist/agentic/shared/AGENTS.md.template +311 -124
- package/dist/agentic/shared/ai/agentic.config.json +0 -2
- package/dist/agentic/shared/ai/lessons.md +3 -26
- package/dist/agentic/shared/ai/skills/om-auto-continue-pr-loop/SKILL.md +27 -0
- package/dist/agentic/shared/ai/skills/om-auto-create-pr-loop/SKILL.md +27 -0
- package/dist/agentic/shared/ai/skills/om-auto-review-pr/SKILL.md +0 -4
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/SKILL.md +241 -20
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/ui-components.md +260 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/SKILL.md +601 -16
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md +146 -0
- package/dist/agentic/shared/ai/skills/om-eject-and-customize/SKILL.md +310 -14
- package/dist/agentic/shared/ai/skills/om-help/SKILL.md +97 -15
- package/dist/agentic/shared/ai/skills/om-help/references/skills-catalog.md +84 -0
- package/dist/agentic/shared/ai/skills/om-help/references/workflow-sequences.md +193 -0
- package/dist/agentic/shared/ai/skills/om-implement-spec/SKILL.md +152 -33
- package/dist/agentic/shared/ai/skills/om-integration-builder/SKILL.md +708 -24
- package/dist/agentic/shared/ai/skills/om-integration-builder/STANDALONE.md +34 -0
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/adapter-contracts.md +762 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/SKILL.md +820 -20
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/naming-conventions.md +50 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/navigation-patterns.md +97 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/SKILL.md +843 -19
- package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-contracts.md +271 -0
- package/dist/agentic/shared/ai/skills/om-trim-unused-modules/SKILL.md +63 -15
- package/dist/agentic/shared/ai/skills/om-troubleshooter/SKILL.md +467 -16
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnostic-commands.md +101 -0
- package/dist/agentic/shared/ai/skills/tiers.json +21 -143
- package/dist/agentic/shared/ai/skills/tiers.schema.json +40 -52
- package/dist/agentic/shared/ai/specs/README.md +3 -4
- package/dist/agentic/shared/ai/specs/SPEC-000-template.md +10 -226
- package/dist/agentic/shared/ai/trackers/github.md +4 -108
- package/dist/agentic/shared/scripts/install-skills.sh +694 -4
- package/dist/bin.js +1 -13
- package/dist/bin.js.map +2 -2
- package/dist/lib/__integration__/TC-INT-008.spec.js +8 -88
- package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
- package/dist/lib/agentic-init.js +3 -13
- package/dist/lib/agentic-init.js.map +2 -2
- package/dist/lib/agentic-setup.js +186 -418
- package/dist/lib/agentic-setup.js.map +2 -2
- package/dist/lib/generators/extensions/injection-widgets.js +0 -20
- package/dist/lib/generators/extensions/injection-widgets.js.map +2 -2
- package/dist/lib/generators/module-facts-discovery.js +7 -41
- package/dist/lib/generators/module-facts-discovery.js.map +2 -2
- package/dist/lib/generators/module-facts.js +45 -1387
- package/dist/lib/generators/module-facts.js.map +3 -3
- package/dist/lib/generators/module-registry.js +5 -11
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/resolver.js +0 -2
- package/dist/lib/resolver.js.map +2 -2
- package/dist/lib/testing/integration.js +0 -5
- package/dist/lib/testing/integration.js.map +2 -2
- package/dist/mercato.js +1 -23
- package/dist/mercato.js.map +2 -2
- package/package.json +11 -13
- package/src/bin.ts +1 -33
- package/src/lib/__integration__/TC-INT-008.spec.ts +9 -107
- package/src/lib/__tests__/agentic-init.test.ts +5 -41
- package/src/lib/agentic-init.ts +3 -15
- package/src/lib/agentic-setup.ts +224 -530
- package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +2 -88
- package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +0 -1
- package/src/lib/generators/__tests__/module-facts.discovery.test.ts +10 -54
- package/src/lib/generators/__tests__/module-subset.test.ts +0 -18
- package/src/lib/generators/extensions/injection-widgets.ts +0 -51
- package/src/lib/generators/module-facts-discovery.ts +7 -58
- package/src/lib/generators/module-facts.ts +46 -1851
- package/src/lib/generators/module-registry.ts +6 -16
- package/src/lib/resolver.ts +0 -3
- package/src/lib/testing/__tests__/integration.test.ts +0 -4
- package/src/lib/testing/integration.ts +0 -5
- package/src/mercato.ts +1 -26
- package/dist/agentic/guides/ai-workflows.md +0 -76
- package/dist/agentic/guides/architecture.md +0 -107
- package/dist/agentic/guides/backend-ui.md +0 -80
- package/dist/agentic/guides/contracts.md +0 -92
- package/dist/agentic/guides/extensions.md +0 -121
- package/dist/agentic/guides/framework-extension-points.md +0 -36
- package/dist/agentic/guides/integrations.md +0 -81
- package/dist/agentic/guides/modules/design_system.md +0 -102
- package/dist/agentic/guides/spec-delivery.md +0 -22
- package/dist/agentic/guides/testing-debugging.md +0 -80
- package/dist/agentic/guides/upstream/AGENTS.md +0 -298
- package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +0 -316
- package/dist/agentic/guides/upstream/manifest.json +0 -8
- package/dist/agentic/shared/ai/harness/README.md +0 -50
- package/dist/agentic/shared/ai/harness/RELEASE.md +0 -57
- package/dist/agentic/shared/ai/harness/cases.json +0 -13680
- package/dist/agentic/shared/ai/harness/cases.schema.json +0 -133
- package/dist/agentic/shared/ai/harness/fixtures/index.json +0 -49
- package/dist/agentic/shared/ai/harness/fixtures/seeds.json +0 -162
- package/dist/agentic/shared/ai/harness/generated-code-review-policy.md +0 -21
- package/dist/agentic/shared/ai/harness/generated-code-review-response.schema.json +0 -96
- package/dist/agentic/shared/ai/harness/generated-code-review-result.schema.json +0 -172
- package/dist/agentic/shared/ai/harness/release-matrix.json +0 -158
- package/dist/agentic/shared/ai/harness/release-result.schema.json +0 -219
- package/dist/agentic/shared/ai/harness/result.schema.json +0 -76
- package/dist/agentic/shared/ai/harness/routing-response.schema.json +0 -12
- package/dist/agentic/shared/ai/harness/target-validation-result.schema.json +0 -73
- package/dist/agentic/shared/ai/harness/validators.json +0 -78
- package/dist/agentic/shared/ai/harness/writable-ast-oracles.mjs +0 -2121
- package/dist/agentic/shared/ai/harness/writable-behavior-oracles.mjs +0 -1096
- package/dist/agentic/shared/ai/lessons/_template.md +0 -16
- package/dist/agentic/shared/ai/review-checklist.md +0 -36
- package/dist/agentic/shared/ai/skills/om-auto-implement-spec/SKILL.md +0 -21
- package/dist/agentic/shared/ai/skills/om-auto-upgrade-0.6.6-to-0.6.7/SKILL.md +0 -98
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/crud-surfaces.md +0 -16
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/frontend-and-design-system.md +0 -53
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/page-and-navigation.md +0 -13
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/quality-states.md +0 -11
- package/dist/agentic/shared/ai/skills/om-build-workflow/SKILL.md +0 -30
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/activity-contracts.md +0 -12
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/durability-and-progress.md +0 -13
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/workflow-design.md +0 -14
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/SKILL.md +0 -28
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/attachments-and-overrides.md +0 -12
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/module-agents-and-tools.md +0 -22
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/orchestrator-agents.md +0 -12
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/surface-selector.md +0 -19
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/integrity-and-concurrency.md +0 -19
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/migration-workflow.md +0 -13
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/schema-design.md +0 -14
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/sensitive-data.md +0 -10
- package/dist/agentic/shared/ai/skills/om-eject-and-customize/references/decision-and-procedure.md +0 -17
- package/dist/agentic/shared/ai/skills/om-evolve-harness/SKILL.md +0 -29
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-template.md +0 -100
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-workflow.md +0 -16
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/owner-selection.md +0 -17
- package/dist/agentic/shared/ai/skills/om-framework-context/SKILL.md +0 -25
- package/dist/agentic/shared/ai/skills/om-framework-context/references/resolver-procedure.md +0 -11
- package/dist/agentic/shared/ai/skills/om-framework-context/references/skew-and-escalation.md +0 -13
- package/dist/agentic/shared/ai/skills/om-help/references/delivery-workflows.md +0 -18
- package/dist/agentic/shared/ai/skills/om-help/references/task-families.md +0 -20
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/phases-and-gates.md +0 -33
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/planning-and-progress.md +0 -40
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/report-templates.md +0 -27
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/spec-resolution.md +0 -24
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/package-and-activation.md +0 -16
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/provider-families.md +0 -14
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/security-and-reliability.md +0 -15
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/sync-and-files.md +0 -12
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/SKILL.md +0 -34
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/agents/openai.yaml +0 -4
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/agentic-setup.md +0 -11
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/input-normalization.md +0 -31
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/judge-workflow.md +0 -39
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/report-template.md +0 -43
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/rules.md +0 -11
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/api-and-domain.md +0 -19
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/business-one-shot-blueprints.md +0 -172
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/data-and-migrations.md +0 -12
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/discovery-surface-catalog.md +0 -83
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/module-surfaces.md +0 -21
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/planning.md +0 -11
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/runtime-cache-and-queues.md +0 -22
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/verification.md +0 -13
- package/dist/agentic/shared/ai/skills/om-share-this-session/SKILL.md +0 -41
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/agentic-setup.md +0 -19
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/bundle-preparation.md +0 -44
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/consent-and-review.md +0 -39
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/publication.md +0 -20
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/report-templates.md +0 -57
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/rules.md +0 -11
- package/dist/agentic/shared/ai/skills/om-share-this-session/scripts/prepare-share-bundle.mjs +0 -486
- package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-branches.md +0 -18
- package/dist/agentic/shared/ai/skills/om-system-extension/references/mechanism-selector.md +0 -27
- package/dist/agentic/shared/ai/skills/om-system-extension/references/read-write-roundtrip.md +0 -13
- package/dist/agentic/shared/ai/skills/om-system-extension/references/unified-overrides.md +0 -41
- package/dist/agentic/shared/ai/skills/om-system-extension/references/verification.md +0 -11
- package/dist/agentic/shared/ai/skills/om-trim-unused-modules/references/dependency-and-redirect.md +0 -15
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnosis-map.md +0 -16
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/regression-oracles.md +0 -14
- package/dist/agentic/shared/scripts/agent-harness-tool-server.mjs +0 -187
- package/dist/agentic/shared/scripts/check-lessons.mjs +0 -178
- package/dist/agentic/shared/scripts/evaluate-agent-harness.mjs +0 -2958
- package/dist/agentic/shared/scripts/execution-sandbox.mjs +0 -329
- package/dist/agentic/shared/scripts/framework-context.mjs +0 -888
- package/dist/agentic/shared/scripts/install-skills.mjs +0 -1029
- package/dist/agentic/shared/scripts/prepare-agent-harness-fixture.mjs +0 -222
- package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +0 -1774
- package/dist/lib/generators/module-extension-facts.js +0 -1840
- package/dist/lib/generators/module-extension-facts.js.map +0 -7
- package/dist/lib/generators/module-fact-sources.js +0 -70
- package/dist/lib/generators/module-fact-sources.js.map +0 -7
- package/dist/lib/generators/module-override-targets.js +0 -688
- package/dist/lib/generators/module-override-targets.js.map +0 -7
- package/dist/lib/load-env.js +0 -24
- package/dist/lib/load-env.js.map +0 -7
- package/dist/lib/telemetry-init.js +0 -358
- package/dist/lib/telemetry-init.js.map +0 -7
- package/src/lib/__tests__/agentic-setup.ownership.test.ts +0 -386
- package/src/lib/__tests__/injection-widget-id-validation.test.ts +0 -184
- package/src/lib/__tests__/load-env.test.ts +0 -65
- package/src/lib/__tests__/telemetry-init.test.ts +0 -298
- package/src/lib/generators/__tests__/activation-adapter-coverage.test.ts +0 -92
- package/src/lib/generators/__tests__/module-extension-activations.test.ts +0 -762
- package/src/lib/generators/__tests__/module-extension-facts.test.ts +0 -404
- package/src/lib/generators/__tests__/module-facts.extension-hosts.test.ts +0 -108
- package/src/lib/generators/__tests__/module-facts.owned-contracts.test.ts +0 -561
- package/src/lib/generators/__tests__/module-facts.source-links.test.ts +0 -119
- package/src/lib/generators/__tests__/module-override-targets.roundtrip.test.ts +0 -149
- package/src/lib/generators/__tests__/module-override-targets.test.ts +0 -304
- package/src/lib/generators/module-extension-facts.ts +0 -2365
- package/src/lib/generators/module-fact-sources.ts +0 -108
- package/src/lib/generators/module-override-targets.ts +0 -863
- package/src/lib/load-env.ts +0 -30
- package/src/lib/telemetry-init.ts +0 -461
package/src/lib/agentic-setup.ts
CHANGED
|
@@ -6,35 +6,16 @@
|
|
|
6
6
|
* This module reads those files at runtime — no embedded string constants.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
chmodSync,
|
|
11
|
-
copyFileSync,
|
|
12
|
-
existsSync,
|
|
13
|
-
lstatSync,
|
|
14
|
-
mkdirSync,
|
|
15
|
-
mkdtempSync,
|
|
16
|
-
readFileSync,
|
|
17
|
-
readdirSync,
|
|
18
|
-
realpathSync,
|
|
19
|
-
renameSync,
|
|
20
|
-
rmSync,
|
|
21
|
-
statSync,
|
|
22
|
-
writeFileSync,
|
|
23
|
-
} from 'node:fs'
|
|
24
|
-
import { createHash } from 'node:crypto'
|
|
9
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync, symlinkSync, lstatSync, unlinkSync, readdirSync } from 'node:fs'
|
|
25
10
|
import { spawnSync } from 'node:child_process'
|
|
26
|
-
import {
|
|
27
|
-
import { join, dirname, basename, relative, resolve, sep } from 'node:path'
|
|
11
|
+
import { join, dirname, basename } from 'node:path'
|
|
28
12
|
import { fileURLToPath } from 'node:url'
|
|
29
13
|
import { Project, SyntaxKind } from 'ts-morph'
|
|
30
14
|
|
|
31
|
-
const
|
|
32
|
-
// In the built output (dist/lib/agentic-setup.js),
|
|
15
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
16
|
+
// In the built output (dist/lib/agentic-setup.js), __dirname is dist/lib/.
|
|
33
17
|
// agentic/ is copied to dist/agentic/ by build.mjs.
|
|
34
|
-
const
|
|
35
|
-
const AGENTIC_DIR = existsSync(bundledAgenticDir)
|
|
36
|
-
? bundledAgenticDir
|
|
37
|
-
: join(moduleDir, '..', '..', '..', 'create-app', 'agentic')
|
|
18
|
+
const AGENTIC_DIR = join(__dirname, '..', 'agentic')
|
|
38
19
|
const GUIDES_DIR = join(AGENTIC_DIR, 'guides')
|
|
39
20
|
|
|
40
21
|
type AskFn = (question: string) => Promise<string>
|
|
@@ -42,7 +23,6 @@ type AskFn = (question: string) => Promise<string>
|
|
|
42
23
|
interface AgenticSetupOptions {
|
|
43
24
|
tool?: string
|
|
44
25
|
force?: boolean
|
|
45
|
-
updateHarness?: boolean
|
|
46
26
|
}
|
|
47
27
|
|
|
48
28
|
interface AgenticConfig {
|
|
@@ -50,19 +30,6 @@ interface AgenticConfig {
|
|
|
50
30
|
targetDir: string
|
|
51
31
|
}
|
|
52
32
|
|
|
53
|
-
interface HarnessManifestFile {
|
|
54
|
-
path: string
|
|
55
|
-
sha256: string
|
|
56
|
-
source: string
|
|
57
|
-
userEditable: boolean
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
interface HarnessManifest {
|
|
61
|
-
version: number
|
|
62
|
-
generator: string
|
|
63
|
-
files: HarnessManifestFile[]
|
|
64
|
-
}
|
|
65
|
-
|
|
66
33
|
// ─── Helpers ─────────────────────────────────────────────────────────────
|
|
67
34
|
|
|
68
35
|
function resolvePlaceholders(content: string, config: AgenticConfig): string {
|
|
@@ -92,14 +59,14 @@ function copyFile(srcDir: string, srcRelative: string, destPath: string): void {
|
|
|
92
59
|
// AST-parse the static `enabledModules` array literal in the app's src/modules.ts
|
|
93
60
|
// and collect each entry's `id`. Only the static literal is read (conditional
|
|
94
61
|
// .push()/spread entries are intentionally not seen — see spec D6).
|
|
95
|
-
function readEnabledModuleIds(modulesPath: string):
|
|
96
|
-
if (!existsSync(modulesPath)) return
|
|
62
|
+
function readEnabledModuleIds(modulesPath: string): string[] {
|
|
63
|
+
if (!existsSync(modulesPath)) return []
|
|
97
64
|
try {
|
|
98
65
|
const project = new Project({ useInMemoryFileSystem: true })
|
|
99
66
|
const sourceFile = project.createSourceFile('modules.ts', readFileSync(modulesPath, 'utf-8'))
|
|
100
67
|
const declaration = sourceFile.getVariableDeclaration('enabledModules')
|
|
101
68
|
const arrayLiteral = declaration?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression)
|
|
102
|
-
if (!arrayLiteral) return
|
|
69
|
+
if (!arrayLiteral) return []
|
|
103
70
|
const ids: string[] = []
|
|
104
71
|
for (const element of arrayLiteral.getElements()) {
|
|
105
72
|
const objectLiteral = element.asKind(SyntaxKind.ObjectLiteralExpression)
|
|
@@ -108,9 +75,9 @@ function readEnabledModuleIds(modulesPath: string): { parsed: boolean; ids: stri
|
|
|
108
75
|
const idValue = idProperty?.getInitializerIfKind(SyntaxKind.StringLiteral)?.getLiteralValue()
|
|
109
76
|
if (idValue) ids.push(idValue)
|
|
110
77
|
}
|
|
111
|
-
return
|
|
78
|
+
return ids
|
|
112
79
|
} catch {
|
|
113
|
-
return
|
|
80
|
+
return []
|
|
114
81
|
}
|
|
115
82
|
}
|
|
116
83
|
|
|
@@ -125,23 +92,48 @@ function selectModuleFactSheets(targetDir: string, modulesSubdir: string): strin
|
|
|
125
92
|
.map((file) => file.replace(/\.md$/, ''))
|
|
126
93
|
: []
|
|
127
94
|
if (available.length === 0) return []
|
|
128
|
-
const
|
|
129
|
-
if (!parsed.parsed) return available
|
|
130
|
-
const enabled = new Set(parsed.ids)
|
|
95
|
+
const enabled = new Set(readEnabledModuleIds(join(targetDir, 'src', 'modules.ts')))
|
|
131
96
|
const selected = available.filter((moduleId) => enabled.has(moduleId))
|
|
132
|
-
return selected
|
|
97
|
+
return selected.length > 0 ? selected : available
|
|
133
98
|
}
|
|
134
99
|
|
|
135
100
|
const MODULE_GUIDES_START = '<!-- om:module-guides:start -->'
|
|
136
101
|
const MODULE_GUIDES_END = '<!-- om:module-guides:end -->'
|
|
137
102
|
|
|
138
|
-
|
|
103
|
+
// Read each module's guide label from the bundled `module-facts.json` (emitted by
|
|
104
|
+
// build.mjs from the generator's extraction of each module's own `metadata`). The
|
|
105
|
+
// label falls back description → title → generic, so the CLI never re-declares
|
|
106
|
+
// specific module names or descriptions. A missing/malformed sidecar degrades to an
|
|
107
|
+
// empty map (generic labels), never a throw.
|
|
108
|
+
function readModuleGuideLabels(guidesDir: string): Record<string, string> {
|
|
109
|
+
const factsPath = join(guidesDir, 'module-facts.json')
|
|
110
|
+
if (!existsSync(factsPath)) return {}
|
|
111
|
+
try {
|
|
112
|
+
const parsed = JSON.parse(readFileSync(factsPath, 'utf-8')) as Record<
|
|
113
|
+
string,
|
|
114
|
+
{ description?: unknown; title?: unknown }
|
|
115
|
+
>
|
|
116
|
+
const labels: Record<string, string> = {}
|
|
117
|
+
for (const [moduleId, entry] of Object.entries(parsed)) {
|
|
118
|
+
const label =
|
|
119
|
+
(entry && typeof entry.description === 'string' && entry.description) ||
|
|
120
|
+
(entry && typeof entry.title === 'string' && entry.title) ||
|
|
121
|
+
''
|
|
122
|
+
if (label) labels[moduleId] = label
|
|
123
|
+
}
|
|
124
|
+
return labels
|
|
125
|
+
} catch {
|
|
126
|
+
return {}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function renderModuleGuidesBlock(selected: string[], labels: Record<string, string>): string {
|
|
139
131
|
if (selected.length === 0) return '_No module fact-sheets are bundled for this app._'
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
].join('\n')
|
|
132
|
+
const rows = selected.map((moduleId) => {
|
|
133
|
+
const label = labels[moduleId] ?? `Use the ${moduleId} module`
|
|
134
|
+
return `| ${label} | \`.ai/guides/modules/${moduleId}.md\` |`
|
|
135
|
+
})
|
|
136
|
+
return ['| Task | Load |', '|---|---|', ...rows].join('\n')
|
|
145
137
|
}
|
|
146
138
|
|
|
147
139
|
// Regenerate the marker-delimited Module-Specific Guides block in the written
|
|
@@ -150,6 +142,7 @@ export function renderModuleGuidesBlock(selected: string[]): string {
|
|
|
150
142
|
function injectModuleGuides(
|
|
151
143
|
agentsMdPath: string,
|
|
152
144
|
selected: string[],
|
|
145
|
+
labels: Record<string, string> = {},
|
|
153
146
|
): void {
|
|
154
147
|
if (!existsSync(agentsMdPath)) return
|
|
155
148
|
const content = readFileSync(agentsMdPath, 'utf-8')
|
|
@@ -163,428 +156,188 @@ function injectModuleGuides(
|
|
|
163
156
|
}
|
|
164
157
|
const before = content.slice(0, startIndex + MODULE_GUIDES_START.length)
|
|
165
158
|
const after = content.slice(endIndex)
|
|
166
|
-
const next = `${before}\n${renderModuleGuidesBlock(selected)}\n${after}`
|
|
159
|
+
const next = `${before}\n${renderModuleGuidesBlock(selected, labels)}\n${after}`
|
|
167
160
|
if (next !== content) writeFileSync(agentsMdPath, next)
|
|
168
161
|
}
|
|
169
162
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
function isTextAsset(path: string): boolean {
|
|
173
|
-
const dot = path.lastIndexOf('.')
|
|
174
|
-
return dot === -1 || TEXT_EXTENSIONS.has(path.slice(dot))
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
function listFiles(root: string): string[] {
|
|
178
|
-
if (!existsSync(root)) return []
|
|
179
|
-
const files: string[] = []
|
|
180
|
-
for (const entry of readdirSync(root, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
181
|
-
const absolute = join(root, entry.name)
|
|
182
|
-
if (entry.isDirectory()) files.push(...listFiles(absolute))
|
|
183
|
-
else if (entry.isFile()) files.push(absolute)
|
|
184
|
-
}
|
|
185
|
-
return files
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function copyTree(sourceRoot: string, destinationRoot: string, config: AgenticConfig): void {
|
|
189
|
-
for (const sourcePath of listFiles(sourceRoot)) {
|
|
190
|
-
const destinationPath = join(destinationRoot, relative(sourceRoot, sourcePath))
|
|
191
|
-
ensureDir(destinationPath)
|
|
192
|
-
if (isTextAsset(sourcePath)) {
|
|
193
|
-
writeFileSync(destinationPath, resolvePlaceholders(readFileSync(sourcePath, 'utf8'), config))
|
|
194
|
-
} else {
|
|
195
|
-
copyFileSync(sourcePath, destinationPath)
|
|
196
|
-
}
|
|
197
|
-
if (process.platform !== 'win32') chmodSync(destinationPath, statSync(sourcePath).mode & 0o777)
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function hashFile(path: string): string {
|
|
202
|
-
return createHash('sha256').update(readFileSync(path)).digest('hex')
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
function canonicalHarnessRoot(root: string): string {
|
|
206
|
-
const resolved = resolve(root)
|
|
207
|
-
if (!existsSync(resolved)) {
|
|
208
|
-
throw new Error(`Harness root must be an existing directory: ${resolved}`)
|
|
209
|
-
}
|
|
210
|
-
const canonical = realpathSync(resolved)
|
|
211
|
-
const entry = lstatSync(canonical, { throwIfNoEntry: false })
|
|
212
|
-
if (!entry || !entry.isDirectory()) {
|
|
213
|
-
throw new Error(`Harness root must be an existing directory: ${resolved}`)
|
|
214
|
-
}
|
|
215
|
-
return canonical
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Validate a managed path without following any link below the canonical app
|
|
220
|
-
* root. A lexical containment check alone is insufficient: `app/.ai -> /tmp`
|
|
221
|
-
* would otherwise make an apparently safe update write outside the app.
|
|
222
|
-
*/
|
|
223
|
-
function assertManagedPath(root: string, path: string, options: { leaf?: 'file' | 'any' } = {}): void {
|
|
224
|
-
const absolutePath = resolve(path)
|
|
225
|
-
const normalizedRelative = relative(root, absolutePath)
|
|
226
|
-
if (
|
|
227
|
-
normalizedRelative === '..' ||
|
|
228
|
-
normalizedRelative.startsWith(`..${sep}`)
|
|
229
|
-
) {
|
|
230
|
-
throw new Error(`Harness-managed path escapes its root: ${absolutePath}`)
|
|
231
|
-
}
|
|
232
|
-
if (normalizedRelative === '') return
|
|
233
|
-
|
|
234
|
-
const components = normalizedRelative.split(sep).filter(Boolean)
|
|
235
|
-
let current = root
|
|
236
|
-
for (let index = 0; index < components.length; index += 1) {
|
|
237
|
-
current = join(current, components[index])
|
|
238
|
-
const entry = lstatSync(current, { throwIfNoEntry: false })
|
|
239
|
-
if (!entry) return
|
|
240
|
-
if (entry.isSymbolicLink()) {
|
|
241
|
-
throw new Error(`Harness-managed path contains a symbolic-link component: ${current}`)
|
|
242
|
-
}
|
|
243
|
-
const isLeaf = index === components.length - 1
|
|
244
|
-
if (!isLeaf && !entry.isDirectory()) {
|
|
245
|
-
throw new Error(`Harness-managed path component is not a directory: ${current}`)
|
|
246
|
-
}
|
|
247
|
-
if (isLeaf && options.leaf === 'file' && !entry.isFile()) {
|
|
248
|
-
throw new Error(`Harness-managed file is not a regular file: ${current}`)
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function ensureManagedParent(root: string, filePath: string): void {
|
|
254
|
-
const parent = dirname(filePath)
|
|
255
|
-
const normalizedRelative = relative(root, parent)
|
|
256
|
-
if (normalizedRelative === '..' || normalizedRelative.startsWith(`..${sep}`)) {
|
|
257
|
-
throw new Error(`Harness-managed path escapes its root: ${filePath}`)
|
|
258
|
-
}
|
|
259
|
-
let current = root
|
|
260
|
-
for (const component of normalizedRelative.split(sep).filter(Boolean)) {
|
|
261
|
-
assertManagedPath(root, current)
|
|
262
|
-
current = join(current, component)
|
|
263
|
-
const entry = lstatSync(current, { throwIfNoEntry: false })
|
|
264
|
-
if (!entry) mkdirSync(current)
|
|
265
|
-
const created = lstatSync(current, { throwIfNoEntry: false })
|
|
266
|
-
if (!created || created.isSymbolicLink() || !created.isDirectory()) {
|
|
267
|
-
throw new Error(`Harness-managed path component is not a real directory: ${current}`)
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
function harnessGeneratorId(): string {
|
|
273
|
-
try {
|
|
274
|
-
const upstream = JSON.parse(readFileSync(join(GUIDES_DIR, 'upstream', 'manifest.json'), 'utf8')) as {
|
|
275
|
-
generator?: unknown
|
|
276
|
-
}
|
|
277
|
-
const generator = typeof upstream.generator === 'string' ? upstream.generator : ''
|
|
278
|
-
const version = generator.slice(generator.lastIndexOf('@') + 1)
|
|
279
|
-
if (version && version !== generator) return `open-mercato-agentic@${version}`
|
|
280
|
-
} catch {
|
|
281
|
-
// Source-mode tests may not have built upstream snapshots yet.
|
|
282
|
-
}
|
|
283
|
-
return 'open-mercato-agentic@unknown'
|
|
284
|
-
}
|
|
163
|
+
// ─── Generators ──────────────────────────────────────────────────────────
|
|
285
164
|
|
|
286
|
-
function
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
external?: { skills?: unknown }
|
|
290
|
-
}
|
|
291
|
-
return new Set(Array.isArray(tiers.external?.skills) ? tiers.external.skills.filter((name): name is string => typeof name === 'string') : [])
|
|
292
|
-
} catch {
|
|
293
|
-
return new Set()
|
|
294
|
-
}
|
|
295
|
-
}
|
|
165
|
+
function generateShared(config: AgenticConfig): void {
|
|
166
|
+
const { targetDir } = config
|
|
167
|
+
const srcDir = join(AGENTIC_DIR, 'shared')
|
|
296
168
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
ensureManagedParent(managedRoot, destinationPath)
|
|
301
|
-
} else {
|
|
302
|
-
ensureDir(destinationPath)
|
|
303
|
-
}
|
|
304
|
-
const temporaryPath = `${destinationPath}.tmp-${process.pid}-${Date.now()}`
|
|
305
|
-
try {
|
|
306
|
-
if (managedRoot) assertManagedPath(managedRoot, temporaryPath, { leaf: 'file' })
|
|
307
|
-
copyFileSync(sourcePath, temporaryPath)
|
|
308
|
-
if (process.platform !== 'win32') chmodSync(temporaryPath, statSync(sourcePath).mode & 0o777)
|
|
309
|
-
if (managedRoot) {
|
|
310
|
-
assertManagedPath(managedRoot, dirname(destinationPath))
|
|
311
|
-
assertManagedPath(managedRoot, destinationPath, { leaf: 'file' })
|
|
312
|
-
assertManagedPath(managedRoot, temporaryPath, { leaf: 'file' })
|
|
313
|
-
}
|
|
314
|
-
renameSync(temporaryPath, destinationPath)
|
|
315
|
-
} finally {
|
|
316
|
-
if (!managedRoot || !lstatSync(temporaryPath, { throwIfNoEntry: false })?.isSymbolicLink()) {
|
|
317
|
-
rmSync(temporaryPath, { force: true })
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
}
|
|
169
|
+
// Resolve which per-module fact-sheets this app gets (enabled ∩ bundled allowlist).
|
|
170
|
+
const selectedModules = selectModuleFactSheets(targetDir, join(GUIDES_DIR, 'modules'))
|
|
171
|
+
const moduleGuideLabels = readModuleGuideLabels(GUIDES_DIR)
|
|
321
172
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
173
|
+
// AGENTS.md
|
|
174
|
+
writeTemplate(srcDir, 'AGENTS.md.template', join(targetDir, 'AGENTS.md'), config)
|
|
175
|
+
injectModuleGuides(join(targetDir, 'AGENTS.md'), selectedModules, moduleGuideLabels)
|
|
176
|
+
|
|
177
|
+
// .ai/ structure
|
|
178
|
+
writeTemplate(srcDir, 'ai/specs/README.md', join(targetDir, '.ai', 'specs', 'README.md'), config)
|
|
179
|
+
copyFile(srcDir, 'ai/specs/SPEC-000-template.md', join(targetDir, '.ai', 'specs', 'SPEC-000-template.md'))
|
|
180
|
+
copyFile(srcDir, 'ai/lessons.md', join(targetDir, '.ai', 'lessons.md'))
|
|
181
|
+
|
|
182
|
+
// .ai/skills/ — the shared skills-mixin manifest + tracker + external installer.
|
|
183
|
+
// Skills owned by the external open-mercato/skills collection (code review, spec
|
|
184
|
+
// writing, integration tests, prepare-issue, the auto-* PR family) are NOT copied
|
|
185
|
+
// here; the user installs them with `yarn install-skills` (npx skills add). Only
|
|
186
|
+
// standalone-only + kept-local skills and repo-local override folders are copied.
|
|
187
|
+
copyFile(srcDir, 'ai/skills/tiers.json', join(targetDir, '.ai', 'skills', 'tiers.json'))
|
|
188
|
+
copyFile(srcDir, 'ai/skills/tiers.schema.json', join(targetDir, '.ai', 'skills', 'tiers.schema.json'))
|
|
189
|
+
copyFile(srcDir, 'ai/agentic.config.json', join(targetDir, '.ai', 'agentic.config.json'))
|
|
190
|
+
copyFile(srcDir, 'ai/trackers/github.md', join(targetDir, '.ai', 'trackers', 'github.md'))
|
|
191
|
+
copyFile(srcDir, 'scripts/install-skills.sh', join(targetDir, 'scripts', 'install-skills.sh'))
|
|
192
|
+
|
|
193
|
+
copyFile(
|
|
194
|
+
srcDir,
|
|
195
|
+
'ai/skills/om-backend-ui-design/SKILL.md',
|
|
196
|
+
join(targetDir, '.ai', 'skills', 'om-backend-ui-design', 'SKILL.md'),
|
|
197
|
+
)
|
|
198
|
+
copyFile(
|
|
199
|
+
srcDir,
|
|
200
|
+
'ai/skills/om-backend-ui-design/references/ui-components.md',
|
|
201
|
+
join(targetDir, '.ai', 'skills', 'om-backend-ui-design', 'references', 'ui-components.md'),
|
|
202
|
+
)
|
|
203
|
+
copyFile(srcDir, 'ai/skills/om-integration-builder/SKILL.md', join(targetDir, '.ai', 'skills', 'om-integration-builder', 'SKILL.md'))
|
|
204
|
+
if (existsSync(join(srcDir, 'ai', 'skills', 'om-integration-builder', 'STANDALONE.md'))) {
|
|
205
|
+
copyFile(
|
|
206
|
+
srcDir,
|
|
207
|
+
'ai/skills/om-integration-builder/STANDALONE.md',
|
|
208
|
+
join(targetDir, '.ai', 'skills', 'om-integration-builder', 'STANDALONE.md'),
|
|
209
|
+
)
|
|
343
210
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
return null
|
|
211
|
+
copyFile(
|
|
212
|
+
srcDir,
|
|
213
|
+
'ai/skills/om-integration-builder/references/adapter-contracts.md',
|
|
214
|
+
join(targetDir, '.ai', 'skills', 'om-integration-builder', 'references', 'adapter-contracts.md'),
|
|
215
|
+
)
|
|
216
|
+
if (existsSync(join(srcDir, 'ai', 'skills', 'om-integration-builder', 'STANDALONE.md'))) {
|
|
217
|
+
copyFile(
|
|
218
|
+
srcDir,
|
|
219
|
+
'ai/skills/om-integration-builder/STANDALONE.md',
|
|
220
|
+
join(targetDir, '.ai', 'skills', 'om-integration-builder', 'STANDALONE.md'),
|
|
221
|
+
)
|
|
356
222
|
}
|
|
357
|
-
return absolutePath
|
|
358
|
-
}
|
|
359
223
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
224
|
+
copyFile(
|
|
225
|
+
srcDir,
|
|
226
|
+
'ai/skills/om-system-extension/SKILL.md',
|
|
227
|
+
join(targetDir, '.ai', 'skills', 'om-system-extension', 'SKILL.md'),
|
|
228
|
+
)
|
|
229
|
+
copyFile(
|
|
230
|
+
srcDir,
|
|
231
|
+
'ai/skills/om-system-extension/references/extension-contracts.md',
|
|
232
|
+
join(targetDir, '.ai', 'skills', 'om-system-extension', 'references', 'extension-contracts.md'),
|
|
233
|
+
)
|
|
363
234
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
)
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
typeof entry.path !== 'string' ||
|
|
380
|
-
typeof entry.sha256 !== 'string' ||
|
|
381
|
-
!/^[a-f0-9]{64}$/.test(entry.sha256) ||
|
|
382
|
-
typeof entry.source !== 'string' ||
|
|
383
|
-
typeof entry.userEditable !== 'boolean'
|
|
384
|
-
) {
|
|
385
|
-
return null
|
|
386
|
-
}
|
|
387
|
-
files.push({ ...entry, path: normalizeManifestRelativePath(entry.path) })
|
|
388
|
-
}
|
|
389
|
-
return { version: parsed.version, generator: parsed.generator, files }
|
|
390
|
-
} catch {
|
|
391
|
-
return null
|
|
392
|
-
}
|
|
393
|
-
}
|
|
235
|
+
copyFile(
|
|
236
|
+
srcDir,
|
|
237
|
+
'ai/skills/om-module-scaffold/SKILL.md',
|
|
238
|
+
join(targetDir, '.ai', 'skills', 'om-module-scaffold', 'SKILL.md'),
|
|
239
|
+
)
|
|
240
|
+
copyFile(
|
|
241
|
+
srcDir,
|
|
242
|
+
'ai/skills/om-module-scaffold/references/naming-conventions.md',
|
|
243
|
+
join(targetDir, '.ai', 'skills', 'om-module-scaffold', 'references', 'naming-conventions.md'),
|
|
244
|
+
)
|
|
245
|
+
copyFile(
|
|
246
|
+
srcDir,
|
|
247
|
+
'ai/skills/om-module-scaffold/references/navigation-patterns.md',
|
|
248
|
+
join(targetDir, '.ai', 'skills', 'om-module-scaffold', 'references', 'navigation-patterns.md'),
|
|
249
|
+
)
|
|
394
250
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
251
|
+
copyFile(
|
|
252
|
+
srcDir,
|
|
253
|
+
'ai/skills/om-troubleshooter/SKILL.md',
|
|
254
|
+
join(targetDir, '.ai', 'skills', 'om-troubleshooter', 'SKILL.md'),
|
|
255
|
+
)
|
|
256
|
+
copyFile(
|
|
257
|
+
srcDir,
|
|
258
|
+
'ai/skills/om-troubleshooter/references/diagnostic-commands.md',
|
|
259
|
+
join(targetDir, '.ai', 'skills', 'om-troubleshooter', 'references', 'diagnostic-commands.md'),
|
|
260
|
+
)
|
|
398
261
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
const paths = new Set<string>([
|
|
404
|
-
join(targetDir, 'AGENTS.md'),
|
|
405
|
-
...targetPathsForTree(join(srcDir, 'ai'), join(targetDir, '.ai')),
|
|
406
|
-
...targetPathsForTree(join(srcDir, 'scripts'), join(targetDir, 'scripts')),
|
|
407
|
-
])
|
|
408
|
-
for (const file of readdirSync(GUIDES_DIR)) {
|
|
409
|
-
if (file.endsWith('.md') || file === 'module-facts.json') paths.add(join(targetDir, '.ai', 'guides', file))
|
|
410
|
-
}
|
|
411
|
-
for (const file of listFiles(join(GUIDES_DIR, 'upstream'))) {
|
|
412
|
-
paths.add(join(targetDir, '.ai', 'guides', 'upstream', relative(join(GUIDES_DIR, 'upstream'), file)))
|
|
413
|
-
}
|
|
414
|
-
for (const moduleId of selectedModules) paths.add(join(targetDir, '.ai', 'guides', 'modules', `${moduleId}.md`))
|
|
415
|
-
if (selectedTools.includes('claude-code')) {
|
|
416
|
-
paths.add(join(targetDir, 'CLAUDE.md'))
|
|
417
|
-
paths.add(join(targetDir, '.claude', 'settings.json'))
|
|
418
|
-
paths.add(join(targetDir, '.claude', 'hooks', 'entity-migration-check.ts'))
|
|
419
|
-
paths.add(join(targetDir, '.mcp.json.example'))
|
|
420
|
-
}
|
|
421
|
-
if (selectedTools.includes('codex')) paths.add(join(targetDir, '.codex', 'mcp.json.example'))
|
|
422
|
-
if (selectedTools.includes('cursor')) {
|
|
423
|
-
for (const file of listFiles(join(AGENTIC_DIR, 'cursor'))) {
|
|
424
|
-
const rel = relative(join(AGENTIC_DIR, 'cursor'), file)
|
|
425
|
-
paths.add(join(targetDir, '.cursor', rel))
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
const manifestPath = join(targetDir, '.ai', 'harness', 'manifest.json')
|
|
429
|
-
const externalSkills = externalSkillNames(targetDir)
|
|
430
|
-
paths.delete(manifestPath)
|
|
431
|
-
const files = [...paths]
|
|
432
|
-
.filter((path) => existsSync(path))
|
|
433
|
-
.sort((left, right) => left.localeCompare(right))
|
|
434
|
-
.map((path) => {
|
|
435
|
-
const relativePath = normalizeManifestRelativePath(relative(targetDir, path))
|
|
436
|
-
const skillName = relativePath.match(/^\.ai\/skills\/([^/]+)\//)?.[1]
|
|
437
|
-
return {
|
|
438
|
-
path: relativePath,
|
|
439
|
-
sha256: hashFile(path),
|
|
440
|
-
source: skillName ? (externalSkills.has(skillName) ? 'external-override' : 'local-skill') : 'generated',
|
|
441
|
-
userEditable:
|
|
442
|
-
relativePath === 'AGENTS.md'
|
|
443
|
-
|| relativePath === '.ai/agentic.config.json'
|
|
444
|
-
|| relativePath === '.ai/lessons.md'
|
|
445
|
-
|| relativePath.startsWith('.ai/lessons/'),
|
|
446
|
-
}
|
|
447
|
-
})
|
|
448
|
-
atomicWriteFile(
|
|
449
|
-
manifestPath,
|
|
450
|
-
`${JSON.stringify({ version: 1, generator: harnessGeneratorId(), files }, null, 2)}\n`,
|
|
262
|
+
copyFile(
|
|
263
|
+
srcDir,
|
|
264
|
+
'ai/skills/om-eject-and-customize/SKILL.md',
|
|
265
|
+
join(targetDir, '.ai', 'skills', 'om-eject-and-customize', 'SKILL.md'),
|
|
451
266
|
)
|
|
452
|
-
}
|
|
453
267
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
destinationPath: string,
|
|
465
|
-
sourcePath: string,
|
|
466
|
-
relativePath: string,
|
|
467
|
-
): string {
|
|
468
|
-
for (let suffix = 1; ; suffix += 1) {
|
|
469
|
-
const label = suffix === 1 ? '.incoming' : `.incoming.${suffix}`
|
|
470
|
-
const candidatePath = `${destinationPath}${label}`
|
|
471
|
-
assertManagedPath(targetRoot, candidatePath, { leaf: 'file' })
|
|
472
|
-
if (!existsSync(candidatePath)) {
|
|
473
|
-
atomicCopyFile(sourcePath, candidatePath, targetRoot)
|
|
474
|
-
return `${relativePath}${label}`
|
|
475
|
-
}
|
|
476
|
-
if (hashFile(candidatePath) === hashFile(sourcePath)) return `${relativePath}${label}`
|
|
477
|
-
}
|
|
478
|
-
}
|
|
268
|
+
copyFile(
|
|
269
|
+
srcDir,
|
|
270
|
+
'ai/skills/om-data-model-design/SKILL.md',
|
|
271
|
+
join(targetDir, '.ai', 'skills', 'om-data-model-design', 'SKILL.md'),
|
|
272
|
+
)
|
|
273
|
+
copyFile(
|
|
274
|
+
srcDir,
|
|
275
|
+
'ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md',
|
|
276
|
+
join(targetDir, '.ai', 'skills', 'om-data-model-design', 'references', 'mikro-orm-cheatsheet.md'),
|
|
277
|
+
)
|
|
479
278
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
)
|
|
485
|
-
const targetRoot = canonicalHarnessRoot(targetDir)
|
|
486
|
-
const stagingRoot = canonicalHarnessRoot(stagingDir)
|
|
487
|
-
const targetManifestPath = join(targetRoot, '.ai', 'harness', 'manifest.json')
|
|
488
|
-
const stagingManifestPath = join(stagingRoot, '.ai', 'harness', 'manifest.json')
|
|
489
|
-
assertManagedPath(targetRoot, targetManifestPath, { leaf: 'file' })
|
|
490
|
-
assertManagedPath(stagingRoot, stagingManifestPath, { leaf: 'file' })
|
|
491
|
-
const candidateManifest = readHarnessManifest(stagingManifestPath)
|
|
492
|
-
if (!candidateManifest) {
|
|
493
|
-
throw new Error('Generated harness candidate has a missing or invalid ownership manifest.')
|
|
494
|
-
}
|
|
279
|
+
copyFile(
|
|
280
|
+
srcDir,
|
|
281
|
+
'ai/skills/om-implement-spec/SKILL.md',
|
|
282
|
+
join(targetDir, '.ai', 'skills', 'om-implement-spec', 'SKILL.md'),
|
|
283
|
+
)
|
|
495
284
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
if (!sourcePath || !destinationPath || !existsSync(sourcePath) || hashFile(sourcePath) !== entry.sha256) {
|
|
512
|
-
throw new Error(`Generated harness candidate is invalid for ${JSON.stringify(entry.path)}.`)
|
|
513
|
-
}
|
|
514
|
-
candidates.push({ entry, sourcePath, destinationPath })
|
|
515
|
-
}
|
|
285
|
+
copyFile(
|
|
286
|
+
srcDir,
|
|
287
|
+
'ai/skills/om-help/SKILL.md',
|
|
288
|
+
join(targetDir, '.ai', 'skills', 'om-help', 'SKILL.md'),
|
|
289
|
+
)
|
|
290
|
+
copyFile(
|
|
291
|
+
srcDir,
|
|
292
|
+
'ai/skills/om-help/references/skills-catalog.md',
|
|
293
|
+
join(targetDir, '.ai', 'skills', 'om-help', 'references', 'skills-catalog.md'),
|
|
294
|
+
)
|
|
295
|
+
copyFile(
|
|
296
|
+
srcDir,
|
|
297
|
+
'ai/skills/om-help/references/workflow-sequences.md',
|
|
298
|
+
join(targetDir, '.ai', 'skills', 'om-help', 'references', 'workflow-sequences.md'),
|
|
299
|
+
)
|
|
516
300
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
}
|
|
523
|
-
if (!existsSync(destinationPath)) {
|
|
524
|
-
atomicCopyFile(sourcePath, destinationPath, targetRoot)
|
|
525
|
-
continue
|
|
526
|
-
}
|
|
301
|
+
copyFile(
|
|
302
|
+
srcDir,
|
|
303
|
+
'ai/skills/om-auto-upgrade-0.4.10-to-0.5.0/SKILL.md',
|
|
304
|
+
join(targetDir, '.ai', 'skills', 'om-auto-upgrade-0.4.10-to-0.5.0', 'SKILL.md'),
|
|
305
|
+
)
|
|
527
306
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
307
|
+
// Slim repo-local OVERRIDE folders (SKILL.md only) for the external auto-* PR
|
|
308
|
+
// family + single autofix skill. The workflow bodies live in open-mercato/skills
|
|
309
|
+
// (installed via `yarn install-skills`); these overrides adjust them for a
|
|
310
|
+
// standalone app and are read on top of the external skill's built-in workflow.
|
|
311
|
+
// om-prepare-test-env's override carries environment knowledge (cross-platform
|
|
312
|
+
// mercato CLI runner commands) rather than tracker adjustments.
|
|
313
|
+
for (const autoSkill of [
|
|
314
|
+
'om-auto-create-pr',
|
|
315
|
+
'om-auto-continue-pr',
|
|
316
|
+
'om-auto-create-pr-loop',
|
|
317
|
+
'om-auto-continue-pr-loop',
|
|
318
|
+
'om-auto-review-pr',
|
|
319
|
+
'om-auto-fix-issue',
|
|
320
|
+
'om-prepare-test-env',
|
|
321
|
+
]) {
|
|
322
|
+
if (!existsSync(join(srcDir, 'ai', 'skills', autoSkill, 'SKILL.md'))) {
|
|
532
323
|
continue
|
|
533
324
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
const retainedRetiredEntries: HarnessManifestFile[] = []
|
|
540
|
-
for (const previousEntry of previousManifest?.files ?? []) {
|
|
541
|
-
if (candidatePaths.has(previousEntry.path)) continue
|
|
542
|
-
const destinationPath = resolveManifestPath(targetRoot, previousEntry.path)
|
|
543
|
-
if (!destinationPath || !existsSync(destinationPath)) continue
|
|
544
|
-
assertManagedPath(targetRoot, destinationPath, { leaf: 'file' })
|
|
545
|
-
let unchanged = false
|
|
546
|
-
try {
|
|
547
|
-
unchanged = hashFile(destinationPath) === previousEntry.sha256
|
|
548
|
-
} catch {
|
|
549
|
-
// A user may replace a generated file with another filesystem object.
|
|
550
|
-
// Preserve it and retain the ownership tombstone for a later review.
|
|
551
|
-
}
|
|
552
|
-
if (unchanged) {
|
|
553
|
-
assertManagedPath(targetRoot, dirname(destinationPath))
|
|
554
|
-
assertManagedPath(targetRoot, destinationPath, { leaf: 'file' })
|
|
555
|
-
rmSync(destinationPath, { force: true })
|
|
556
|
-
} else {
|
|
557
|
-
retainedRetiredEntries.push(previousEntry)
|
|
558
|
-
conflicts.push({ path: previousEntry.path, candidate: null })
|
|
559
|
-
}
|
|
325
|
+
copyFile(
|
|
326
|
+
srcDir,
|
|
327
|
+
`ai/skills/${autoSkill}/SKILL.md`,
|
|
328
|
+
join(targetDir, '.ai', 'skills', autoSkill, 'SKILL.md'),
|
|
329
|
+
)
|
|
560
330
|
}
|
|
561
331
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
files: [...candidateManifest.files, ...retainedRetiredEntries],
|
|
568
|
-
}
|
|
569
|
-
atomicWriteFile(targetManifestPath, `${JSON.stringify(finalManifest, null, 2)}\n`, targetRoot)
|
|
570
|
-
return conflicts
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
// ─── Generators ──────────────────────────────────────────────────────────
|
|
574
|
-
|
|
575
|
-
function generateShared(config: AgenticConfig): void {
|
|
576
|
-
const { targetDir } = config
|
|
577
|
-
const srcDir = join(AGENTIC_DIR, 'shared')
|
|
578
|
-
|
|
579
|
-
// Resolve which per-module fact-sheets this app gets (enabled ∩ bundled allowlist).
|
|
580
|
-
const selectedModules = selectModuleFactSheets(targetDir, join(GUIDES_DIR, 'modules'))
|
|
332
|
+
copyFile(
|
|
333
|
+
srcDir,
|
|
334
|
+
'ai/skills/om-trim-unused-modules/SKILL.md',
|
|
335
|
+
join(targetDir, '.ai', 'skills', 'om-trim-unused-modules', 'SKILL.md'),
|
|
336
|
+
)
|
|
581
337
|
|
|
582
|
-
|
|
583
|
-
writeTemplate(srcDir, 'AGENTS.md.template', join(targetDir, 'AGENTS.md'), config)
|
|
584
|
-
copyTree(join(srcDir, 'ai'), join(targetDir, '.ai'), config)
|
|
585
|
-
copyTree(join(srcDir, 'scripts'), join(targetDir, 'scripts'), config)
|
|
338
|
+
copyFile(srcDir, 'ai/qa/tests/playwright.config.ts', join(targetDir, '.ai', 'qa', 'tests', 'playwright.config.ts'))
|
|
586
339
|
|
|
587
|
-
//
|
|
340
|
+
// Package & conceptual guides are copied wholesale (framework-wide). Per-module
|
|
588
341
|
// fact-sheets (.ai/guides/modules/<module>.md) are filtered to the app's enabled
|
|
589
342
|
// module set; the combined module-facts.json sidecar is copied as-is.
|
|
590
343
|
if (existsSync(GUIDES_DIR)) {
|
|
@@ -604,9 +357,6 @@ function generateShared(config: AgenticConfig): void {
|
|
|
604
357
|
copyFileSync(moduleFactsPath, destPath)
|
|
605
358
|
}
|
|
606
359
|
|
|
607
|
-
|
|
608
|
-
copyTree(join(GUIDES_DIR, 'upstream'), join(guidesDestDir, 'upstream'), config)
|
|
609
|
-
|
|
610
360
|
const modulesSubdir = join(GUIDES_DIR, 'modules')
|
|
611
361
|
for (const moduleId of selectedModules) {
|
|
612
362
|
const destPath = join(guidesDestDir, 'modules', `${moduleId}.md`)
|
|
@@ -614,8 +364,6 @@ function generateShared(config: AgenticConfig): void {
|
|
|
614
364
|
copyFileSync(join(modulesSubdir, `${moduleId}.md`), destPath)
|
|
615
365
|
}
|
|
616
366
|
}
|
|
617
|
-
|
|
618
|
-
injectModuleGuides(join(targetDir, 'AGENTS.md'), selectedModules)
|
|
619
367
|
}
|
|
620
368
|
|
|
621
369
|
function generateClaudeCode(config: AgenticConfig): void {
|
|
@@ -627,7 +375,8 @@ function generateClaudeCode(config: AgenticConfig): void {
|
|
|
627
375
|
copyFile(srcDir, 'hooks/entity-migration-check.ts', join(targetDir, '.claude', 'hooks', 'entity-migration-check.ts'))
|
|
628
376
|
copyFile(srcDir, 'mcp.json.example', join(targetDir, '.mcp.json.example'))
|
|
629
377
|
|
|
630
|
-
//
|
|
378
|
+
// Symlink .claude/skills → ../.ai/skills
|
|
379
|
+
ensureSkillsLink(join(targetDir, '.claude', 'skills'), join('..', '.ai', 'skills'))
|
|
631
380
|
}
|
|
632
381
|
|
|
633
382
|
function generateCodex(config: AgenticConfig): void {
|
|
@@ -679,6 +428,17 @@ function generateCursor(config: AgenticConfig): void {
|
|
|
679
428
|
// which scripts/install-skills.sh populates.
|
|
680
429
|
}
|
|
681
430
|
|
|
431
|
+
function ensureSkillsLink(linkPath: string, target: string): void {
|
|
432
|
+
ensureDir(linkPath)
|
|
433
|
+
if (existsSync(linkPath) && !lstatSync(linkPath).isSymbolicLink()) {
|
|
434
|
+
return
|
|
435
|
+
}
|
|
436
|
+
if (lstatSync(linkPath, { throwIfNoEntry: false })?.isSymbolicLink()) {
|
|
437
|
+
unlinkSync(linkPath)
|
|
438
|
+
}
|
|
439
|
+
symlinkSync(target, linkPath)
|
|
440
|
+
}
|
|
441
|
+
|
|
682
442
|
// ─── Wizard ──────────────────────────────────────────────────────────────
|
|
683
443
|
|
|
684
444
|
const TOOLS = [
|
|
@@ -691,35 +451,6 @@ const TOOLS = [
|
|
|
691
451
|
|
|
692
452
|
const SELECTABLE = TOOLS.filter((t) => t.id !== 'multiple' && t.id !== 'skip')
|
|
693
453
|
|
|
694
|
-
function persistedAgentSelection(targetDir: string): string[] | null {
|
|
695
|
-
const selectableIds = SELECTABLE.map((tool) => tool.id)
|
|
696
|
-
const tiersPath = join(targetDir, '.ai', 'skills', 'tiers.json')
|
|
697
|
-
try {
|
|
698
|
-
const tiers = JSON.parse(readFileSync(tiersPath, 'utf8')) as { agents?: { ignore?: unknown } }
|
|
699
|
-
if (Array.isArray(tiers.agents?.ignore)
|
|
700
|
-
&& tiers.agents.ignore.every((id): id is string => typeof id === 'string')) {
|
|
701
|
-
const ignored = new Set(tiers.agents.ignore)
|
|
702
|
-
return selectableIds.filter((id) => !ignored.has(id))
|
|
703
|
-
}
|
|
704
|
-
} catch {
|
|
705
|
-
// Fall through to the ownership manifest and existing generated assets.
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
const manifest = readHarnessManifest(join(targetDir, '.ai', 'harness', 'manifest.json'))
|
|
709
|
-
const owned = new Set(manifest?.files.map((entry) => entry.path) ?? [])
|
|
710
|
-
const selected = SELECTABLE.filter((tool) => {
|
|
711
|
-
if (tool.id === 'claude-code') {
|
|
712
|
-
return owned.has('CLAUDE.md') || owned.has('.claude/settings.json')
|
|
713
|
-
|| existsSync(join(targetDir, 'CLAUDE.md')) || existsSync(join(targetDir, '.claude', 'settings.json'))
|
|
714
|
-
}
|
|
715
|
-
if (tool.id === 'codex') {
|
|
716
|
-
return owned.has('.codex/mcp.json.example') || existsSync(join(targetDir, '.codex', 'mcp.json.example'))
|
|
717
|
-
}
|
|
718
|
-
return owned.has('.cursor/hooks.json') || existsSync(join(targetDir, '.cursor', 'hooks.json'))
|
|
719
|
-
}).map((tool) => tool.id)
|
|
720
|
-
return selected.length > 0 ? selected : null
|
|
721
|
-
}
|
|
722
|
-
|
|
723
454
|
async function promptSelection(ask: AskFn): Promise<string[]> {
|
|
724
455
|
console.log('')
|
|
725
456
|
console.log('🤖 Agentic workflow setup')
|
|
@@ -766,8 +497,6 @@ export async function runAgenticSetup(
|
|
|
766
497
|
|
|
767
498
|
if (options?.tool) {
|
|
768
499
|
selectedIds = options.tool.split(',').map((t) => t.trim())
|
|
769
|
-
} else if (options?.updateHarness) {
|
|
770
|
-
selectedIds = persistedAgentSelection(targetDir) ?? await promptSelection(ask)
|
|
771
500
|
} else {
|
|
772
501
|
selectedIds = await promptSelection(ask)
|
|
773
502
|
}
|
|
@@ -784,37 +513,12 @@ export async function runAgenticSetup(
|
|
|
784
513
|
targetDir,
|
|
785
514
|
}
|
|
786
515
|
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
if (existsSync(modulesSourcePath)) {
|
|
792
|
-
ensureDir(modulesCandidatePath)
|
|
793
|
-
copyFileSync(modulesSourcePath, modulesCandidatePath)
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
const stagingConfig: AgenticConfig = {
|
|
797
|
-
projectName: config.projectName,
|
|
798
|
-
targetDir: stagingDir,
|
|
799
|
-
}
|
|
800
|
-
generateHarness(stagingConfig, selectedIds)
|
|
801
|
-
const conflicts = applyHarnessUpdate(targetDir, stagingDir, {
|
|
802
|
-
force: options?.force,
|
|
803
|
-
})
|
|
804
|
-
if (conflicts.length > 0) {
|
|
805
|
-
console.warn('')
|
|
806
|
-
console.warn(' ⚠ Preserved locally modified harness files:')
|
|
807
|
-
for (const conflict of conflicts) {
|
|
808
|
-
const detail = conflict.candidate
|
|
809
|
-
? `candidate: ${conflict.candidate}`
|
|
810
|
-
: 'retired asset kept because it has local changes'
|
|
811
|
-
console.warn(` • ${conflict.path} (${detail})`)
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
} finally {
|
|
815
|
-
rmSync(stagingDir, { recursive: true, force: true })
|
|
816
|
-
}
|
|
516
|
+
generateShared(config)
|
|
517
|
+
if (selectedIds.includes('claude-code')) generateClaudeCode(config)
|
|
518
|
+
if (selectedIds.includes('codex')) generateCodex(config)
|
|
519
|
+
if (selectedIds.includes('cursor')) generateCursor(config)
|
|
817
520
|
|
|
521
|
+
persistAgentSelection(targetDir, selectedIds)
|
|
818
522
|
installSkills(targetDir)
|
|
819
523
|
|
|
820
524
|
console.log('')
|
|
@@ -836,16 +540,6 @@ export async function runAgenticSetup(
|
|
|
836
540
|
console.log('')
|
|
837
541
|
}
|
|
838
542
|
|
|
839
|
-
function generateHarness(config: AgenticConfig, selectedIds: string[]): void {
|
|
840
|
-
generateShared(config)
|
|
841
|
-
if (selectedIds.includes('claude-code')) generateClaudeCode(config)
|
|
842
|
-
if (selectedIds.includes('codex')) generateCodex(config)
|
|
843
|
-
if (selectedIds.includes('cursor')) generateCursor(config)
|
|
844
|
-
|
|
845
|
-
persistAgentSelection(config.targetDir, selectedIds)
|
|
846
|
-
finalizeHarnessManifest(config, selectedIds)
|
|
847
|
-
}
|
|
848
|
-
|
|
849
543
|
/**
|
|
850
544
|
* Persist the agent selection so later `yarn install-skills` runs keep honoring
|
|
851
545
|
* it: agents the user did not pick go into `agents.ignore` in tiers.json and
|
|
@@ -865,11 +559,11 @@ function persistAgentSelection(targetDir: string, selectedIds: string[]): void {
|
|
|
865
559
|
}
|
|
866
560
|
|
|
867
561
|
function installSkills(targetDir: string): void {
|
|
868
|
-
const installScript = join(targetDir, 'scripts', 'install-skills.
|
|
562
|
+
const installScript = join(targetDir, 'scripts', 'install-skills.sh')
|
|
869
563
|
if (!existsSync(installScript)) return
|
|
870
564
|
console.log('')
|
|
871
565
|
console.log(' Installing agent skills (local tiers + external open-mercato/skills subset)...')
|
|
872
|
-
const result = spawnSync(
|
|
566
|
+
const result = spawnSync('sh', [installScript], { cwd: targetDir, stdio: 'inherit' })
|
|
873
567
|
if (result.error || result.status !== 0) {
|
|
874
568
|
console.log(' ⚠ Skill installation did not complete; run `yarn install-skills` inside the app when online.')
|
|
875
569
|
}
|