@open-mercato/cli 0.6.7 → 0.6.8-develop.6875.1.871a4afc94
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 +24 -7
- package/dist/agentic/claude-code/hooks/entity-migration-check.ts +32 -88
- package/dist/agentic/codex/enforcement-rules.md +2 -16
- package/dist/agentic/cursor/hooks/entity-migration-check.mjs +19 -50
- package/dist/agentic/cursor/rules/entity-guard.mdc +9 -21
- package/dist/agentic/cursor/rules/generated-guard.mdc +3 -5
- package/dist/agentic/cursor/rules/open-mercato.mdc +3 -29
- package/dist/agentic/guides/ai-workflows.md +76 -0
- package/dist/agentic/guides/architecture.md +107 -0
- package/dist/agentic/guides/backend-ui.md +80 -0
- package/dist/agentic/guides/contracts.md +92 -0
- package/dist/agentic/guides/extensions.md +121 -0
- package/dist/agentic/guides/framework-extension-points.md +36 -0
- package/dist/agentic/guides/integrations.md +81 -0
- package/dist/agentic/guides/module-facts.json +115537 -3951
- package/dist/agentic/guides/module-system.md +12 -127
- package/dist/agentic/guides/modules/ai_assistant.md +227 -28
- package/dist/agentic/guides/modules/api_docs.md +58 -2
- package/dist/agentic/guides/modules/api_keys.md +92 -7
- package/dist/agentic/guides/modules/attachments.md +119 -14
- package/dist/agentic/guides/modules/audit_logs.md +131 -10
- package/dist/agentic/guides/modules/auth.md +276 -33
- package/dist/agentic/guides/modules/business_rules.md +149 -14
- package/dist/agentic/guides/modules/catalog.md +475 -43
- package/dist/agentic/guides/modules/channel_gmail.md +82 -3
- package/dist/agentic/guides/modules/channel_imap.md +82 -3
- package/dist/agentic/guides/modules/checkout.md +299 -27
- package/dist/agentic/guides/modules/communication_channels.md +315 -33
- package/dist/agentic/guides/modules/configs.md +104 -8
- package/dist/agentic/guides/modules/content.md +57 -2
- package/dist/agentic/guides/modules/currencies.md +152 -17
- package/dist/agentic/guides/modules/customer_accounts.md +387 -45
- package/dist/agentic/guides/modules/customers.md +746 -85
- package/dist/agentic/guides/modules/dashboards.md +155 -10
- package/dist/agentic/guides/modules/data_sync.md +149 -16
- package/dist/agentic/guides/modules/design_system.md +102 -0
- package/dist/agentic/guides/modules/dictionaries.md +107 -12
- package/dist/agentic/guides/modules/directory.md +148 -15
- package/dist/agentic/guides/modules/entities.md +145 -13
- package/dist/agentic/guides/modules/events.md +59 -2
- package/dist/agentic/guides/modules/feature_toggles.md +119 -9
- package/dist/agentic/guides/modules/gateway_stripe.md +92 -4
- package/dist/agentic/guides/modules/generators.md +45 -2
- package/dist/agentic/guides/modules/inbox_ops.md +207 -27
- package/dist/agentic/guides/modules/integrations.md +146 -16
- package/dist/agentic/guides/modules/messages.md +223 -24
- package/dist/agentic/guides/modules/notifications.md +96 -8
- package/dist/agentic/guides/modules/onboarding.md +77 -6
- package/dist/agentic/guides/modules/payment_gateways.md +164 -21
- package/dist/agentic/guides/modules/perspectives.md +77 -7
- package/dist/agentic/guides/modules/planner.md +136 -18
- package/dist/agentic/guides/modules/portal.md +93 -2
- package/dist/agentic/guides/modules/progress.md +104 -14
- package/dist/agentic/guides/modules/query_index.md +154 -15
- package/dist/agentic/guides/modules/record_locks.md +206 -21
- package/dist/agentic/guides/modules/resources.md +197 -30
- package/dist/agentic/guides/modules/sales.md +678 -84
- package/dist/agentic/guides/modules/scheduler.md +133 -14
- package/dist/agentic/guides/modules/search.md +170 -6
- package/dist/agentic/guides/modules/security.md +294 -35
- package/dist/agentic/guides/modules/shipping_carriers.md +134 -18
- package/dist/agentic/guides/modules/sso.md +151 -26
- package/dist/agentic/guides/modules/staff.md +369 -57
- package/dist/agentic/guides/modules/storage_s3.md +95 -5
- package/dist/agentic/guides/modules/sync_akeneo.md +85 -3
- package/dist/agentic/guides/modules/sync_excel.md +75 -6
- package/dist/agentic/guides/modules/system_status_overlays.md +60 -2
- package/dist/agentic/guides/modules/translations.md +104 -10
- package/dist/agentic/guides/modules/webhooks.md +203 -24
- package/dist/agentic/guides/modules/wms.md +441 -46
- package/dist/agentic/guides/modules/workflows.md +302 -43
- package/dist/agentic/guides/spec-delivery.md +22 -0
- package/dist/agentic/guides/testing-debugging.md +80 -0
- package/dist/agentic/guides/upstream/AGENTS.md +299 -0
- package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +316 -0
- package/dist/agentic/guides/upstream/manifest.json +8 -0
- package/dist/agentic/shared/AGENTS.md.template +124 -311
- package/dist/agentic/shared/ai/agentic.config.json +2 -0
- package/dist/agentic/shared/ai/harness/README.md +50 -0
- package/dist/agentic/shared/ai/harness/RELEASE.md +57 -0
- package/dist/agentic/shared/ai/harness/cases.json +13680 -0
- package/dist/agentic/shared/ai/harness/cases.schema.json +133 -0
- package/dist/agentic/shared/ai/harness/fixtures/index.json +49 -0
- package/dist/agentic/shared/ai/harness/fixtures/seeds.json +162 -0
- package/dist/agentic/shared/ai/harness/generated-code-review-policy.md +21 -0
- package/dist/agentic/shared/ai/harness/generated-code-review-response.schema.json +96 -0
- package/dist/agentic/shared/ai/harness/generated-code-review-result.schema.json +172 -0
- package/dist/agentic/shared/ai/harness/release-matrix.json +158 -0
- package/dist/agentic/shared/ai/harness/release-result.schema.json +219 -0
- package/dist/agentic/shared/ai/harness/result.schema.json +76 -0
- package/dist/agentic/shared/ai/harness/routing-response.schema.json +12 -0
- package/dist/agentic/shared/ai/harness/target-validation-result.schema.json +73 -0
- package/dist/agentic/shared/ai/harness/validators.json +78 -0
- package/dist/agentic/shared/ai/harness/writable-ast-oracles.mjs +2121 -0
- package/dist/agentic/shared/ai/harness/writable-behavior-oracles.mjs +1096 -0
- package/dist/agentic/shared/ai/lessons/_template.md +16 -0
- package/dist/agentic/shared/ai/lessons.md +26 -3
- package/dist/agentic/shared/ai/review-checklist.md +36 -0
- package/dist/agentic/shared/ai/skills/om-auto-implement-spec/SKILL.md +21 -0
- package/dist/agentic/shared/ai/skills/om-auto-review-pr/SKILL.md +4 -0
- package/dist/agentic/shared/ai/skills/om-auto-upgrade-0.6.6-to-0.6.7/SKILL.md +98 -0
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/SKILL.md +20 -241
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/crud-surfaces.md +16 -0
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/frontend-and-design-system.md +53 -0
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/page-and-navigation.md +13 -0
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/quality-states.md +11 -0
- package/dist/agentic/shared/ai/skills/om-build-workflow/SKILL.md +30 -0
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/activity-contracts.md +12 -0
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/durability-and-progress.md +13 -0
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/workflow-design.md +14 -0
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/SKILL.md +28 -0
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/attachments-and-overrides.md +12 -0
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/module-agents-and-tools.md +22 -0
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/orchestrator-agents.md +12 -0
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/surface-selector.md +19 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/SKILL.md +16 -601
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/integrity-and-concurrency.md +19 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/migration-workflow.md +13 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/schema-design.md +14 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/sensitive-data.md +10 -0
- package/dist/agentic/shared/ai/skills/om-eject-and-customize/SKILL.md +14 -310
- package/dist/agentic/shared/ai/skills/om-eject-and-customize/references/decision-and-procedure.md +17 -0
- package/dist/agentic/shared/ai/skills/om-evolve-harness/SKILL.md +29 -0
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-template.md +100 -0
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-workflow.md +16 -0
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/owner-selection.md +17 -0
- package/dist/agentic/shared/ai/skills/om-framework-context/SKILL.md +25 -0
- package/dist/agentic/shared/ai/skills/om-framework-context/references/resolver-procedure.md +11 -0
- package/dist/agentic/shared/ai/skills/om-framework-context/references/skew-and-escalation.md +13 -0
- package/dist/agentic/shared/ai/skills/om-help/SKILL.md +15 -97
- package/dist/agentic/shared/ai/skills/om-help/references/delivery-workflows.md +18 -0
- package/dist/agentic/shared/ai/skills/om-help/references/task-families.md +20 -0
- package/dist/agentic/shared/ai/skills/om-implement-spec/SKILL.md +33 -152
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/phases-and-gates.md +33 -0
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/planning-and-progress.md +40 -0
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/report-templates.md +27 -0
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/spec-resolution.md +24 -0
- package/dist/agentic/shared/ai/skills/om-integration-builder/SKILL.md +24 -708
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/package-and-activation.md +16 -0
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/provider-families.md +14 -0
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/security-and-reliability.md +15 -0
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/sync-and-files.md +12 -0
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/SKILL.md +34 -0
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/agents/openai.yaml +4 -0
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/agentic-setup.md +11 -0
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/input-normalization.md +31 -0
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/judge-workflow.md +39 -0
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/report-template.md +43 -0
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/rules.md +11 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/SKILL.md +20 -820
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/api-and-domain.md +19 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/business-one-shot-blueprints.md +172 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/data-and-migrations.md +12 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/discovery-surface-catalog.md +83 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/module-surfaces.md +21 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/planning.md +11 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/runtime-cache-and-queues.md +22 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/verification.md +13 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/SKILL.md +41 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/agentic-setup.md +19 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/bundle-preparation.md +44 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/consent-and-review.md +39 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/publication.md +20 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/report-templates.md +57 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/rules.md +11 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/scripts/prepare-share-bundle.mjs +486 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/SKILL.md +19 -843
- package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-branches.md +18 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/references/mechanism-selector.md +27 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/references/read-write-roundtrip.md +13 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/references/unified-overrides.md +41 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/references/verification.md +11 -0
- package/dist/agentic/shared/ai/skills/om-trim-unused-modules/SKILL.md +15 -63
- package/dist/agentic/shared/ai/skills/om-trim-unused-modules/references/dependency-and-redirect.md +15 -0
- package/dist/agentic/shared/ai/skills/om-troubleshooter/SKILL.md +16 -467
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnosis-map.md +16 -0
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/regression-oracles.md +14 -0
- package/dist/agentic/shared/ai/skills/tiers.json +143 -21
- package/dist/agentic/shared/ai/skills/tiers.schema.json +52 -40
- package/dist/agentic/shared/ai/specs/README.md +4 -3
- package/dist/agentic/shared/ai/specs/SPEC-000-template.md +226 -10
- package/dist/agentic/shared/ai/trackers/github.md +108 -4
- package/dist/agentic/shared/scripts/agent-harness-tool-server.mjs +187 -0
- package/dist/agentic/shared/scripts/check-lessons.mjs +178 -0
- package/dist/agentic/shared/scripts/evaluate-agent-harness.mjs +2958 -0
- package/dist/agentic/shared/scripts/execution-sandbox.mjs +329 -0
- package/dist/agentic/shared/scripts/framework-context.mjs +888 -0
- package/dist/agentic/shared/scripts/install-skills.mjs +1029 -0
- package/dist/agentic/shared/scripts/install-skills.sh +4 -694
- package/dist/agentic/shared/scripts/prepare-agent-harness-fixture.mjs +222 -0
- package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +1774 -0
- package/dist/bin.js +13 -1
- package/dist/bin.js.map +2 -2
- package/dist/lib/__integration__/TC-INT-008.spec.js +88 -8
- package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
- package/dist/lib/agentic-init.js +13 -3
- package/dist/lib/agentic-init.js.map +2 -2
- package/dist/lib/agentic-setup.js +434 -186
- package/dist/lib/agentic-setup.js.map +2 -2
- package/dist/lib/generators/extensions/injection-widgets.js +20 -0
- package/dist/lib/generators/extensions/injection-widgets.js.map +2 -2
- package/dist/lib/generators/module-extension-facts.js +1840 -0
- package/dist/lib/generators/module-extension-facts.js.map +7 -0
- package/dist/lib/generators/module-fact-sources.js +70 -0
- package/dist/lib/generators/module-fact-sources.js.map +7 -0
- package/dist/lib/generators/module-facts-discovery.js +41 -7
- package/dist/lib/generators/module-facts-discovery.js.map +2 -2
- package/dist/lib/generators/module-facts.js +1387 -45
- package/dist/lib/generators/module-facts.js.map +3 -3
- package/dist/lib/generators/module-override-targets.js +688 -0
- package/dist/lib/generators/module-override-targets.js.map +7 -0
- package/dist/lib/generators/module-registry.js +11 -5
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/load-env.js +24 -0
- package/dist/lib/load-env.js.map +7 -0
- package/dist/lib/resolver.js +2 -0
- package/dist/lib/resolver.js.map +2 -2
- package/dist/lib/telemetry-init.js +358 -0
- package/dist/lib/telemetry-init.js.map +7 -0
- package/dist/lib/testing/integration.js +5 -0
- package/dist/lib/testing/integration.js.map +2 -2
- package/dist/mercato.js +23 -1
- package/dist/mercato.js.map +2 -2
- package/package.json +13 -11
- package/src/bin.ts +33 -1
- package/src/lib/__integration__/TC-INT-008.spec.ts +107 -9
- package/src/lib/__tests__/agentic-init.test.ts +41 -5
- package/src/lib/__tests__/agentic-setup.ownership.test.ts +386 -0
- package/src/lib/__tests__/injection-widget-id-validation.test.ts +184 -0
- package/src/lib/__tests__/load-env.test.ts +65 -0
- package/src/lib/__tests__/telemetry-init.test.ts +298 -0
- package/src/lib/agentic-init.ts +15 -3
- package/src/lib/agentic-setup.ts +573 -222
- package/src/lib/generators/__tests__/activation-adapter-coverage.test.ts +92 -0
- package/src/lib/generators/__tests__/module-extension-activations.test.ts +762 -0
- package/src/lib/generators/__tests__/module-extension-facts.test.ts +404 -0
- package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +88 -2
- package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +1 -0
- package/src/lib/generators/__tests__/module-facts.discovery.test.ts +54 -10
- package/src/lib/generators/__tests__/module-facts.extension-hosts.test.ts +108 -0
- package/src/lib/generators/__tests__/module-facts.owned-contracts.test.ts +561 -0
- package/src/lib/generators/__tests__/module-facts.source-links.test.ts +119 -0
- package/src/lib/generators/__tests__/module-override-targets.roundtrip.test.ts +149 -0
- package/src/lib/generators/__tests__/module-override-targets.test.ts +304 -0
- package/src/lib/generators/__tests__/module-subset.test.ts +18 -0
- package/src/lib/generators/extensions/injection-widgets.ts +51 -0
- package/src/lib/generators/module-extension-facts.ts +2365 -0
- package/src/lib/generators/module-fact-sources.ts +108 -0
- package/src/lib/generators/module-facts-discovery.ts +58 -7
- package/src/lib/generators/module-facts.ts +1851 -46
- package/src/lib/generators/module-override-targets.ts +863 -0
- package/src/lib/generators/module-registry.ts +16 -6
- package/src/lib/load-env.ts +30 -0
- package/src/lib/resolver.ts +3 -0
- package/src/lib/telemetry-init.ts +461 -0
- package/src/lib/testing/__tests__/integration.test.ts +4 -0
- package/src/lib/testing/integration.ts +5 -0
- package/src/mercato.ts +26 -1
- package/dist/agentic/guides/cache.md +0 -45
- package/dist/agentic/guides/core.md +0 -453
- package/dist/agentic/guides/events.md +0 -117
- package/dist/agentic/guides/queue.md +0 -53
- package/dist/agentic/guides/search.md +0 -115
- package/dist/agentic/guides/shared.md +0 -108
- package/dist/agentic/guides/ui.md +0 -347
- package/dist/agentic/shared/ai/skills/om-auto-continue-pr-loop/SKILL.md +0 -27
- package/dist/agentic/shared/ai/skills/om-auto-create-pr-loop/SKILL.md +0 -27
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/ui-components.md +0 -260
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md +0 -146
- package/dist/agentic/shared/ai/skills/om-help/references/skills-catalog.md +0 -84
- package/dist/agentic/shared/ai/skills/om-help/references/workflow-sequences.md +0 -193
- package/dist/agentic/shared/ai/skills/om-integration-builder/STANDALONE.md +0 -34
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/adapter-contracts.md +0 -762
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/naming-conventions.md +0 -50
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/navigation-patterns.md +0 -97
- package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-contracts.md +0 -271
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnostic-commands.md +0 -101
|
@@ -1,10 +1,27 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
chmodSync,
|
|
3
|
+
copyFileSync,
|
|
4
|
+
existsSync,
|
|
5
|
+
lstatSync,
|
|
6
|
+
mkdirSync,
|
|
7
|
+
mkdtempSync,
|
|
8
|
+
readFileSync,
|
|
9
|
+
readdirSync,
|
|
10
|
+
realpathSync,
|
|
11
|
+
renameSync,
|
|
12
|
+
rmSync,
|
|
13
|
+
statSync,
|
|
14
|
+
writeFileSync
|
|
15
|
+
} from "node:fs";
|
|
16
|
+
import { createHash } from "node:crypto";
|
|
2
17
|
import { spawnSync } from "node:child_process";
|
|
3
|
-
import {
|
|
18
|
+
import { tmpdir } from "node:os";
|
|
19
|
+
import { join, dirname, basename, relative, resolve, sep } from "node:path";
|
|
4
20
|
import { fileURLToPath } from "node:url";
|
|
5
21
|
import { Project, SyntaxKind } from "ts-morph";
|
|
6
|
-
const
|
|
7
|
-
const
|
|
22
|
+
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
const bundledAgenticDir = join(moduleDir, "..", "agentic");
|
|
24
|
+
const AGENTIC_DIR = existsSync(bundledAgenticDir) ? bundledAgenticDir : join(moduleDir, "..", "..", "..", "create-app", "agentic");
|
|
8
25
|
const GUIDES_DIR = join(AGENTIC_DIR, "guides");
|
|
9
26
|
function resolvePlaceholders(content, config) {
|
|
10
27
|
return content.replace(/\{\{PROJECT_NAME\}\}/g, config.projectName);
|
|
@@ -25,13 +42,13 @@ function copyFile(srcDir, srcRelative, destPath) {
|
|
|
25
42
|
copyFileSync(srcPath, destPath);
|
|
26
43
|
}
|
|
27
44
|
function readEnabledModuleIds(modulesPath) {
|
|
28
|
-
if (!existsSync(modulesPath)) return [];
|
|
45
|
+
if (!existsSync(modulesPath)) return { parsed: false, ids: [] };
|
|
29
46
|
try {
|
|
30
47
|
const project = new Project({ useInMemoryFileSystem: true });
|
|
31
48
|
const sourceFile = project.createSourceFile("modules.ts", readFileSync(modulesPath, "utf-8"));
|
|
32
49
|
const declaration = sourceFile.getVariableDeclaration("enabledModules");
|
|
33
50
|
const arrayLiteral = declaration?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression);
|
|
34
|
-
if (!arrayLiteral) return [];
|
|
51
|
+
if (!arrayLiteral) return { parsed: false, ids: [] };
|
|
35
52
|
const ids = [];
|
|
36
53
|
for (const element of arrayLiteral.getElements()) {
|
|
37
54
|
const objectLiteral = element.asKind(SyntaxKind.ObjectLiteralExpression);
|
|
@@ -40,44 +57,33 @@ function readEnabledModuleIds(modulesPath) {
|
|
|
40
57
|
const idValue = idProperty?.getInitializerIfKind(SyntaxKind.StringLiteral)?.getLiteralValue();
|
|
41
58
|
if (idValue) ids.push(idValue);
|
|
42
59
|
}
|
|
43
|
-
return ids;
|
|
60
|
+
return { parsed: true, ids };
|
|
44
61
|
} catch {
|
|
45
|
-
return [];
|
|
62
|
+
return { parsed: false, ids: [] };
|
|
46
63
|
}
|
|
47
64
|
}
|
|
48
65
|
function selectModuleFactSheets(targetDir, modulesSubdir) {
|
|
49
66
|
const available = existsSync(modulesSubdir) ? readdirSync(modulesSubdir).filter((file) => file.endsWith(".md")).map((file) => file.replace(/\.md$/, "")) : [];
|
|
50
67
|
if (available.length === 0) return [];
|
|
51
|
-
const
|
|
68
|
+
const parsed = readEnabledModuleIds(join(targetDir, "src", "modules.ts"));
|
|
69
|
+
if (!parsed.parsed) return available;
|
|
70
|
+
const enabled = new Set(parsed.ids);
|
|
52
71
|
const selected = available.filter((moduleId) => enabled.has(moduleId));
|
|
53
|
-
return selected
|
|
72
|
+
return selected;
|
|
54
73
|
}
|
|
55
74
|
const MODULE_GUIDES_START = "<!-- om:module-guides:start -->";
|
|
56
75
|
const MODULE_GUIDES_END = "<!-- om:module-guides:end -->";
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (!existsSync(factsPath)) return {};
|
|
60
|
-
try {
|
|
61
|
-
const parsed = JSON.parse(readFileSync(factsPath, "utf-8"));
|
|
62
|
-
const labels = {};
|
|
63
|
-
for (const [moduleId, entry] of Object.entries(parsed)) {
|
|
64
|
-
const label = entry && typeof entry.description === "string" && entry.description || entry && typeof entry.title === "string" && entry.title || "";
|
|
65
|
-
if (label) labels[moduleId] = label;
|
|
66
|
-
}
|
|
67
|
-
return labels;
|
|
68
|
-
} catch {
|
|
69
|
-
return {};
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
function renderModuleGuidesBlock(selected, labels) {
|
|
76
|
+
const STANDALONE_ROOT_TARGET_BYTES = 12 * 1024;
|
|
77
|
+
function renderModuleGuidesBlock(selected, options = {}) {
|
|
73
78
|
if (selected.length === 0) return "_No module fact-sheets are bundled for this app._";
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
const index = options.compact ? `Enabled module facts: ${selected.length} sheets bundled, too many to index inline \u2014 list the module facts directory to see which modules have one.` : `Enabled module facts: ${selected.map((moduleId) => `\`${moduleId}\``).join(",")}.`;
|
|
80
|
+
return [
|
|
81
|
+
index,
|
|
82
|
+
"",
|
|
83
|
+
"Load `.ai/guides/modules/<id>.md` only for a named or targeted installed module/host; never preload all module facts."
|
|
84
|
+
].join("\n");
|
|
79
85
|
}
|
|
80
|
-
function injectModuleGuides(agentsMdPath, selected,
|
|
86
|
+
function injectModuleGuides(agentsMdPath, selected, options = {}) {
|
|
81
87
|
if (!existsSync(agentsMdPath)) return;
|
|
82
88
|
const content = readFileSync(agentsMdPath, "utf-8");
|
|
83
89
|
const startIndex = content.indexOf(MODULE_GUIDES_START);
|
|
@@ -91,154 +97,339 @@ function injectModuleGuides(agentsMdPath, selected, labels = {}) {
|
|
|
91
97
|
const before = content.slice(0, startIndex + MODULE_GUIDES_START.length);
|
|
92
98
|
const after = content.slice(endIndex);
|
|
93
99
|
const next = `${before}
|
|
94
|
-
${renderModuleGuidesBlock(selected,
|
|
100
|
+
${renderModuleGuidesBlock(selected, options)}
|
|
95
101
|
${after}`;
|
|
96
102
|
if (next !== content) writeFileSync(agentsMdPath, next);
|
|
97
103
|
}
|
|
98
|
-
function
|
|
104
|
+
function enforceRootInstructionBudget(agentsMdPath, selected, maxBytes = STANDALONE_ROOT_TARGET_BYTES) {
|
|
105
|
+
if (!existsSync(agentsMdPath)) return false;
|
|
106
|
+
if (Buffer.byteLength(readFileSync(agentsMdPath)) <= maxBytes) return false;
|
|
107
|
+
injectModuleGuides(agentsMdPath, selected, { compact: true });
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
const TEXT_EXTENSIONS = /* @__PURE__ */ new Set([".cjs", ".json", ".md", ".mdc", ".mjs", ".sh", ".ts", ".txt"]);
|
|
111
|
+
function isTextAsset(path) {
|
|
112
|
+
const dot = path.lastIndexOf(".");
|
|
113
|
+
return dot === -1 || TEXT_EXTENSIONS.has(path.slice(dot));
|
|
114
|
+
}
|
|
115
|
+
function listFiles(root) {
|
|
116
|
+
if (!existsSync(root)) return [];
|
|
117
|
+
const files = [];
|
|
118
|
+
for (const entry of readdirSync(root, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
119
|
+
const absolute = join(root, entry.name);
|
|
120
|
+
if (entry.isDirectory()) files.push(...listFiles(absolute));
|
|
121
|
+
else if (entry.isFile()) files.push(absolute);
|
|
122
|
+
}
|
|
123
|
+
return files;
|
|
124
|
+
}
|
|
125
|
+
function copyTree(sourceRoot, destinationRoot, config) {
|
|
126
|
+
for (const sourcePath of listFiles(sourceRoot)) {
|
|
127
|
+
const destinationPath = join(destinationRoot, relative(sourceRoot, sourcePath));
|
|
128
|
+
ensureDir(destinationPath);
|
|
129
|
+
if (isTextAsset(sourcePath)) {
|
|
130
|
+
writeFileSync(destinationPath, resolvePlaceholders(readFileSync(sourcePath, "utf8"), config));
|
|
131
|
+
} else {
|
|
132
|
+
copyFileSync(sourcePath, destinationPath);
|
|
133
|
+
}
|
|
134
|
+
if (process.platform !== "win32") chmodSync(destinationPath, statSync(sourcePath).mode & 511);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function hashFile(path) {
|
|
138
|
+
return createHash("sha256").update(readFileSync(path)).digest("hex");
|
|
139
|
+
}
|
|
140
|
+
function canonicalHarnessRoot(root) {
|
|
141
|
+
const resolved = resolve(root);
|
|
142
|
+
if (!existsSync(resolved)) {
|
|
143
|
+
throw new Error(`Harness root must be an existing directory: ${resolved}`);
|
|
144
|
+
}
|
|
145
|
+
const canonical = realpathSync(resolved);
|
|
146
|
+
const entry = lstatSync(canonical, { throwIfNoEntry: false });
|
|
147
|
+
if (!entry || !entry.isDirectory()) {
|
|
148
|
+
throw new Error(`Harness root must be an existing directory: ${resolved}`);
|
|
149
|
+
}
|
|
150
|
+
return canonical;
|
|
151
|
+
}
|
|
152
|
+
function assertManagedPath(root, path, options = {}) {
|
|
153
|
+
const absolutePath = resolve(path);
|
|
154
|
+
const normalizedRelative = relative(root, absolutePath);
|
|
155
|
+
if (normalizedRelative === ".." || normalizedRelative.startsWith(`..${sep}`)) {
|
|
156
|
+
throw new Error(`Harness-managed path escapes its root: ${absolutePath}`);
|
|
157
|
+
}
|
|
158
|
+
if (normalizedRelative === "") return;
|
|
159
|
+
const components = normalizedRelative.split(sep).filter(Boolean);
|
|
160
|
+
let current = root;
|
|
161
|
+
for (let index = 0; index < components.length; index += 1) {
|
|
162
|
+
current = join(current, components[index]);
|
|
163
|
+
const entry = lstatSync(current, { throwIfNoEntry: false });
|
|
164
|
+
if (!entry) return;
|
|
165
|
+
if (entry.isSymbolicLink()) {
|
|
166
|
+
throw new Error(`Harness-managed path contains a symbolic-link component: ${current}`);
|
|
167
|
+
}
|
|
168
|
+
const isLeaf = index === components.length - 1;
|
|
169
|
+
if (!isLeaf && !entry.isDirectory()) {
|
|
170
|
+
throw new Error(`Harness-managed path component is not a directory: ${current}`);
|
|
171
|
+
}
|
|
172
|
+
if (isLeaf && options.leaf === "file" && !entry.isFile()) {
|
|
173
|
+
throw new Error(`Harness-managed file is not a regular file: ${current}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function ensureManagedParent(root, filePath) {
|
|
178
|
+
const parent = dirname(filePath);
|
|
179
|
+
const normalizedRelative = relative(root, parent);
|
|
180
|
+
if (normalizedRelative === ".." || normalizedRelative.startsWith(`..${sep}`)) {
|
|
181
|
+
throw new Error(`Harness-managed path escapes its root: ${filePath}`);
|
|
182
|
+
}
|
|
183
|
+
let current = root;
|
|
184
|
+
for (const component of normalizedRelative.split(sep).filter(Boolean)) {
|
|
185
|
+
assertManagedPath(root, current);
|
|
186
|
+
current = join(current, component);
|
|
187
|
+
const entry = lstatSync(current, { throwIfNoEntry: false });
|
|
188
|
+
if (!entry) mkdirSync(current);
|
|
189
|
+
const created = lstatSync(current, { throwIfNoEntry: false });
|
|
190
|
+
if (!created || created.isSymbolicLink() || !created.isDirectory()) {
|
|
191
|
+
throw new Error(`Harness-managed path component is not a real directory: ${current}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function harnessGeneratorId() {
|
|
196
|
+
try {
|
|
197
|
+
const upstream = JSON.parse(readFileSync(join(GUIDES_DIR, "upstream", "manifest.json"), "utf8"));
|
|
198
|
+
const generator = typeof upstream.generator === "string" ? upstream.generator : "";
|
|
199
|
+
const version = generator.slice(generator.lastIndexOf("@") + 1);
|
|
200
|
+
if (version && version !== generator) return `open-mercato-agentic@${version}`;
|
|
201
|
+
} catch {
|
|
202
|
+
}
|
|
203
|
+
return "open-mercato-agentic@unknown";
|
|
204
|
+
}
|
|
205
|
+
function externalSkillNames(targetDir) {
|
|
206
|
+
try {
|
|
207
|
+
const tiers = JSON.parse(readFileSync(join(targetDir, ".ai", "skills", "tiers.json"), "utf8"));
|
|
208
|
+
return new Set(Array.isArray(tiers.external?.skills) ? tiers.external.skills.filter((name) => typeof name === "string") : []);
|
|
209
|
+
} catch {
|
|
210
|
+
return /* @__PURE__ */ new Set();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function atomicCopyFile(sourcePath, destinationPath, managedRoot) {
|
|
214
|
+
if (managedRoot) {
|
|
215
|
+
assertManagedPath(managedRoot, destinationPath, { leaf: "file" });
|
|
216
|
+
ensureManagedParent(managedRoot, destinationPath);
|
|
217
|
+
} else {
|
|
218
|
+
ensureDir(destinationPath);
|
|
219
|
+
}
|
|
220
|
+
const temporaryPath = `${destinationPath}.tmp-${process.pid}-${Date.now()}`;
|
|
221
|
+
try {
|
|
222
|
+
if (managedRoot) assertManagedPath(managedRoot, temporaryPath, { leaf: "file" });
|
|
223
|
+
copyFileSync(sourcePath, temporaryPath);
|
|
224
|
+
if (process.platform !== "win32") chmodSync(temporaryPath, statSync(sourcePath).mode & 511);
|
|
225
|
+
if (managedRoot) {
|
|
226
|
+
assertManagedPath(managedRoot, dirname(destinationPath));
|
|
227
|
+
assertManagedPath(managedRoot, destinationPath, { leaf: "file" });
|
|
228
|
+
assertManagedPath(managedRoot, temporaryPath, { leaf: "file" });
|
|
229
|
+
}
|
|
230
|
+
renameSync(temporaryPath, destinationPath);
|
|
231
|
+
} finally {
|
|
232
|
+
if (!managedRoot || !lstatSync(temporaryPath, { throwIfNoEntry: false })?.isSymbolicLink()) {
|
|
233
|
+
rmSync(temporaryPath, { force: true });
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function atomicWriteFile(destinationPath, content, managedRoot) {
|
|
238
|
+
if (managedRoot) {
|
|
239
|
+
assertManagedPath(managedRoot, destinationPath, { leaf: "file" });
|
|
240
|
+
ensureManagedParent(managedRoot, destinationPath);
|
|
241
|
+
} else {
|
|
242
|
+
ensureDir(destinationPath);
|
|
243
|
+
}
|
|
244
|
+
const temporaryPath = `${destinationPath}.tmp-${process.pid}-${Date.now()}`;
|
|
245
|
+
try {
|
|
246
|
+
if (managedRoot) assertManagedPath(managedRoot, temporaryPath, { leaf: "file" });
|
|
247
|
+
writeFileSync(temporaryPath, content);
|
|
248
|
+
if (managedRoot) {
|
|
249
|
+
assertManagedPath(managedRoot, dirname(destinationPath));
|
|
250
|
+
assertManagedPath(managedRoot, destinationPath, { leaf: "file" });
|
|
251
|
+
assertManagedPath(managedRoot, temporaryPath, { leaf: "file" });
|
|
252
|
+
}
|
|
253
|
+
renameSync(temporaryPath, destinationPath);
|
|
254
|
+
} finally {
|
|
255
|
+
if (!managedRoot || !lstatSync(temporaryPath, { throwIfNoEntry: false })?.isSymbolicLink()) {
|
|
256
|
+
rmSync(temporaryPath, { force: true });
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
function resolveManifestPath(root, relativePath) {
|
|
261
|
+
if (!relativePath || relativePath.includes("\0")) return null;
|
|
262
|
+
const absolutePath = resolve(root, relativePath);
|
|
263
|
+
const normalizedRelative = relative(root, absolutePath);
|
|
264
|
+
if (normalizedRelative === "" || normalizedRelative === ".." || normalizedRelative.startsWith(`..${sep}`)) {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
return absolutePath;
|
|
268
|
+
}
|
|
269
|
+
function normalizeManifestRelativePath(path) {
|
|
270
|
+
return path.replace(/\\/g, "/");
|
|
271
|
+
}
|
|
272
|
+
function readHarnessManifest(manifestPath) {
|
|
273
|
+
if (!existsSync(manifestPath)) return null;
|
|
274
|
+
try {
|
|
275
|
+
const parsed = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
276
|
+
if (typeof parsed.version !== "number" || typeof parsed.generator !== "string" || !Array.isArray(parsed.files)) {
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
const files = [];
|
|
280
|
+
for (const entry of parsed.files) {
|
|
281
|
+
if (!entry || typeof entry.path !== "string" || typeof entry.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(entry.sha256) || typeof entry.source !== "string" || typeof entry.userEditable !== "boolean") {
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
files.push({ ...entry, path: normalizeManifestRelativePath(entry.path) });
|
|
285
|
+
}
|
|
286
|
+
return { version: parsed.version, generator: parsed.generator, files };
|
|
287
|
+
} catch {
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function targetPathsForTree(sourceRoot, destinationRoot) {
|
|
292
|
+
return listFiles(sourceRoot).map((sourcePath) => join(destinationRoot, relative(sourceRoot, sourcePath)));
|
|
293
|
+
}
|
|
294
|
+
function finalizeHarnessManifest(config, selectedTools) {
|
|
99
295
|
const { targetDir } = config;
|
|
100
296
|
const srcDir = join(AGENTIC_DIR, "shared");
|
|
101
297
|
const selectedModules = selectModuleFactSheets(targetDir, join(GUIDES_DIR, "modules"));
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
copyFile(srcDir, "ai/skills/tiers.schema.json", join(targetDir, ".ai", "skills", "tiers.schema.json"));
|
|
110
|
-
copyFile(srcDir, "ai/agentic.config.json", join(targetDir, ".ai", "agentic.config.json"));
|
|
111
|
-
copyFile(srcDir, "ai/trackers/github.md", join(targetDir, ".ai", "trackers", "github.md"));
|
|
112
|
-
copyFile(srcDir, "scripts/install-skills.sh", join(targetDir, "scripts", "install-skills.sh"));
|
|
113
|
-
copyFile(
|
|
114
|
-
srcDir,
|
|
115
|
-
"ai/skills/om-backend-ui-design/SKILL.md",
|
|
116
|
-
join(targetDir, ".ai", "skills", "om-backend-ui-design", "SKILL.md")
|
|
117
|
-
);
|
|
118
|
-
copyFile(
|
|
119
|
-
srcDir,
|
|
120
|
-
"ai/skills/om-backend-ui-design/references/ui-components.md",
|
|
121
|
-
join(targetDir, ".ai", "skills", "om-backend-ui-design", "references", "ui-components.md")
|
|
122
|
-
);
|
|
123
|
-
copyFile(srcDir, "ai/skills/om-integration-builder/SKILL.md", join(targetDir, ".ai", "skills", "om-integration-builder", "SKILL.md"));
|
|
124
|
-
if (existsSync(join(srcDir, "ai", "skills", "om-integration-builder", "STANDALONE.md"))) {
|
|
125
|
-
copyFile(
|
|
126
|
-
srcDir,
|
|
127
|
-
"ai/skills/om-integration-builder/STANDALONE.md",
|
|
128
|
-
join(targetDir, ".ai", "skills", "om-integration-builder", "STANDALONE.md")
|
|
129
|
-
);
|
|
298
|
+
const paths = /* @__PURE__ */ new Set([
|
|
299
|
+
join(targetDir, "AGENTS.md"),
|
|
300
|
+
...targetPathsForTree(join(srcDir, "ai"), join(targetDir, ".ai")),
|
|
301
|
+
...targetPathsForTree(join(srcDir, "scripts"), join(targetDir, "scripts"))
|
|
302
|
+
]);
|
|
303
|
+
for (const file of readdirSync(GUIDES_DIR)) {
|
|
304
|
+
if (file.endsWith(".md") || file === "module-facts.json") paths.add(join(targetDir, ".ai", "guides", file));
|
|
130
305
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
"ai/skills/om-integration-builder/references/adapter-contracts.md",
|
|
134
|
-
join(targetDir, ".ai", "skills", "om-integration-builder", "references", "adapter-contracts.md")
|
|
135
|
-
);
|
|
136
|
-
if (existsSync(join(srcDir, "ai", "skills", "om-integration-builder", "STANDALONE.md"))) {
|
|
137
|
-
copyFile(
|
|
138
|
-
srcDir,
|
|
139
|
-
"ai/skills/om-integration-builder/STANDALONE.md",
|
|
140
|
-
join(targetDir, ".ai", "skills", "om-integration-builder", "STANDALONE.md")
|
|
141
|
-
);
|
|
306
|
+
for (const file of listFiles(join(GUIDES_DIR, "upstream"))) {
|
|
307
|
+
paths.add(join(targetDir, ".ai", "guides", "upstream", relative(join(GUIDES_DIR, "upstream"), file)));
|
|
142
308
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
"
|
|
146
|
-
join(targetDir, ".
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
);
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
srcDir,
|
|
175
|
-
"ai/skills/om-troubleshooter/references/diagnostic-commands.md",
|
|
176
|
-
join(targetDir, ".ai", "skills", "om-troubleshooter", "references", "diagnostic-commands.md")
|
|
177
|
-
);
|
|
178
|
-
copyFile(
|
|
179
|
-
srcDir,
|
|
180
|
-
"ai/skills/om-eject-and-customize/SKILL.md",
|
|
181
|
-
join(targetDir, ".ai", "skills", "om-eject-and-customize", "SKILL.md")
|
|
182
|
-
);
|
|
183
|
-
copyFile(
|
|
184
|
-
srcDir,
|
|
185
|
-
"ai/skills/om-data-model-design/SKILL.md",
|
|
186
|
-
join(targetDir, ".ai", "skills", "om-data-model-design", "SKILL.md")
|
|
187
|
-
);
|
|
188
|
-
copyFile(
|
|
189
|
-
srcDir,
|
|
190
|
-
"ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md",
|
|
191
|
-
join(targetDir, ".ai", "skills", "om-data-model-design", "references", "mikro-orm-cheatsheet.md")
|
|
192
|
-
);
|
|
193
|
-
copyFile(
|
|
194
|
-
srcDir,
|
|
195
|
-
"ai/skills/om-implement-spec/SKILL.md",
|
|
196
|
-
join(targetDir, ".ai", "skills", "om-implement-spec", "SKILL.md")
|
|
197
|
-
);
|
|
198
|
-
copyFile(
|
|
199
|
-
srcDir,
|
|
200
|
-
"ai/skills/om-help/SKILL.md",
|
|
201
|
-
join(targetDir, ".ai", "skills", "om-help", "SKILL.md")
|
|
202
|
-
);
|
|
203
|
-
copyFile(
|
|
204
|
-
srcDir,
|
|
205
|
-
"ai/skills/om-help/references/skills-catalog.md",
|
|
206
|
-
join(targetDir, ".ai", "skills", "om-help", "references", "skills-catalog.md")
|
|
207
|
-
);
|
|
208
|
-
copyFile(
|
|
209
|
-
srcDir,
|
|
210
|
-
"ai/skills/om-help/references/workflow-sequences.md",
|
|
211
|
-
join(targetDir, ".ai", "skills", "om-help", "references", "workflow-sequences.md")
|
|
212
|
-
);
|
|
213
|
-
copyFile(
|
|
214
|
-
srcDir,
|
|
215
|
-
"ai/skills/om-auto-upgrade-0.4.10-to-0.5.0/SKILL.md",
|
|
216
|
-
join(targetDir, ".ai", "skills", "om-auto-upgrade-0.4.10-to-0.5.0", "SKILL.md")
|
|
309
|
+
for (const moduleId of selectedModules) paths.add(join(targetDir, ".ai", "guides", "modules", `${moduleId}.md`));
|
|
310
|
+
if (selectedTools.includes("claude-code")) {
|
|
311
|
+
paths.add(join(targetDir, "CLAUDE.md"));
|
|
312
|
+
paths.add(join(targetDir, ".claude", "settings.json"));
|
|
313
|
+
paths.add(join(targetDir, ".claude", "hooks", "entity-migration-check.ts"));
|
|
314
|
+
paths.add(join(targetDir, ".mcp.json.example"));
|
|
315
|
+
}
|
|
316
|
+
if (selectedTools.includes("codex")) paths.add(join(targetDir, ".codex", "mcp.json.example"));
|
|
317
|
+
if (selectedTools.includes("cursor")) {
|
|
318
|
+
for (const file of listFiles(join(AGENTIC_DIR, "cursor"))) {
|
|
319
|
+
const rel = relative(join(AGENTIC_DIR, "cursor"), file);
|
|
320
|
+
paths.add(join(targetDir, ".cursor", rel));
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
const manifestPath = join(targetDir, ".ai", "harness", "manifest.json");
|
|
324
|
+
const externalSkills = externalSkillNames(targetDir);
|
|
325
|
+
paths.delete(manifestPath);
|
|
326
|
+
const files = [...paths].filter((path) => existsSync(path)).sort((left, right) => left.localeCompare(right)).map((path) => {
|
|
327
|
+
const relativePath = normalizeManifestRelativePath(relative(targetDir, path));
|
|
328
|
+
const skillName = relativePath.match(/^\.ai\/skills\/([^/]+)\//)?.[1];
|
|
329
|
+
return {
|
|
330
|
+
path: relativePath,
|
|
331
|
+
sha256: hashFile(path),
|
|
332
|
+
source: skillName ? externalSkills.has(skillName) ? "external-override" : "local-skill" : "generated",
|
|
333
|
+
userEditable: relativePath === "AGENTS.md" || relativePath === ".ai/agentic.config.json" || relativePath === ".ai/lessons.md" || relativePath.startsWith(".ai/lessons/")
|
|
334
|
+
};
|
|
335
|
+
});
|
|
336
|
+
atomicWriteFile(
|
|
337
|
+
manifestPath,
|
|
338
|
+
`${JSON.stringify({ version: 1, generator: harnessGeneratorId(), files }, null, 2)}
|
|
339
|
+
`
|
|
217
340
|
);
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
"
|
|
222
|
-
|
|
223
|
-
"
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
341
|
+
}
|
|
342
|
+
function preserveIncomingCandidate(targetRoot, destinationPath, sourcePath, relativePath) {
|
|
343
|
+
for (let suffix = 1; ; suffix += 1) {
|
|
344
|
+
const label = suffix === 1 ? ".incoming" : `.incoming.${suffix}`;
|
|
345
|
+
const candidatePath = `${destinationPath}${label}`;
|
|
346
|
+
assertManagedPath(targetRoot, candidatePath, { leaf: "file" });
|
|
347
|
+
if (!existsSync(candidatePath)) {
|
|
348
|
+
atomicCopyFile(sourcePath, candidatePath, targetRoot);
|
|
349
|
+
return `${relativePath}${label}`;
|
|
350
|
+
}
|
|
351
|
+
if (hashFile(candidatePath) === hashFile(sourcePath)) return `${relativePath}${label}`;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
function applyHarnessUpdate(targetDir, stagingDir, options = {}) {
|
|
355
|
+
const targetRoot = canonicalHarnessRoot(targetDir);
|
|
356
|
+
const stagingRoot = canonicalHarnessRoot(stagingDir);
|
|
357
|
+
const targetManifestPath = join(targetRoot, ".ai", "harness", "manifest.json");
|
|
358
|
+
const stagingManifestPath = join(stagingRoot, ".ai", "harness", "manifest.json");
|
|
359
|
+
assertManagedPath(targetRoot, targetManifestPath, { leaf: "file" });
|
|
360
|
+
assertManagedPath(stagingRoot, stagingManifestPath, { leaf: "file" });
|
|
361
|
+
const candidateManifest = readHarnessManifest(stagingManifestPath);
|
|
362
|
+
if (!candidateManifest) {
|
|
363
|
+
throw new Error("Generated harness candidate has a missing or invalid ownership manifest.");
|
|
364
|
+
}
|
|
365
|
+
const previousManifest = readHarnessManifest(targetManifestPath);
|
|
366
|
+
const previousFiles = new Map(previousManifest?.files.map((entry) => [entry.path, entry]) ?? []);
|
|
367
|
+
const candidatePaths = new Set(candidateManifest.files.map((entry) => entry.path));
|
|
368
|
+
const candidates = [];
|
|
369
|
+
for (const entry of candidateManifest.files) {
|
|
370
|
+
const sourcePath = resolveManifestPath(stagingRoot, entry.path);
|
|
371
|
+
const destinationPath = resolveManifestPath(targetRoot, entry.path);
|
|
372
|
+
if (sourcePath) assertManagedPath(stagingRoot, sourcePath, { leaf: "file" });
|
|
373
|
+
if (destinationPath) assertManagedPath(targetRoot, destinationPath, { leaf: "file" });
|
|
374
|
+
if (!sourcePath || !destinationPath || !existsSync(sourcePath) || hashFile(sourcePath) !== entry.sha256) {
|
|
375
|
+
throw new Error(`Generated harness candidate is invalid for ${JSON.stringify(entry.path)}.`);
|
|
376
|
+
}
|
|
377
|
+
candidates.push({ entry, sourcePath, destinationPath });
|
|
378
|
+
}
|
|
379
|
+
const conflicts = [];
|
|
380
|
+
for (const { entry, sourcePath, destinationPath } of candidates) {
|
|
381
|
+
if (options.force) {
|
|
382
|
+
atomicCopyFile(sourcePath, destinationPath, targetRoot);
|
|
228
383
|
continue;
|
|
229
384
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
);
|
|
385
|
+
if (!existsSync(destinationPath)) {
|
|
386
|
+
atomicCopyFile(sourcePath, destinationPath, targetRoot);
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
const currentHash = hashFile(destinationPath);
|
|
390
|
+
const previousEntry = previousFiles.get(entry.path);
|
|
391
|
+
if (currentHash === entry.sha256 || previousEntry && currentHash === previousEntry.sha256) {
|
|
392
|
+
atomicCopyFile(sourcePath, destinationPath, targetRoot);
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
const candidate = preserveIncomingCandidate(targetRoot, destinationPath, sourcePath, entry.path);
|
|
396
|
+
conflicts.push({ path: entry.path, candidate });
|
|
235
397
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
398
|
+
const retainedRetiredEntries = [];
|
|
399
|
+
for (const previousEntry of previousManifest?.files ?? []) {
|
|
400
|
+
if (candidatePaths.has(previousEntry.path)) continue;
|
|
401
|
+
const destinationPath = resolveManifestPath(targetRoot, previousEntry.path);
|
|
402
|
+
if (!destinationPath || !existsSync(destinationPath)) continue;
|
|
403
|
+
assertManagedPath(targetRoot, destinationPath, { leaf: "file" });
|
|
404
|
+
let unchanged = false;
|
|
405
|
+
try {
|
|
406
|
+
unchanged = hashFile(destinationPath) === previousEntry.sha256;
|
|
407
|
+
} catch {
|
|
408
|
+
}
|
|
409
|
+
if (unchanged) {
|
|
410
|
+
assertManagedPath(targetRoot, dirname(destinationPath));
|
|
411
|
+
assertManagedPath(targetRoot, destinationPath, { leaf: "file" });
|
|
412
|
+
rmSync(destinationPath, { force: true });
|
|
413
|
+
} else {
|
|
414
|
+
retainedRetiredEntries.push(previousEntry);
|
|
415
|
+
conflicts.push({ path: previousEntry.path, candidate: null });
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
const finalManifest = {
|
|
419
|
+
...candidateManifest,
|
|
420
|
+
files: [...candidateManifest.files, ...retainedRetiredEntries]
|
|
421
|
+
};
|
|
422
|
+
atomicWriteFile(targetManifestPath, `${JSON.stringify(finalManifest, null, 2)}
|
|
423
|
+
`, targetRoot);
|
|
424
|
+
return conflicts;
|
|
425
|
+
}
|
|
426
|
+
function generateShared(config) {
|
|
427
|
+
const { targetDir } = config;
|
|
428
|
+
const srcDir = join(AGENTIC_DIR, "shared");
|
|
429
|
+
const selectedModules = selectModuleFactSheets(targetDir, join(GUIDES_DIR, "modules"));
|
|
430
|
+
writeTemplate(srcDir, "AGENTS.md.template", join(targetDir, "AGENTS.md"), config);
|
|
431
|
+
copyTree(join(srcDir, "ai"), join(targetDir, ".ai"), config);
|
|
432
|
+
copyTree(join(srcDir, "scripts"), join(targetDir, "scripts"), config);
|
|
242
433
|
if (existsSync(GUIDES_DIR)) {
|
|
243
434
|
const guidesDestDir = join(targetDir, ".ai", "guides");
|
|
244
435
|
for (const file of readdirSync(GUIDES_DIR)) {
|
|
@@ -254,6 +445,7 @@ function generateShared(config) {
|
|
|
254
445
|
ensureDir(destPath);
|
|
255
446
|
copyFileSync(moduleFactsPath, destPath);
|
|
256
447
|
}
|
|
448
|
+
copyTree(join(GUIDES_DIR, "upstream"), join(guidesDestDir, "upstream"), config);
|
|
257
449
|
const modulesSubdir = join(GUIDES_DIR, "modules");
|
|
258
450
|
for (const moduleId of selectedModules) {
|
|
259
451
|
const destPath = join(guidesDestDir, "modules", `${moduleId}.md`);
|
|
@@ -261,6 +453,7 @@ function generateShared(config) {
|
|
|
261
453
|
copyFileSync(join(modulesSubdir, `${moduleId}.md`), destPath);
|
|
262
454
|
}
|
|
263
455
|
}
|
|
456
|
+
injectModuleGuides(join(targetDir, "AGENTS.md"), selectedModules);
|
|
264
457
|
}
|
|
265
458
|
function generateClaudeCode(config) {
|
|
266
459
|
const { targetDir } = config;
|
|
@@ -269,7 +462,6 @@ function generateClaudeCode(config) {
|
|
|
269
462
|
copyFile(srcDir, "settings.json", join(targetDir, ".claude", "settings.json"));
|
|
270
463
|
copyFile(srcDir, "hooks/entity-migration-check.ts", join(targetDir, ".claude", "hooks", "entity-migration-check.ts"));
|
|
271
464
|
copyFile(srcDir, "mcp.json.example", join(targetDir, ".mcp.json.example"));
|
|
272
|
-
ensureSkillsLink(join(targetDir, ".claude", "skills"), join("..", ".ai", "skills"));
|
|
273
465
|
}
|
|
274
466
|
function generateCodex(config) {
|
|
275
467
|
const { targetDir } = config;
|
|
@@ -308,16 +500,6 @@ function generateCursor(config) {
|
|
|
308
500
|
copyFile(srcDir, "hooks/entity-migration-check.mjs", join(targetDir, ".cursor", "hooks", "entity-migration-check.mjs"));
|
|
309
501
|
copyFile(srcDir, "mcp.json.example", join(targetDir, ".cursor", "mcp.json.example"));
|
|
310
502
|
}
|
|
311
|
-
function ensureSkillsLink(linkPath, target) {
|
|
312
|
-
ensureDir(linkPath);
|
|
313
|
-
if (existsSync(linkPath) && !lstatSync(linkPath).isSymbolicLink()) {
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
if (lstatSync(linkPath, { throwIfNoEntry: false })?.isSymbolicLink()) {
|
|
317
|
-
unlinkSync(linkPath);
|
|
318
|
-
}
|
|
319
|
-
symlinkSync(target, linkPath);
|
|
320
|
-
}
|
|
321
503
|
const TOOLS = [
|
|
322
504
|
{ key: "1", label: "Claude Code (Anthropic)", id: "claude-code" },
|
|
323
505
|
{ key: "2", label: "Codex (OpenAI)", id: "codex" },
|
|
@@ -326,6 +508,30 @@ const TOOLS = [
|
|
|
326
508
|
{ key: "5", label: "Skip \u2014 set up manually later", id: "skip" }
|
|
327
509
|
];
|
|
328
510
|
const SELECTABLE = TOOLS.filter((t) => t.id !== "multiple" && t.id !== "skip");
|
|
511
|
+
function persistedAgentSelection(targetDir) {
|
|
512
|
+
const selectableIds = SELECTABLE.map((tool) => tool.id);
|
|
513
|
+
const tiersPath = join(targetDir, ".ai", "skills", "tiers.json");
|
|
514
|
+
try {
|
|
515
|
+
const tiers = JSON.parse(readFileSync(tiersPath, "utf8"));
|
|
516
|
+
if (Array.isArray(tiers.agents?.ignore) && tiers.agents.ignore.every((id) => typeof id === "string")) {
|
|
517
|
+
const ignored = new Set(tiers.agents.ignore);
|
|
518
|
+
return selectableIds.filter((id) => !ignored.has(id));
|
|
519
|
+
}
|
|
520
|
+
} catch {
|
|
521
|
+
}
|
|
522
|
+
const manifest = readHarnessManifest(join(targetDir, ".ai", "harness", "manifest.json"));
|
|
523
|
+
const owned = new Set(manifest?.files.map((entry) => entry.path) ?? []);
|
|
524
|
+
const selected = SELECTABLE.filter((tool) => {
|
|
525
|
+
if (tool.id === "claude-code") {
|
|
526
|
+
return owned.has("CLAUDE.md") || owned.has(".claude/settings.json") || existsSync(join(targetDir, "CLAUDE.md")) || existsSync(join(targetDir, ".claude", "settings.json"));
|
|
527
|
+
}
|
|
528
|
+
if (tool.id === "codex") {
|
|
529
|
+
return owned.has(".codex/mcp.json.example") || existsSync(join(targetDir, ".codex", "mcp.json.example"));
|
|
530
|
+
}
|
|
531
|
+
return owned.has(".cursor/hooks.json") || existsSync(join(targetDir, ".cursor", "hooks.json"));
|
|
532
|
+
}).map((tool) => tool.id);
|
|
533
|
+
return selected.length > 0 ? selected : null;
|
|
534
|
+
}
|
|
329
535
|
async function promptSelection(ask) {
|
|
330
536
|
console.log("");
|
|
331
537
|
console.log("\u{1F916} Agentic workflow setup");
|
|
@@ -362,6 +568,8 @@ async function runAgenticSetup(targetDir, ask, options) {
|
|
|
362
568
|
let selectedIds;
|
|
363
569
|
if (options?.tool) {
|
|
364
570
|
selectedIds = options.tool.split(",").map((t) => t.trim());
|
|
571
|
+
} else if (options?.updateHarness) {
|
|
572
|
+
selectedIds = persistedAgentSelection(targetDir) ?? await promptSelection(ask);
|
|
365
573
|
} else {
|
|
366
574
|
selectedIds = await promptSelection(ask);
|
|
367
575
|
}
|
|
@@ -375,11 +583,33 @@ async function runAgenticSetup(targetDir, ask, options) {
|
|
|
375
583
|
projectName: basename(targetDir),
|
|
376
584
|
targetDir
|
|
377
585
|
};
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
586
|
+
const stagingDir = mkdtempSync(join(tmpdir(), "open-mercato-harness-"));
|
|
587
|
+
try {
|
|
588
|
+
const modulesSourcePath = join(targetDir, "src", "modules.ts");
|
|
589
|
+
const modulesCandidatePath = join(stagingDir, "src", "modules.ts");
|
|
590
|
+
if (existsSync(modulesSourcePath)) {
|
|
591
|
+
ensureDir(modulesCandidatePath);
|
|
592
|
+
copyFileSync(modulesSourcePath, modulesCandidatePath);
|
|
593
|
+
}
|
|
594
|
+
const stagingConfig = {
|
|
595
|
+
projectName: config.projectName,
|
|
596
|
+
targetDir: stagingDir
|
|
597
|
+
};
|
|
598
|
+
generateHarness(stagingConfig, selectedIds);
|
|
599
|
+
const conflicts = applyHarnessUpdate(targetDir, stagingDir, {
|
|
600
|
+
force: options?.force
|
|
601
|
+
});
|
|
602
|
+
if (conflicts.length > 0) {
|
|
603
|
+
console.warn("");
|
|
604
|
+
console.warn(" \u26A0 Preserved locally modified harness files:");
|
|
605
|
+
for (const conflict of conflicts) {
|
|
606
|
+
const detail = conflict.candidate ? `candidate: ${conflict.candidate}` : "retired asset kept because it has local changes";
|
|
607
|
+
console.warn(` \u2022 ${conflict.path} (${detail})`);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
} finally {
|
|
611
|
+
rmSync(stagingDir, { recursive: true, force: true });
|
|
612
|
+
}
|
|
383
613
|
installSkills(targetDir);
|
|
384
614
|
console.log("");
|
|
385
615
|
console.log(" Agentic setup complete:");
|
|
@@ -399,6 +629,20 @@ async function runAgenticSetup(targetDir, ask, options) {
|
|
|
399
629
|
console.log(" refresh the external open-mercato/skills subset.");
|
|
400
630
|
console.log("");
|
|
401
631
|
}
|
|
632
|
+
function generateHarness(config, selectedIds) {
|
|
633
|
+
generateShared(config);
|
|
634
|
+
if (selectedIds.includes("claude-code")) generateClaudeCode(config);
|
|
635
|
+
if (selectedIds.includes("codex")) generateCodex(config);
|
|
636
|
+
if (selectedIds.includes("cursor")) generateCursor(config);
|
|
637
|
+
enforceGeneratedRootBudget(config);
|
|
638
|
+
persistAgentSelection(config.targetDir, selectedIds);
|
|
639
|
+
finalizeHarnessManifest(config, selectedIds);
|
|
640
|
+
}
|
|
641
|
+
function enforceGeneratedRootBudget(config, maxBytes = STANDALONE_ROOT_TARGET_BYTES) {
|
|
642
|
+
const { targetDir } = config;
|
|
643
|
+
const selectedModules = selectModuleFactSheets(targetDir, join(GUIDES_DIR, "modules"));
|
|
644
|
+
return enforceRootInstructionBudget(join(targetDir, "AGENTS.md"), selectedModules, maxBytes);
|
|
645
|
+
}
|
|
402
646
|
function persistAgentSelection(targetDir, selectedIds) {
|
|
403
647
|
const manifestPath = join(targetDir, ".ai", "skills", "tiers.json");
|
|
404
648
|
if (!existsSync(manifestPath)) return;
|
|
@@ -413,16 +657,20 @@ function persistAgentSelection(targetDir, selectedIds) {
|
|
|
413
657
|
`);
|
|
414
658
|
}
|
|
415
659
|
function installSkills(targetDir) {
|
|
416
|
-
const installScript = join(targetDir, "scripts", "install-skills.
|
|
660
|
+
const installScript = join(targetDir, "scripts", "install-skills.mjs");
|
|
417
661
|
if (!existsSync(installScript)) return;
|
|
418
662
|
console.log("");
|
|
419
663
|
console.log(" Installing agent skills (local tiers + external open-mercato/skills subset)...");
|
|
420
|
-
const result = spawnSync(
|
|
664
|
+
const result = spawnSync(process.execPath, [installScript], { cwd: targetDir, stdio: "inherit" });
|
|
421
665
|
if (result.error || result.status !== 0) {
|
|
422
666
|
console.log(" \u26A0 Skill installation did not complete; run `yarn install-skills` inside the app when online.");
|
|
423
667
|
}
|
|
424
668
|
}
|
|
425
669
|
export {
|
|
670
|
+
STANDALONE_ROOT_TARGET_BYTES,
|
|
671
|
+
applyHarnessUpdate,
|
|
672
|
+
enforceRootInstructionBudget,
|
|
673
|
+
renderModuleGuidesBlock,
|
|
426
674
|
runAgenticSetup
|
|
427
675
|
};
|
|
428
676
|
//# sourceMappingURL=agentic-setup.js.map
|