@open-mercato/cli 0.6.6-develop.6485.1.6021282db1 → 0.6.6-develop.6490.1.bf38ceb3d8
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 +3 -3
- package/dist/agentic/guides/module-facts.json +53 -53
- package/dist/agentic/guides/modules/ai_assistant.md +1 -1
- package/dist/agentic/guides/modules/api_docs.md +1 -1
- package/dist/agentic/guides/modules/api_keys.md +1 -1
- package/dist/agentic/guides/modules/attachments.md +1 -1
- package/dist/agentic/guides/modules/audit_logs.md +1 -1
- package/dist/agentic/guides/modules/auth.md +1 -1
- package/dist/agentic/guides/modules/business_rules.md +1 -1
- package/dist/agentic/guides/modules/catalog.md +1 -1
- package/dist/agentic/guides/modules/channel_gmail.md +1 -1
- package/dist/agentic/guides/modules/channel_imap.md +1 -1
- package/dist/agentic/guides/modules/checkout.md +1 -1
- package/dist/agentic/guides/modules/communication_channels.md +1 -1
- package/dist/agentic/guides/modules/configs.md +1 -1
- package/dist/agentic/guides/modules/content.md +1 -1
- package/dist/agentic/guides/modules/currencies.md +1 -1
- package/dist/agentic/guides/modules/customer_accounts.md +1 -1
- package/dist/agentic/guides/modules/customers.md +1 -1
- package/dist/agentic/guides/modules/dashboards.md +1 -1
- package/dist/agentic/guides/modules/data_sync.md +1 -1
- package/dist/agentic/guides/modules/dictionaries.md +1 -1
- package/dist/agentic/guides/modules/directory.md +1 -1
- package/dist/agentic/guides/modules/entities.md +1 -1
- package/dist/agentic/guides/modules/events.md +1 -1
- package/dist/agentic/guides/modules/feature_toggles.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe.md +1 -1
- package/dist/agentic/guides/modules/generators.md +1 -1
- package/dist/agentic/guides/modules/inbox_ops.md +1 -1
- package/dist/agentic/guides/modules/integrations.md +1 -1
- package/dist/agentic/guides/modules/messages.md +1 -1
- package/dist/agentic/guides/modules/notifications.md +1 -1
- package/dist/agentic/guides/modules/onboarding.md +1 -1
- package/dist/agentic/guides/modules/payment_gateways.md +1 -1
- package/dist/agentic/guides/modules/perspectives.md +1 -1
- package/dist/agentic/guides/modules/planner.md +1 -1
- package/dist/agentic/guides/modules/portal.md +1 -1
- package/dist/agentic/guides/modules/progress.md +1 -1
- package/dist/agentic/guides/modules/query_index.md +1 -1
- package/dist/agentic/guides/modules/record_locks.md +1 -1
- package/dist/agentic/guides/modules/resources.md +1 -1
- package/dist/agentic/guides/modules/sales.md +1 -1
- package/dist/agentic/guides/modules/scheduler.md +1 -1
- package/dist/agentic/guides/modules/search.md +1 -1
- package/dist/agentic/guides/modules/security.md +1 -1
- package/dist/agentic/guides/modules/shipping_carriers.md +1 -1
- package/dist/agentic/guides/modules/sso.md +1 -1
- package/dist/agentic/guides/modules/staff.md +1 -1
- package/dist/agentic/guides/modules/storage_s3.md +1 -1
- package/dist/agentic/guides/modules/sync_akeneo.md +1 -1
- package/dist/agentic/guides/modules/sync_excel.md +1 -1
- package/dist/agentic/guides/modules/system_status_overlays.md +1 -1
- package/dist/agentic/guides/modules/translations.md +1 -1
- package/dist/agentic/guides/modules/webhooks.md +1 -1
- package/dist/agentic/guides/modules/workflows.md +1 -1
- package/dist/agentic/shared/AGENTS.md.template +8 -2
- package/dist/agentic/shared/ai/skills/om-help/references/skills-catalog.md +4 -1
- package/dist/agentic/shared/ai/skills/om-prepare-test-env/SKILL.md +70 -0
- package/dist/agentic/shared/ai/skills/tiers.json +8 -1
- package/dist/lib/__integration__/TC-INT-008.spec.js +25 -9
- package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
- package/dist/lib/agentic-setup.js +19 -1
- package/dist/lib/agentic-setup.js.map +2 -2
- package/package.json +5 -5
- package/src/lib/__integration__/TC-INT-008.spec.ts +34 -10
- package/src/lib/agentic-setup.ts +22 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# feature_toggles — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/core 0.6.6-develop.
|
|
2
|
+
<!-- generated from @open-mercato/core 0.6.6-develop.6490.1.bf38ceb3d8 — R1 staleness stamp -->
|
|
3
3
|
|
|
4
4
|
## Entities
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# gateway_stripe — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/core 0.6.6-develop.
|
|
2
|
+
<!-- generated from @open-mercato/core 0.6.6-develop.6490.1.bf38ceb3d8 — R1 staleness stamp -->
|
|
3
3
|
|
|
4
4
|
## Entities
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# payment_gateways — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/core 0.6.6-develop.
|
|
2
|
+
<!-- generated from @open-mercato/core 0.6.6-develop.6490.1.bf38ceb3d8 — R1 staleness stamp -->
|
|
3
3
|
|
|
4
4
|
## Entities
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# shipping_carriers — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/core 0.6.6-develop.
|
|
2
|
+
<!-- generated from @open-mercato/core 0.6.6-develop.6490.1.bf38ceb3d8 — R1 staleness stamp -->
|
|
3
3
|
|
|
4
4
|
## Entities
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# system_status_overlays — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/core 0.6.6-develop.
|
|
2
|
+
<!-- generated from @open-mercato/core 0.6.6-develop.6490.1.bf38ceb3d8 — R1 staleness stamp -->
|
|
3
3
|
|
|
4
4
|
## Entities
|
|
5
5
|
|
|
@@ -79,6 +79,9 @@ Skills come from two places. Repo-local skills (module scaffolding, UI design, t
|
|
|
79
79
|
| Write a spec | `om-spec-writing` (external — `yarn install-skills`), `.ai/specs/SPEC-000-template.md` |
|
|
80
80
|
| Implement a spec (or selected phases) | `.ai/skills/om-implement-spec/SKILL.md` |
|
|
81
81
|
| Create / run integration tests | `om-integration-tests` (external — `yarn install-skills`) |
|
|
82
|
+
| Prepare / reuse a local test environment (shared descriptor for QA + integration tests) | `om-prepare-test-env` (external — invoked by `om-integration-tests` when no environment is running) |
|
|
83
|
+
| Configure or re-configure the agent PR pipeline (`.ai/agentic.config.json`, tracker, labels, QA gate) | `om-setup-agent-pipeline` (external) |
|
|
84
|
+
| Sync installed pipeline artifacts after `yarn install-skills` refreshed the collection | `om-apply-upgrade-notes` (external) |
|
|
82
85
|
| Upgrade framework from 0.4.10 to 0.5.0 | `.ai/skills/om-auto-upgrade-0.4.10-to-0.5.0/SKILL.md` |
|
|
83
86
|
|
|
84
87
|
### Agent Automation / Auto-Skills
|
|
@@ -92,10 +95,10 @@ These skills are installed from the shared collection by `yarn install-skills` (
|
|
|
92
95
|
| Run a long multi-step spec implementation with resumable checkpoints | `om-auto-create-pr-loop` (external) |
|
|
93
96
|
| Resume a checkpointed PR started by `om-auto-create-pr-loop` | `om-auto-continue-pr-loop` (external) |
|
|
94
97
|
| Automated code review on a PR (with optional autofix) | `om-auto-review-pr` (external) |
|
|
95
|
-
| Fix a GitHub issue by number and open a PR | `om-auto-fix-issue` (external) |
|
|
98
|
+
| Fix a GitHub issue by number and open a PR | `om-auto-fix-issue` (external — drives the chain `om-verify-in-repo` → `om-root-cause` → `om-fix` → `om-open-pr` → `om-auto-review-pr`, all installed alongside it) |
|
|
96
99
|
| Propose disabling unused built-in modules after the user adds a new module (classic-mode slimdown) | `.ai/skills/om-trim-unused-modules/SKILL.md` |
|
|
97
100
|
|
|
98
|
-
Invoke these as slash commands in your agent CLI (Claude Code, Codex, …), for example `/auto-create-pr add rate-limiting to the products API` or `/auto-fix-issue 42`. The skills read `.ai/agentic.config.json` (base branch `auto`, resolved via the tracker descriptor's **default-branch** operation; pipeline labels off by default; the standalone validation-gate command list) and perform every GitHub interaction through the tracker descriptor `.ai/trackers/github.md
|
|
101
|
+
Invoke these as slash commands in your agent CLI (Claude Code, Codex, …), for example `/auto-create-pr add rate-limiting to the products API` or `/auto-fix-issue 42`. The skills read `.ai/agentic.config.json` (base branch `auto`, resolved via the tracker descriptor's **default-branch** operation; pipeline labels off by default; the standalone validation-gate command list) and perform every GitHub interaction through the tracker descriptor `.ai/trackers/github.md`. That config ships preconfigured, so the skills work without any setup step — run `/om-setup-agent-pipeline` when you want to tailor it: enable the full label pipeline (`labels.enabled: true` plus the tracker's **ensure-label-taxonomy** operation) and the QA gate, switch tracker, or change the validation commands. After `yarn install-skills` refreshes the external collection, run `/om-apply-upgrade-notes` to bring the installed artifacts (tracker descriptor, config) up to date with the new skill versions.
|
|
99
102
|
|
|
100
103
|
## Module Anatomy
|
|
101
104
|
|
|
@@ -291,6 +294,9 @@ import type { ApiInterceptor } from '@open-mercato/shared/lib/crud/api-intercept
|
|
|
291
294
|
| `yarn initialize` | Bootstrap DB + first admin account |
|
|
292
295
|
| `yarn build` | Build for production |
|
|
293
296
|
| `yarn mercato eject <module>` | Copy a core module into `src/modules/` |
|
|
297
|
+
| `yarn test:integration:ephemeral` | Run Playwright integration tests against a fresh ephemeral app + DB (reuses a healthy running env) |
|
|
298
|
+
| `yarn mercato test:ephemeral` | Start the ephemeral app only (manual QA; admin@acme.com / secret) — the `om-prepare-test-env` skill wraps this and shares the env via `.ai/qa/test-env.json` |
|
|
299
|
+
| `npx playwright show-report .ai/qa/test-results/html` | Open the HTML integration test report |
|
|
294
300
|
|
|
295
301
|
## Architecture Rules
|
|
296
302
|
|
|
@@ -60,8 +60,11 @@ Skills for modifying or extending behavior without touching core module source.
|
|
|
60
60
|
| `om-auto-create-pr-loop` | Long multi-step implementation with step-level resumability | — | `om-auto-review-pr` |
|
|
61
61
|
| `om-auto-continue-pr-loop` | Resume a PR started by `om-auto-create-pr-loop` | — | `om-auto-review-pr` |
|
|
62
62
|
| `om-auto-review-pr` | Automated PR review + approve/request-changes | `om-auto-create-pr` | — |
|
|
63
|
-
| `om-auto-fix-issue` | Fix a GitHub issue end-to-end | — | `om-auto-create-pr` |
|
|
63
|
+
| `om-auto-fix-issue` | Fix a GitHub issue end-to-end (drives `om-verify-in-repo` → `om-root-cause` → `om-fix` → `om-open-pr`) | — | `om-auto-create-pr` |
|
|
64
64
|
| `om-prepare-issue` | Capture a feature to build later — write the spec, ship a docs-only spec PR, open a tracking issue | `om-spec-writing` | `om-implement-spec` |
|
|
65
|
+
| `om-prepare-test-env` | Boot a reusable local test environment (shared descriptor for QA + integration tests) | — | `om-integration-tests` |
|
|
66
|
+
| `om-setup-agent-pipeline` | Tailor `.ai/agentic.config.json` (labels, QA gate, tracker, validation commands) — the scaffold ships working defaults | — | any auto-skill |
|
|
67
|
+
| `om-apply-upgrade-notes` | Sync installed pipeline artifacts after `yarn install-skills` refreshed the external collection | — | — |
|
|
65
68
|
|
|
66
69
|
---
|
|
67
70
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: om-prepare-test-env
|
|
3
|
+
description: Repo-local extension of the shared om-prepare-test-env skill. Adds this standalone Open Mercato app's environment specifics — the mercato CLI ephemeral runner commands, state-file semantics, readiness-probe contract, and the rule that generated entrypoint scripts stay machine-local — on top of the shared skill's workflow. Local rules win on repo specifics only; this file never relaxes the shared skill's safety rules.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Prepare Test Environment — standalone app rules
|
|
7
|
+
|
|
8
|
+
Repo-local **extension** of the installed `om-prepare-test-env` skill (contract v2,
|
|
9
|
+
compile-once). Everything there applies; this file only adds repository-provided configuration.
|
|
10
|
+
It cannot relax the shared skill's safety rules, expand tool or network access, or redirect
|
|
11
|
+
outputs.
|
|
12
|
+
|
|
13
|
+
## Use the app's own tooling — it is already cross-platform
|
|
14
|
+
|
|
15
|
+
This app ships an ephemeral test runner inside the mercato CLI. Discovery is unnecessary: wrap
|
|
16
|
+
these `package.json` / CLI commands instead of inventing a boot procedure. They own build
|
|
17
|
+
caching, database provisioning (testcontainers), seeding, readiness waits, and their own
|
|
18
|
+
owner lock — never re-implement any of that.
|
|
19
|
+
|
|
20
|
+
- Boot app-only ephemeral env: `yarn mercato test:ephemeral`. Preferred app port `5001`; the
|
|
21
|
+
actual port and database URL land in `.ai/qa/ephemeral-env.json` (CLI-owned and authoritative
|
|
22
|
+
for its own reuse decisions — never write it by hand).
|
|
23
|
+
- Full suite with managed env: `yarn test:integration:ephemeral` (= `yarn mercato test:integration`).
|
|
24
|
+
It reuses a healthy running ephemeral env from the state file, else provisions one.
|
|
25
|
+
- Filtered run: `yarn mercato test:integration <substring>` — batches all specs whose path
|
|
26
|
+
matches the substring.
|
|
27
|
+
- Interactive runner: `yarn mercato test:integration:interactive`.
|
|
28
|
+
- Readiness marker in the boot log: `Application is ready at <baseUrl>`.
|
|
29
|
+
- Reuse TTL: `OM_INTEGRATION_BUILD_CACHE_TTL_SECONDS` (default 600s) gates the CLI's own reuse;
|
|
30
|
+
keep any wrapper TTL in lockstep with it.
|
|
31
|
+
|
|
32
|
+
## MUST: suite runs go through the CLI runner
|
|
33
|
+
|
|
34
|
+
`yarn test:integration` with only `BASE_URL` exported is a trap: the CLI runner injects a full
|
|
35
|
+
env block into the Playwright process (`DATABASE_URL` for the ephemeral DB, queue dirs, JWT and
|
|
36
|
+
webhook secrets). Without it, fixtures silently hit the dev database from `.env`. Always run
|
|
37
|
+
suites via `yarn test:integration:ephemeral [filter]`.
|
|
38
|
+
|
|
39
|
+
## Readiness probe contract
|
|
40
|
+
|
|
41
|
+
- Shell: `GET /login` → 200.
|
|
42
|
+
- Authenticated round trip: `POST /api/auth/login` with a **form-encoded** body
|
|
43
|
+
(`email=admin@acme.com&password=secret`) → 200. The endpoint rejects JSON bodies with 400 —
|
|
44
|
+
a JSON 400 here means a malformed probe, not a broken app.
|
|
45
|
+
- Seeded credentials: `admin@acme.com` / `secret`, `employee@acme.com` / `secret`, superadmin
|
|
46
|
+
from `OM_INIT_SUPERADMIN_EMAIL` / `OM_INIT_SUPERADMIN_PASSWORD` (default
|
|
47
|
+
`superadmin@acme.com` / `secret`).
|
|
48
|
+
|
|
49
|
+
## Generated entrypoint scripts are machine-local
|
|
50
|
+
|
|
51
|
+
When the shared skill compiles its entrypoint scripts (default `.ai/scripts/test-env-up.sh` /
|
|
52
|
+
`test-env-down.sh`), they are bound to the machine that generated them (shell, process tools,
|
|
53
|
+
ports). They are gitignored in this repo (`.ai/scripts/test-env-*`) — keep them local and NEVER
|
|
54
|
+
commit them; anything worth preserving for teammates belongs in this file as a platform-neutral
|
|
55
|
+
rule instead. On a machine without generated scripts, regenerate from the commands above.
|
|
56
|
+
|
|
57
|
+
## Teardown
|
|
58
|
+
|
|
59
|
+
Stop the CLI owner process (`test:ephemeral`) and the app process bound to the recorded port,
|
|
60
|
+
then delete `.ai/qa/ephemeral-env.json`. If a `mercato server start` wrapper survives, stop it
|
|
61
|
+
and clear `.mercato/server-start.lock` — a surviving wrapper keeps the single-instance guard
|
|
62
|
+
locked and the next boot dies with "Another Open Mercato production server is already running".
|
|
63
|
+
The ephemeral Postgres containers are testcontainers-managed; ryuk reaps them once their owner
|
|
64
|
+
is gone — never remove containers this app did not create.
|
|
65
|
+
|
|
66
|
+
## Descriptor
|
|
67
|
+
|
|
68
|
+
After boot, mirror the state into `.ai/qa/test-env.json` (the shared descriptor) as the shared
|
|
69
|
+
skill prescribes, so `om-integration-tests` and `om-auto-verify-pr-ui` attach to the same
|
|
70
|
+
instance; `.ai/qa/ephemeral-env.json` stays authoritative for the CLI's own reuse decisions.
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
"source": "open-mercato/skills",
|
|
6
6
|
"description": "Skills installed from the shared open-mercato/skills collection via `npx skills add` (see scripts/install-skills.sh). Only the subset this standalone app ships is installed. A folder under .ai/skills/ matching one of these names is a repo-local override read by the external skill, never symlinked into the harness directories.",
|
|
7
7
|
"skills": [
|
|
8
|
+
"om-apply-upgrade-notes",
|
|
8
9
|
"om-auto-continue-pr",
|
|
9
10
|
"om-auto-continue-pr-loop",
|
|
10
11
|
"om-auto-create-pr",
|
|
@@ -12,9 +13,15 @@
|
|
|
12
13
|
"om-auto-fix-issue",
|
|
13
14
|
"om-auto-review-pr",
|
|
14
15
|
"om-code-review",
|
|
16
|
+
"om-fix",
|
|
15
17
|
"om-integration-tests",
|
|
18
|
+
"om-open-pr",
|
|
16
19
|
"om-prepare-issue",
|
|
17
|
-
"om-
|
|
20
|
+
"om-prepare-test-env",
|
|
21
|
+
"om-root-cause",
|
|
22
|
+
"om-setup-agent-pipeline",
|
|
23
|
+
"om-spec-writing",
|
|
24
|
+
"om-verify-in-repo"
|
|
18
25
|
]
|
|
19
26
|
},
|
|
20
27
|
"tiers": {
|
|
@@ -25,7 +25,11 @@ function runCommand(command, args, cwd) {
|
|
|
25
25
|
env: {
|
|
26
26
|
...process.env,
|
|
27
27
|
FORCE_COLOR: "0",
|
|
28
|
-
NODE_NO_WARNINGS: "1"
|
|
28
|
+
NODE_NO_WARNINGS: "1",
|
|
29
|
+
// Keep the test hermetic: agentic:init runs scripts/install-skills.sh,
|
|
30
|
+
// whose external step (`npx skills add`) needs the network. Local tier
|
|
31
|
+
// symlinks are still installed.
|
|
32
|
+
OM_SKIP_EXTERNAL_SKILLS: "1"
|
|
29
33
|
}
|
|
30
34
|
});
|
|
31
35
|
}
|
|
@@ -82,6 +86,9 @@ function mapSharedSourceToOutput(relativePath) {
|
|
|
82
86
|
if (relativePath === "AGENTS.md.template") {
|
|
83
87
|
return "AGENTS.md";
|
|
84
88
|
}
|
|
89
|
+
if (relativePath.startsWith("scripts/")) {
|
|
90
|
+
return relativePath;
|
|
91
|
+
}
|
|
85
92
|
if (!relativePath.startsWith("ai/")) {
|
|
86
93
|
throw new Error(`Unexpected shared source path: ${relativePath}`);
|
|
87
94
|
}
|
|
@@ -219,15 +226,24 @@ test.describe("TC-INT-008: CLI agentic init mirrors standalone scaffolding asset
|
|
|
219
226
|
expect(specsReadmeSource).toContain("sample-store");
|
|
220
227
|
const cursorRulesSource = fs.readFileSync(path.join(appDir, ".cursor", "rules", "open-mercato.mdc"), "utf8");
|
|
221
228
|
expect(cursorRulesSource).toContain("sample-store");
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
229
|
+
expect(fs.existsSync(path.join(appDir, ".ai", "skills", "om-spec-writing"))).toBe(false);
|
|
230
|
+
expect(fs.existsSync(path.join(appDir, "scripts", "install-skills.sh"))).toBe(true);
|
|
231
|
+
const cursorSkillsLinkPath = path.join(appDir, ".cursor", "skills");
|
|
232
|
+
expect(fs.lstatSync(cursorSkillsLinkPath).isSymbolicLink()).toBe(true);
|
|
233
|
+
expect(normalizePath(fs.readlinkSync(cursorSkillsLinkPath))).toBe("../.ai/skills");
|
|
234
|
+
const tiersManifest = JSON.parse(
|
|
235
|
+
fs.readFileSync(path.join(agenticRoot, "shared", "ai", "skills", "tiers.json"), "utf8")
|
|
225
236
|
);
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
expect(
|
|
237
|
+
const defaultTierSkills = tiersManifest.default.flatMap((tierName) => tiersManifest.tiers[tierName].skills);
|
|
238
|
+
expect(defaultTierSkills.length).toBeGreaterThan(0);
|
|
239
|
+
for (const toolDir of [".claude", ".codex"]) {
|
|
240
|
+
const harnessSkillsDir = path.join(appDir, toolDir, "skills");
|
|
241
|
+
expect(fs.lstatSync(harnessSkillsDir).isDirectory()).toBe(true);
|
|
242
|
+
for (const skillName of defaultTierSkills) {
|
|
243
|
+
const skillLinkPath = path.join(harnessSkillsDir, skillName);
|
|
244
|
+
expect(fs.lstatSync(skillLinkPath).isSymbolicLink()).toBe(true);
|
|
245
|
+
expect(normalizePath(fs.readlinkSync(skillLinkPath))).toBe(`../../.ai/skills/${skillName}`);
|
|
246
|
+
}
|
|
231
247
|
}
|
|
232
248
|
} finally {
|
|
233
249
|
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/__integration__/TC-INT-008.spec.ts"],
|
|
4
|
-
"sourcesContent": ["import { expect, test } from '@playwright/test'\nimport { execFileSync } from 'node:child_process'\nimport fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { MODULE_FACTS_ALLOWLIST } from '../generators/module-facts'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\nconst repoRoot = path.resolve(__dirname, '..', '..', '..', '..', '..')\nconst cliDir = path.join(repoRoot, 'packages', 'cli')\nconst cliBin = path.join(cliDir, 'dist', 'bin.js')\nconst cliBuildScript = path.join(cliDir, 'build.mjs')\nconst cliIntegrationRunnerPath = path.join(cliDir, 'src', 'lib', 'testing', 'integration.ts')\nconst standaloneTemplatePackageJsonPath = path.join(repoRoot, 'packages', 'create-app', 'template', 'package.json.template')\nconst agenticRoot = path.join(repoRoot, 'packages', 'create-app', 'agentic')\nconst packagesRoot = path.join(repoRoot, 'packages')\n\n// Modules the standalone fixture enables in src/modules.ts. Both are on the\n// fact-sheet allowlist, so agentic:init must ship exactly their fact-sheets\n// (enabled \u2229 allowlist \u2014 spec D6) and list them in the AGENTS.md marker block.\nconst FIXTURE_ENABLED_MODULES = ['customers', 'sales']\n\nfunction normalizePath(value: string): string {\n return value.split(path.sep).join('/')\n}\n\nfunction runCommand(command: string, args: string[], cwd: string): string {\n return execFileSync(command, args, {\n cwd,\n encoding: 'utf8',\n env: {\n ...process.env,\n FORCE_COLOR: '0',\n NODE_NO_WARNINGS: '1',\n },\n })\n}\n\nfunction runMercato(args: string[], cwd: string): string {\n return runCommand(process.execPath, [cliBin, ...args], cwd)\n}\n\nfunction writeFile(filePath: string, content: string): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true })\n fs.writeFileSync(filePath, content)\n}\n\nfunction ensureCliBuilt(): void {\n runCommand(process.execPath, [cliBuildScript], cliDir)\n}\n\nfunction createStandaloneFixture(rootDir: string): string {\n const appDir = path.join(rootDir, 'sample-store')\n writeFile(\n path.join(appDir, 'package.json'),\n JSON.stringify(\n {\n name: 'sample-store',\n private: true,\n },\n null,\n 2,\n ),\n )\n const moduleEntries = FIXTURE_ENABLED_MODULES.map((moduleId) => ` { id: '${moduleId}' },`).join('\\n')\n writeFile(path.join(appDir, 'src', 'modules.ts'), `export const enabledModules = [\\n${moduleEntries}\\n]\\n`)\n return appDir\n}\n\nfunction listRelativeFiles(rootDir: string): string[] {\n if (!fs.existsSync(rootDir)) {\n return []\n }\n\n const collected: string[] = []\n for (const entry of fs.readdirSync(rootDir, { withFileTypes: true })) {\n const absolutePath = path.join(rootDir, entry.name)\n if (entry.isDirectory()) {\n for (const nestedPath of listRelativeFiles(absolutePath)) {\n collected.push(path.join(entry.name, nestedPath))\n }\n continue\n }\n if (entry.isFile()) {\n collected.push(entry.name)\n }\n }\n\n return collected.map(normalizePath).sort()\n}\n\nfunction mapSharedSourceToOutput(relativePath: string): string {\n if (relativePath === 'AGENTS.md.template') {\n return 'AGENTS.md'\n }\n\n if (!relativePath.startsWith('ai/')) {\n throw new Error(`Unexpected shared source path: ${relativePath}`)\n }\n\n return normalizePath(path.join('.ai', relativePath.slice('ai/'.length)))\n}\n\nfunction mapClaudeSourceToOutput(relativePath: string): string {\n if (relativePath === 'CLAUDE.md.template') {\n return 'CLAUDE.md'\n }\n if (relativePath === 'settings.json') {\n return '.claude/settings.json'\n }\n if (relativePath === 'mcp.json.example') {\n return '.mcp.json.example'\n }\n if (relativePath.startsWith('hooks/')) {\n return normalizePath(path.join('.claude', relativePath))\n }\n\n throw new Error(`Unexpected Claude source path: ${relativePath}`)\n}\n\nfunction mapCursorSourceToOutput(relativePath: string): string {\n if (relativePath === 'hooks.json') {\n return '.cursor/hooks.json'\n }\n if (relativePath === 'mcp.json.example') {\n return '.cursor/mcp.json.example'\n }\n if (relativePath.startsWith('hooks/') || relativePath.startsWith('rules/')) {\n return normalizePath(path.join('.cursor', relativePath))\n }\n\n throw new Error(`Unexpected Cursor source path: ${relativePath}`)\n}\n\nfunction mapCodexSourceToOutput(relativePath: string): string | null {\n if (relativePath === 'mcp.json.example') {\n return '.codex/mcp.json.example'\n }\n if (relativePath === 'enforcement-rules.md') {\n return null\n }\n\n throw new Error(`Unexpected Codex source path: ${relativePath}`)\n}\n\nfunction readPlaywrightConfigPathFromTemplate(): string {\n const packageTemplate = JSON.parse(fs.readFileSync(standaloneTemplatePackageJsonPath, 'utf8')) as {\n scripts?: Record<string, string>\n }\n const integrationScript = packageTemplate.scripts?.['test:integration']\n if (!integrationScript) {\n throw new Error('Standalone template is missing the test:integration script')\n }\n\n const configPathMatch = integrationScript.match(/--config\\s+([^\\s]+)/)\n if (!configPathMatch?.[1]) {\n throw new Error('Standalone template test:integration script is missing --config')\n }\n\n return normalizePath(configPathMatch[1])\n}\n\nfunction readPlaywrightConfigPathFromCliRunner(): string {\n const integrationRunnerSource = fs.readFileSync(cliIntegrationRunnerPath, 'utf8')\n const configPathMatch = integrationRunnerSource.match(/const PLAYWRIGHT_INTEGRATION_CONFIG_PATH = '([^']+)'/)\n if (!configPathMatch?.[1]) {\n throw new Error('CLI integration runner is missing PLAYWRIGHT_INTEGRATION_CONFIG_PATH')\n }\n\n return normalizePath(configPathMatch[1])\n}\n\nfunction expectedGuideOutputNames(): string[] {\n const collected = new Set<string>()\n\n // Static conceptual guides checked into create-app (e.g. module-system.md) are\n // bundled into dist/agentic/guides by the CLI build and copied wholesale.\n const staticGuidesRoot = path.join(agenticRoot, 'guides')\n if (fs.existsSync(staticGuidesRoot)) {\n for (const entry of fs.readdirSync(staticGuidesRoot, { withFileTypes: true })) {\n if (entry.isFile() && entry.name.endsWith('.md')) {\n collected.add(entry.name)\n }\n }\n }\n\n for (const packageName of fs.readdirSync(packagesRoot)) {\n const packageGuide = path.join(packagesRoot, packageName, 'agentic', 'standalone-guide.md')\n if (fs.existsSync(packageGuide)) {\n collected.add(`${packageName}.md`)\n }\n\n const modulesRoot = path.join(packagesRoot, packageName, 'src', 'modules')\n if (!fs.existsSync(modulesRoot)) {\n continue\n }\n\n for (const moduleName of fs.readdirSync(modulesRoot)) {\n const moduleGuide = path.join(modulesRoot, moduleName, 'agentic', 'standalone-guide.md')\n if (fs.existsSync(moduleGuide)) {\n collected.add(`${packageName}.${moduleName}.md`)\n }\n }\n }\n\n // Generated fact-sheet artifacts (spec 2026-06-27-ts-morph-module-fact-sheets):\n // the module-facts.json sidecar is copied as-is, fact-sheets are filtered to the\n // fixture's enabled modules, and every allowlisted module whose hand-written\n // core.<module>.md guide no longer exists gets a legacy redirect stub.\n collected.add('module-facts.json')\n for (const moduleId of FIXTURE_ENABLED_MODULES) {\n collected.add(normalizePath(path.join('modules', `${moduleId}.md`)))\n }\n for (const moduleId of MODULE_FACTS_ALLOWLIST) {\n const legacyGuideSource = path.join(packagesRoot, 'core', 'src', 'modules', moduleId, 'agentic', 'standalone-guide.md')\n if (!fs.existsSync(legacyGuideSource)) {\n collected.add(`core.${moduleId}.md`)\n }\n }\n\n return Array.from(collected).sort()\n}\n\nfunction assertPathsExist(appDir: string, relativePaths: string[]): void {\n const missingPaths = relativePaths.filter((relativePath) => !fs.existsSync(path.join(appDir, relativePath)))\n expect(missingPaths).toEqual([])\n}\n\ntest.describe('TC-INT-008: CLI agentic init mirrors standalone scaffolding assets', () => {\n test.beforeAll(() => {\n ensureCliBuilt()\n })\n\n test('should run bootstrap-free and generate the shared, guide, and tool-specific agentic files', () => {\n const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-agentic-'))\n\n try {\n const appDir = createStandaloneFixture(tempRoot)\n const standalonePlaywrightConfigPath = readPlaywrightConfigPathFromTemplate()\n const cliPlaywrightConfigPath = readPlaywrightConfigPathFromCliRunner()\n const commandOutput = runMercato(['agentic:init', '--tool=claude-code,codex,cursor'], appDir)\n\n expect(cliPlaywrightConfigPath).toBe(standalonePlaywrightConfigPath)\n expect(commandOutput).toContain('Agentic setup complete:')\n expect(fs.existsSync(path.join(appDir, '.mercato', 'generated'))).toBe(false)\n\n const sharedOutputs = listRelativeFiles(path.join(agenticRoot, 'shared')).map(mapSharedSourceToOutput)\n const claudeOutputs = listRelativeFiles(path.join(agenticRoot, 'claude-code')).map(mapClaudeSourceToOutput)\n const cursorOutputs = listRelativeFiles(path.join(agenticRoot, 'cursor')).map(mapCursorSourceToOutput)\n const codexOutputs = listRelativeFiles(path.join(agenticRoot, 'codex'))\n .map(mapCodexSourceToOutput)\n .filter((relativePath): relativePath is string => relativePath !== null)\n\n expect(sharedOutputs).toContain(standalonePlaywrightConfigPath)\n assertPathsExist(appDir, [...sharedOutputs, ...claudeOutputs, ...cursorOutputs, ...codexOutputs])\n expect(fs.existsSync(path.join(appDir, standalonePlaywrightConfigPath))).toBe(true)\n\n const generatedGuideNames = listRelativeFiles(path.join(appDir, '.ai', 'guides'))\n expect(generatedGuideNames).toEqual(expectedGuideOutputNames())\n\n const agentsSource = fs.readFileSync(path.join(appDir, 'AGENTS.md'), 'utf8')\n expect(agentsSource).toContain('<!-- CODEX_ENFORCEMENT_RULES_START -->')\n expect(agentsSource).toContain('.ai/guides/core.md')\n\n // The Module-Specific Guides marker block lists exactly the enabled modules'\n // fact-sheets (enabled \u2229 allowlist), not the full bundled set.\n for (const moduleId of FIXTURE_ENABLED_MODULES) {\n expect(agentsSource).toContain(`.ai/guides/modules/${moduleId}.md`)\n }\n expect(agentsSource).not.toContain('.ai/guides/modules/auth.md')\n\n const specsReadmeSource = fs.readFileSync(path.join(appDir, '.ai', 'specs', 'README.md'), 'utf8')\n expect(specsReadmeSource).toContain('sample-store')\n\n const cursorRulesSource = fs.readFileSync(path.join(appDir, '.cursor', 'rules', 'open-mercato.mdc'), 'utf8')\n expect(cursorRulesSource).toContain('sample-store')\n\n const specWritingSkillSource = fs.readFileSync(\n path.join(appDir, '.ai', 'skills', 'om-spec-writing', 'SKILL.md'),\n 'utf8',\n )\n expect(specWritingSkillSource).toContain('sample-store')\n\n for (const toolDir of ['.claude', '.codex', '.cursor']) {\n const skillsLinkPath = path.join(appDir, toolDir, 'skills')\n expect(fs.lstatSync(skillsLinkPath).isSymbolicLink()).toBe(true)\n expect(normalizePath(fs.readlinkSync(skillsLinkPath))).toBe('../.ai/skills')\n }\n } finally {\n fs.rmSync(tempRoot, { recursive: true, force: true })\n }\n })\n})\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,QAAQ,YAAY;AAC7B,SAAS,oBAAoB;AAC7B,OAAO,QAAQ;AACf,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAC9B,SAAS,8BAA8B;AAEvC,MAAM,YAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAC7D,MAAM,WAAW,KAAK,QAAQ,WAAW,MAAM,MAAM,MAAM,MAAM,IAAI;AACrE,MAAM,SAAS,KAAK,KAAK,UAAU,YAAY,KAAK;AACpD,MAAM,SAAS,KAAK,KAAK,QAAQ,QAAQ,QAAQ;AACjD,MAAM,iBAAiB,KAAK,KAAK,QAAQ,WAAW;AACpD,MAAM,2BAA2B,KAAK,KAAK,QAAQ,OAAO,OAAO,WAAW,gBAAgB;AAC5F,MAAM,oCAAoC,KAAK,KAAK,UAAU,YAAY,cAAc,YAAY,uBAAuB;AAC3H,MAAM,cAAc,KAAK,KAAK,UAAU,YAAY,cAAc,SAAS;AAC3E,MAAM,eAAe,KAAK,KAAK,UAAU,UAAU;AAKnD,MAAM,0BAA0B,CAAC,aAAa,OAAO;AAErD,SAAS,cAAc,OAAuB;AAC5C,SAAO,MAAM,MAAM,KAAK,GAAG,EAAE,KAAK,GAAG;AACvC;AAEA,SAAS,WAAW,SAAiB,MAAgB,KAAqB;AACxE,SAAO,aAAa,SAAS,MAAM;AAAA,IACjC;AAAA,IACA,UAAU;AAAA,IACV,KAAK;AAAA,MACH,GAAG,QAAQ;AAAA,MACX,aAAa;AAAA,MACb,kBAAkB;AAAA,
|
|
4
|
+
"sourcesContent": ["import { expect, test } from '@playwright/test'\nimport { execFileSync } from 'node:child_process'\nimport fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { MODULE_FACTS_ALLOWLIST } from '../generators/module-facts'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\nconst repoRoot = path.resolve(__dirname, '..', '..', '..', '..', '..')\nconst cliDir = path.join(repoRoot, 'packages', 'cli')\nconst cliBin = path.join(cliDir, 'dist', 'bin.js')\nconst cliBuildScript = path.join(cliDir, 'build.mjs')\nconst cliIntegrationRunnerPath = path.join(cliDir, 'src', 'lib', 'testing', 'integration.ts')\nconst standaloneTemplatePackageJsonPath = path.join(repoRoot, 'packages', 'create-app', 'template', 'package.json.template')\nconst agenticRoot = path.join(repoRoot, 'packages', 'create-app', 'agentic')\nconst packagesRoot = path.join(repoRoot, 'packages')\n\n// Modules the standalone fixture enables in src/modules.ts. Both are on the\n// fact-sheet allowlist, so agentic:init must ship exactly their fact-sheets\n// (enabled \u2229 allowlist \u2014 spec D6) and list them in the AGENTS.md marker block.\nconst FIXTURE_ENABLED_MODULES = ['customers', 'sales']\n\nfunction normalizePath(value: string): string {\n return value.split(path.sep).join('/')\n}\n\nfunction runCommand(command: string, args: string[], cwd: string): string {\n return execFileSync(command, args, {\n cwd,\n encoding: 'utf8',\n env: {\n ...process.env,\n FORCE_COLOR: '0',\n NODE_NO_WARNINGS: '1',\n // Keep the test hermetic: agentic:init runs scripts/install-skills.sh,\n // whose external step (`npx skills add`) needs the network. Local tier\n // symlinks are still installed.\n OM_SKIP_EXTERNAL_SKILLS: '1',\n },\n })\n}\n\nfunction runMercato(args: string[], cwd: string): string {\n return runCommand(process.execPath, [cliBin, ...args], cwd)\n}\n\nfunction writeFile(filePath: string, content: string): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true })\n fs.writeFileSync(filePath, content)\n}\n\nfunction ensureCliBuilt(): void {\n runCommand(process.execPath, [cliBuildScript], cliDir)\n}\n\nfunction createStandaloneFixture(rootDir: string): string {\n const appDir = path.join(rootDir, 'sample-store')\n writeFile(\n path.join(appDir, 'package.json'),\n JSON.stringify(\n {\n name: 'sample-store',\n private: true,\n },\n null,\n 2,\n ),\n )\n const moduleEntries = FIXTURE_ENABLED_MODULES.map((moduleId) => ` { id: '${moduleId}' },`).join('\\n')\n writeFile(path.join(appDir, 'src', 'modules.ts'), `export const enabledModules = [\\n${moduleEntries}\\n]\\n`)\n return appDir\n}\n\nfunction listRelativeFiles(rootDir: string): string[] {\n if (!fs.existsSync(rootDir)) {\n return []\n }\n\n const collected: string[] = []\n for (const entry of fs.readdirSync(rootDir, { withFileTypes: true })) {\n const absolutePath = path.join(rootDir, entry.name)\n if (entry.isDirectory()) {\n for (const nestedPath of listRelativeFiles(absolutePath)) {\n collected.push(path.join(entry.name, nestedPath))\n }\n continue\n }\n if (entry.isFile()) {\n collected.push(entry.name)\n }\n }\n\n return collected.map(normalizePath).sort()\n}\n\nfunction mapSharedSourceToOutput(relativePath: string): string {\n if (relativePath === 'AGENTS.md.template') {\n return 'AGENTS.md'\n }\n\n if (relativePath.startsWith('scripts/')) {\n return relativePath\n }\n\n if (!relativePath.startsWith('ai/')) {\n throw new Error(`Unexpected shared source path: ${relativePath}`)\n }\n\n return normalizePath(path.join('.ai', relativePath.slice('ai/'.length)))\n}\n\nfunction mapClaudeSourceToOutput(relativePath: string): string {\n if (relativePath === 'CLAUDE.md.template') {\n return 'CLAUDE.md'\n }\n if (relativePath === 'settings.json') {\n return '.claude/settings.json'\n }\n if (relativePath === 'mcp.json.example') {\n return '.mcp.json.example'\n }\n if (relativePath.startsWith('hooks/')) {\n return normalizePath(path.join('.claude', relativePath))\n }\n\n throw new Error(`Unexpected Claude source path: ${relativePath}`)\n}\n\nfunction mapCursorSourceToOutput(relativePath: string): string {\n if (relativePath === 'hooks.json') {\n return '.cursor/hooks.json'\n }\n if (relativePath === 'mcp.json.example') {\n return '.cursor/mcp.json.example'\n }\n if (relativePath.startsWith('hooks/') || relativePath.startsWith('rules/')) {\n return normalizePath(path.join('.cursor', relativePath))\n }\n\n throw new Error(`Unexpected Cursor source path: ${relativePath}`)\n}\n\nfunction mapCodexSourceToOutput(relativePath: string): string | null {\n if (relativePath === 'mcp.json.example') {\n return '.codex/mcp.json.example'\n }\n if (relativePath === 'enforcement-rules.md') {\n return null\n }\n\n throw new Error(`Unexpected Codex source path: ${relativePath}`)\n}\n\nfunction readPlaywrightConfigPathFromTemplate(): string {\n const packageTemplate = JSON.parse(fs.readFileSync(standaloneTemplatePackageJsonPath, 'utf8')) as {\n scripts?: Record<string, string>\n }\n const integrationScript = packageTemplate.scripts?.['test:integration']\n if (!integrationScript) {\n throw new Error('Standalone template is missing the test:integration script')\n }\n\n const configPathMatch = integrationScript.match(/--config\\s+([^\\s]+)/)\n if (!configPathMatch?.[1]) {\n throw new Error('Standalone template test:integration script is missing --config')\n }\n\n return normalizePath(configPathMatch[1])\n}\n\nfunction readPlaywrightConfigPathFromCliRunner(): string {\n const integrationRunnerSource = fs.readFileSync(cliIntegrationRunnerPath, 'utf8')\n const configPathMatch = integrationRunnerSource.match(/const PLAYWRIGHT_INTEGRATION_CONFIG_PATH = '([^']+)'/)\n if (!configPathMatch?.[1]) {\n throw new Error('CLI integration runner is missing PLAYWRIGHT_INTEGRATION_CONFIG_PATH')\n }\n\n return normalizePath(configPathMatch[1])\n}\n\nfunction expectedGuideOutputNames(): string[] {\n const collected = new Set<string>()\n\n // Static conceptual guides checked into create-app (e.g. module-system.md) are\n // bundled into dist/agentic/guides by the CLI build and copied wholesale.\n const staticGuidesRoot = path.join(agenticRoot, 'guides')\n if (fs.existsSync(staticGuidesRoot)) {\n for (const entry of fs.readdirSync(staticGuidesRoot, { withFileTypes: true })) {\n if (entry.isFile() && entry.name.endsWith('.md')) {\n collected.add(entry.name)\n }\n }\n }\n\n for (const packageName of fs.readdirSync(packagesRoot)) {\n const packageGuide = path.join(packagesRoot, packageName, 'agentic', 'standalone-guide.md')\n if (fs.existsSync(packageGuide)) {\n collected.add(`${packageName}.md`)\n }\n\n const modulesRoot = path.join(packagesRoot, packageName, 'src', 'modules')\n if (!fs.existsSync(modulesRoot)) {\n continue\n }\n\n for (const moduleName of fs.readdirSync(modulesRoot)) {\n const moduleGuide = path.join(modulesRoot, moduleName, 'agentic', 'standalone-guide.md')\n if (fs.existsSync(moduleGuide)) {\n collected.add(`${packageName}.${moduleName}.md`)\n }\n }\n }\n\n // Generated fact-sheet artifacts (spec 2026-06-27-ts-morph-module-fact-sheets):\n // the module-facts.json sidecar is copied as-is, fact-sheets are filtered to the\n // fixture's enabled modules, and every allowlisted module whose hand-written\n // core.<module>.md guide no longer exists gets a legacy redirect stub.\n collected.add('module-facts.json')\n for (const moduleId of FIXTURE_ENABLED_MODULES) {\n collected.add(normalizePath(path.join('modules', `${moduleId}.md`)))\n }\n for (const moduleId of MODULE_FACTS_ALLOWLIST) {\n const legacyGuideSource = path.join(packagesRoot, 'core', 'src', 'modules', moduleId, 'agentic', 'standalone-guide.md')\n if (!fs.existsSync(legacyGuideSource)) {\n collected.add(`core.${moduleId}.md`)\n }\n }\n\n return Array.from(collected).sort()\n}\n\nfunction assertPathsExist(appDir: string, relativePaths: string[]): void {\n const missingPaths = relativePaths.filter((relativePath) => !fs.existsSync(path.join(appDir, relativePath)))\n expect(missingPaths).toEqual([])\n}\n\ntest.describe('TC-INT-008: CLI agentic init mirrors standalone scaffolding assets', () => {\n test.beforeAll(() => {\n ensureCliBuilt()\n })\n\n test('should run bootstrap-free and generate the shared, guide, and tool-specific agentic files', () => {\n const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-agentic-'))\n\n try {\n const appDir = createStandaloneFixture(tempRoot)\n const standalonePlaywrightConfigPath = readPlaywrightConfigPathFromTemplate()\n const cliPlaywrightConfigPath = readPlaywrightConfigPathFromCliRunner()\n const commandOutput = runMercato(['agentic:init', '--tool=claude-code,codex,cursor'], appDir)\n\n expect(cliPlaywrightConfigPath).toBe(standalonePlaywrightConfigPath)\n expect(commandOutput).toContain('Agentic setup complete:')\n expect(fs.existsSync(path.join(appDir, '.mercato', 'generated'))).toBe(false)\n\n const sharedOutputs = listRelativeFiles(path.join(agenticRoot, 'shared')).map(mapSharedSourceToOutput)\n const claudeOutputs = listRelativeFiles(path.join(agenticRoot, 'claude-code')).map(mapClaudeSourceToOutput)\n const cursorOutputs = listRelativeFiles(path.join(agenticRoot, 'cursor')).map(mapCursorSourceToOutput)\n const codexOutputs = listRelativeFiles(path.join(agenticRoot, 'codex'))\n .map(mapCodexSourceToOutput)\n .filter((relativePath): relativePath is string => relativePath !== null)\n\n expect(sharedOutputs).toContain(standalonePlaywrightConfigPath)\n assertPathsExist(appDir, [...sharedOutputs, ...claudeOutputs, ...cursorOutputs, ...codexOutputs])\n expect(fs.existsSync(path.join(appDir, standalonePlaywrightConfigPath))).toBe(true)\n\n const generatedGuideNames = listRelativeFiles(path.join(appDir, '.ai', 'guides'))\n expect(generatedGuideNames).toEqual(expectedGuideOutputNames())\n\n const agentsSource = fs.readFileSync(path.join(appDir, 'AGENTS.md'), 'utf8')\n expect(agentsSource).toContain('<!-- CODEX_ENFORCEMENT_RULES_START -->')\n expect(agentsSource).toContain('.ai/guides/core.md')\n\n // The Module-Specific Guides marker block lists exactly the enabled modules'\n // fact-sheets (enabled \u2229 allowlist), not the full bundled set.\n for (const moduleId of FIXTURE_ENABLED_MODULES) {\n expect(agentsSource).toContain(`.ai/guides/modules/${moduleId}.md`)\n }\n expect(agentsSource).not.toContain('.ai/guides/modules/auth.md')\n\n const specsReadmeSource = fs.readFileSync(path.join(appDir, '.ai', 'specs', 'README.md'), 'utf8')\n expect(specsReadmeSource).toContain('sample-store')\n\n const cursorRulesSource = fs.readFileSync(path.join(appDir, '.cursor', 'rules', 'open-mercato.mdc'), 'utf8')\n expect(cursorRulesSource).toContain('sample-store')\n\n // om-spec-writing moved to the external open-mercato/skills collection\n // (installed via `yarn install-skills`), so agentic:init must not ship a copy.\n expect(fs.existsSync(path.join(appDir, '.ai', 'skills', 'om-spec-writing'))).toBe(false)\n expect(fs.existsSync(path.join(appDir, 'scripts', 'install-skills.sh'))).toBe(true)\n\n // install-skills.sh (run by agentic:init) replaces the legacy directory-level\n // .claude/skills and .codex/skills symlinks with real directories holding one\n // symlink per default-tier local skill; .cursor/skills keeps the directory link.\n const cursorSkillsLinkPath = path.join(appDir, '.cursor', 'skills')\n expect(fs.lstatSync(cursorSkillsLinkPath).isSymbolicLink()).toBe(true)\n expect(normalizePath(fs.readlinkSync(cursorSkillsLinkPath))).toBe('../.ai/skills')\n\n const tiersManifest = JSON.parse(\n fs.readFileSync(path.join(agenticRoot, 'shared', 'ai', 'skills', 'tiers.json'), 'utf8'),\n ) as { default: string[]; tiers: Record<string, { skills: string[] }> }\n const defaultTierSkills = tiersManifest.default.flatMap((tierName) => tiersManifest.tiers[tierName].skills)\n expect(defaultTierSkills.length).toBeGreaterThan(0)\n\n for (const toolDir of ['.claude', '.codex']) {\n const harnessSkillsDir = path.join(appDir, toolDir, 'skills')\n expect(fs.lstatSync(harnessSkillsDir).isDirectory()).toBe(true)\n for (const skillName of defaultTierSkills) {\n const skillLinkPath = path.join(harnessSkillsDir, skillName)\n expect(fs.lstatSync(skillLinkPath).isSymbolicLink()).toBe(true)\n expect(normalizePath(fs.readlinkSync(skillLinkPath))).toBe(`../../.ai/skills/${skillName}`)\n }\n }\n } finally {\n fs.rmSync(tempRoot, { recursive: true, force: true })\n }\n })\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|