@mnstry/atelier 0.2.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +383 -0
- package/LICENSE +202 -0
- package/NOTICE +5 -0
- package/README.md +262 -0
- package/SECURITY.md +93 -0
- package/TRADEMARKS.md +88 -0
- package/announcements/2026-08-06-announcements-channel.v1.json +12 -0
- package/announcements/keys/mnstry-announcements.public.v1.json +9 -0
- package/bin/atelier.mjs +2 -0
- package/bin/mnstry-atelier.mjs +3 -0
- package/contracts/analysis-adapter.v1.schema.json +248 -0
- package/contracts/atelier-action-intent.v1.schema.json +143 -0
- package/contracts/atelier-analysis-adapter.v1.schema.json +360 -0
- package/contracts/atelier-attestation.v1.schema.json +239 -0
- package/contracts/atelier-boundary-policy.v1.schema.json +339 -0
- package/contracts/atelier-claim.v1.schema.json +97 -0
- package/contracts/atelier-export.v1.schema.json +1015 -0
- package/contracts/atelier-extension-pack.v1.schema.json +290 -0
- package/contracts/atelier-kit-manifest.v1.schema.json +273 -0
- package/contracts/atelier-lock.v1.schema.json +364 -0
- package/contracts/atelier-migration.v1.schema.json +162 -0
- package/contracts/atelier-project-config.v1.schema.json +352 -0
- package/contracts/atelier-readiness-protocol.v1.schema.json +517 -0
- package/contracts/atelier-readiness-run.v1.schema.json +229 -0
- package/contracts/atelier-readiness.v1.schema.json +457 -0
- package/contracts/compat-baseline.json +10 -0
- package/contracts/git-promote-event.v1.schema.json +145 -0
- package/contracts/knowledge-source-sidecar.v1.schema.json +157 -0
- package/contracts/mnstry-atelier-semantic-profile.v1.json +254 -0
- package/docs/announcements.md +101 -0
- package/docs/atelier-runtime.md +34 -0
- package/docs/attestation.md +201 -0
- package/docs/continuity.md +55 -0
- package/docs/contract-stability.md +111 -0
- package/docs/distributions.md +220 -0
- package/docs/install.md +140 -0
- package/docs/knowledge-graph.md +140 -0
- package/docs/ontology.md +206 -0
- package/docs/release-engineering.md +151 -0
- package/docs/repo-boundary-guard.md +199 -0
- package/docs/tenant-readiness.md +64 -0
- package/docs/upgrade.md +124 -0
- package/fixtures/analysis/invalid/native-graph.v1.json +4 -0
- package/fixtures/analysis/invalid/promoted-claim.v1.json +17 -0
- package/fixtures/analysis/invalid/runtime-import.v1.json +20 -0
- package/fixtures/analysis/valid/output.claims.v1.json +17 -0
- package/fixtures/analysis-adapter/invalid/manifest-hidden-provider.v1.json +24 -0
- package/fixtures/analysis-adapter/invalid/output-frontmatter-mutation.v1.json +21 -0
- package/fixtures/analysis-adapter/invalid/output-native-graph.v1.json +14 -0
- package/fixtures/analysis-adapter/manifest.disabled.v1.json +22 -0
- package/fixtures/analysis-adapter/manifest.enabled-local.v1.json +23 -0
- package/fixtures/analysis-adapter/output.claims.v1.json +21 -0
- package/fixtures/atelier-action-intent/invalid/runtime-mutation-authority.v1.json +16 -0
- package/fixtures/atelier-action-intent/invalid/unknown-top-level-field.v1.json +17 -0
- package/fixtures/atelier-action-intent/invalid/writes-beyond-clipboard.v1.json +16 -0
- package/fixtures/atelier-action-intent/valid/copy-agent-prompt.v1.json +16 -0
- package/fixtures/atelier-action-intent/valid/copy-repo-path.v1.json +22 -0
- package/fixtures/atelier-analysis-adapter/invalid/hidden-model-provider.v1.json +24 -0
- package/fixtures/atelier-analysis-adapter/invalid/inert-with-execute-command.v1.json +24 -0
- package/fixtures/atelier-analysis-adapter/invalid/proposals-with-runtime-import.v1.json +30 -0
- package/fixtures/atelier-analysis-adapter/valid/manifest-inert.v1.json +24 -0
- package/fixtures/atelier-analysis-adapter/valid/proposals-claim-only.v1.json +27 -0
- package/fixtures/atelier-attestation/invalid/bad-digest.v1.json +23 -0
- package/fixtures/atelier-attestation/invalid/conformance-scope.v1.json +23 -0
- package/fixtures/atelier-attestation/invalid/missing-signature.v1.json +22 -0
- package/fixtures/atelier-attestation/invalid/unknown-root-field.v1.json +24 -0
- package/fixtures/atelier-attestation/keys/roundtrip-issuer.public.v1.json +9 -0
- package/fixtures/atelier-attestation/valid/rejected-with-reasons.v1.json +49 -0
- package/fixtures/atelier-attestation/valid/signed-admitted.v1.json +35 -0
- package/fixtures/atelier-attestation/valid/signed-roundtrip.v1.json +29 -0
- package/fixtures/atelier-attestation/valid/unsigned-advisory.v1.json +23 -0
- package/fixtures/atelier-claim/invalid/unknown-provider.v1.json +15 -0
- package/fixtures/atelier-claim/invalid/unknown-top-level-field.v1.json +16 -0
- package/fixtures/atelier-claim/invalid/wrong-schema-const.v1.json +15 -0
- package/fixtures/atelier-claim/valid/adapter-style-proposed-relation.v1.json +19 -0
- package/fixtures/atelier-claim/valid/codex-proposed-relation.v1.json +16 -0
- package/fixtures/atelier-claim/valid/manual-proposed-relation.v1.json +16 -0
- package/fixtures/atelier-claim/valid/readiness-proposed-relation.v1.json +18 -0
- package/fixtures/atelier-export/invalid/dirty-unforced-empty-taint.v1.json +19 -0
- package/fixtures/atelier-export/invalid/object-local-audience-visibility.v1.json +11 -0
- package/fixtures/atelier-export/invalid/open-object-class-owner.v1.json +23 -0
- package/fixtures/atelier-export/invalid/pricing-legacy-amount.v1.json +23 -0
- package/fixtures/atelier-export/invalid/public-disguised-internal-source-ref.v1.json +11 -0
- package/fixtures/atelier-export/invalid/public-nested-private-source-ref.v1.json +17 -0
- package/fixtures/atelier-export/invalid/public-resolved-private-source-ref.v1.json +13 -0
- package/fixtures/atelier-export/invalid/public-resolved-sensitive-source-ref.v1.json +13 -0
- package/fixtures/atelier-export/invalid/public-source-ref-missing-provenance.v1.json +20 -0
- package/fixtures/atelier-export/invalid/public-source-team-kg.json +12 -0
- package/fixtures/atelier-export/invalid/source-node-legacy-visibility.v1.json +21 -0
- package/fixtures/atelier-export/invalid/source-node-unknown-field.v1.json +18 -0
- package/fixtures/atelier-export/invalid/unresolved-public-source-ref.v1.json +11 -0
- package/fixtures/atelier-export/sample-studio-offer.v1.json +397 -0
- package/fixtures/atelier-extension-pack/invalid/bundled-slug-collision.v1.json +22 -0
- package/fixtures/atelier-extension-pack/invalid/escapes-root.v1.json +22 -0
- package/fixtures/atelier-extension-pack/invalid/posture-tampered.v1.json +22 -0
- package/fixtures/atelier-extension-pack/invalid/protocols/autonomous-authority.v1.json +118 -0
- package/fixtures/atelier-extension-pack/invalid/protocols/offer-map.v1.json +109 -0
- package/fixtures/atelier-extension-pack/invalid/redefines-runtime-term.v1.json +19 -0
- package/fixtures/atelier-extension-pack/invalid/wrong-namespace.v1.json +19 -0
- package/fixtures/atelier-extension-pack/valid/protocols/contract-gate.v1.json +109 -0
- package/fixtures/atelier-extension-pack/valid/sample-pack.v1.json +48 -0
- package/fixtures/atelier-kit-manifest/invalid/runtime-copy-without-canonical-role.v1.json +53 -0
- package/fixtures/atelier-kit-manifest/invalid/telemetry-send-path.v1.json +21 -0
- package/fixtures/atelier-kit-manifest/valid/mnstry-atelier.valid.v1.json +76 -0
- package/fixtures/atelier-lock/invalid/absolute-contract-path.v1.json +40 -0
- package/fixtures/atelier-lock/invalid/runtime-mutation-enabled.v1.json +41 -0
- package/fixtures/atelier-lock/invalid/unknown-top-level-field.v1.json +42 -0
- package/fixtures/atelier-lock/valid/extension-pack.v1.json +55 -0
- package/fixtures/atelier-lock/valid/minimal.v1.json +44 -0
- package/fixtures/atelier-migration/invalid/live-apply-mode.v1.json +21 -0
- package/fixtures/atelier-migration/invalid/missing-review-evidence.v1.json +20 -0
- package/fixtures/atelier-migration/invalid/runtime-mutation-enabled.v1.json +21 -0
- package/fixtures/atelier-migration/valid/minimal.v1.json +32 -0
- package/fixtures/atelier-project-config/invalid/absolute-repo-path.v1.json +11 -0
- package/fixtures/atelier-project-config/invalid/ext-not-object.v1.json +12 -0
- package/fixtures/atelier-project-config/invalid/external-kind-read-boundary.v1.json +12 -0
- package/fixtures/atelier-project-config/invalid/missing-repos-and-alignment.v1.json +7 -0
- package/fixtures/atelier-project-config/invalid/unknown-top-level-field.v1.json +14 -0
- package/fixtures/atelier-project-config/valid/alignment-scaffold.v1.json +15 -0
- package/fixtures/atelier-project-config/valid/ext-extension-packs.v1.json +36 -0
- package/fixtures/atelier-project-config/valid/repo-workspace.v1.json +23 -0
- package/fixtures/atelier-project-config/validator-only/ext-member-not-object.v1.json +14 -0
- package/fixtures/atelier-readiness/invalid/dry-run-only-false.v1.json +87 -0
- package/fixtures/atelier-readiness/invalid/support-bundle-send-path.v1.json +87 -0
- package/fixtures/atelier-readiness/invalid/unknown-top-level-field.v1.json +88 -0
- package/fixtures/atelier-readiness/valid/ready-workspace.v1.json +84 -0
- package/fixtures/boundary-policy/invalid/content-rule-exception-blanket-path.v1.json +67 -0
- package/fixtures/boundary-policy/invalid/invalid-actor-private-repo-mapping.v1.json +20 -0
- package/fixtures/boundary-policy/invalid/legacy-warning-missing-warning.v1.json +20 -0
- package/fixtures/boundary-policy/invalid/missing-repo-coverage.v1.json +19 -0
- package/fixtures/boundary-policy/invalid/unknown-key.v1.json +12 -0
- package/fixtures/boundary-policy/valid/content-rule-exception.v1.json +67 -0
- package/fixtures/boundary-policy/valid/legacy-warning.v1.json +33 -0
- package/fixtures/boundary-policy/valid/strict-private-shared.v1.json +40 -0
- package/fixtures/git-promote/invalid/provision-named-revocable.v1.json +29 -0
- package/fixtures/git-promote/private-to-team.v1.json +29 -0
- package/fixtures/knowledge-source-sidecar/invalid/legacy-visibility-field.v1.json +17 -0
- package/fixtures/knowledge-source-sidecar/invalid/missing-audience.v1.json +15 -0
- package/fixtures/knowledge-source-sidecar/invalid/unknown-relation-kind.v1.json +18 -0
- package/fixtures/knowledge-source-sidecar/valid/html-source.v1.json +18 -0
- package/fixtures/knowledge-source-sidecar/valid/pdf-evidence.v1.json +18 -0
- package/fixtures/projects/neutral-project/atelier.project.json +15 -0
- package/fixtures/projects/neutral-project/ops/config/repo-access.v1.json +12 -0
- package/fixtures/projects/neutral-project/project-knowledge.graph.json +69 -0
- package/fixtures/projects/sample-workspace/atelier.project.json +23 -0
- package/fixtures/projects/sample-workspace/boundary-policy.v1.json +59 -0
- package/fixtures/projects/sample-workspace/content/README.md +16 -0
- package/fixtures/projects/sample-workspace/content/source.html +5 -0
- package/fixtures/projects/sample-workspace/content/source.html.kg.json +15 -0
- package/fixtures/projects/sample-workspace/repo-access.v1.json +9 -0
- package/fixtures/projects/source-formats-workspace/atelier.project.json +23 -0
- package/fixtures/projects/source-formats-workspace/content/README.md +17 -0
- package/fixtures/projects/source-formats-workspace/content/data.json +7 -0
- package/fixtures/projects/source-formats-workspace/content/data.json.kg.json +15 -0
- package/fixtures/projects/source-formats-workspace/content/logo.png.kg.json +15 -0
- package/fixtures/projects/source-formats-workspace/content/metrics.csv +3 -0
- package/fixtures/projects/source-formats-workspace/content/metrics.csv.kg.json +15 -0
- package/fixtures/projects/source-formats-workspace/content/pipeline.yaml +4 -0
- package/fixtures/projects/source-formats-workspace/content/pipeline.yaml.kg.json +15 -0
- package/fixtures/projects/source-formats-workspace/repo-access.v1.json +9 -0
- package/fixtures/readiness-protocols/extension-pack/invalid/protocol-missing-path.v1.json +20 -0
- package/fixtures/readiness-protocols/extension-pack/valid/with-protocol.v1.json +24 -0
- package/fixtures/readiness-protocols/protocol/invalid/missing-check-target.v1.json +103 -0
- package/fixtures/readiness-protocols/protocol/invalid/runtime-mutation-enabled.v1.json +107 -0
- package/fixtures/readiness-protocols/protocol/valid/minimal.v1.json +100 -0
- package/fixtures/readiness-protocols/run/invalid/missing-evidence.v1.json +37 -0
- package/fixtures/readiness-protocols/run/invalid/pass-with-blocker.v1.json +22 -0
- package/fixtures/readiness-protocols/run/invalid/runtime-mutation-enabled.v1.json +22 -0
- package/fixtures/readiness-protocols/run/valid/pass.v1.json +44 -0
- package/fixtures/support/invalid/leaky-support.v1.json +13 -0
- package/fixtures/support/valid/minimal-safe.v1.json +20 -0
- package/package.json +98 -0
- package/skills/claude/atelier-open/SKILL.md +68 -0
- package/skills/claude/mnstry-readiness/SKILL.md +41 -0
- package/skills/codex/atelier-open/SKILL.md +68 -0
- package/skills/codex/mnstry-readiness/SKILL.md +41 -0
- package/src/analysis/adapter.mjs +20 -0
- package/src/analysis/analysis-claim-contract.mjs +335 -0
- package/src/attestation/jcs.mjs +64 -0
- package/src/attestation/sign.mjs +305 -0
- package/src/boundary/content-rules.mjs +262 -0
- package/src/boundary/policy.mjs +806 -0
- package/src/check-atelier-export-contract.mjs +116 -0
- package/src/cli/run.mjs +283 -0
- package/src/collaboration/proposals.mjs +262 -0
- package/src/commands/analysis.mjs +8 -0
- package/src/commands/announcements.mjs +308 -0
- package/src/commands/attestation.mjs +198 -0
- package/src/commands/boundary.mjs +25 -0
- package/src/commands/config.mjs +4 -0
- package/src/commands/context.mjs +3 -0
- package/src/commands/distribution.mjs +224 -0
- package/src/commands/egress.mjs +11 -0
- package/src/commands/extension-pack.mjs +209 -0
- package/src/commands/feedback.mjs +3 -0
- package/src/commands/graph.mjs +3 -0
- package/src/commands/init.mjs +130 -0
- package/src/commands/lock.mjs +3 -0
- package/src/commands/project.mjs +3 -0
- package/src/commands/promote.mjs +4 -0
- package/src/commands/readiness.mjs +3 -0
- package/src/commands/server.mjs +6 -0
- package/src/commands/setup.mjs +250 -0
- package/src/commands/support.mjs +3 -0
- package/src/commands/upgrade.mjs +3 -0
- package/src/contracts/corpus.mjs +171 -0
- package/src/egress/check.mjs +45 -0
- package/src/egress/forbidden-egress.mjs +323 -0
- package/src/export/atelier-export-contract.mjs +722 -0
- package/src/extension-packs/loader.mjs +491 -0
- package/src/graph/graph.mjs +370 -0
- package/src/graph/knowledge-graph.mjs +887 -0
- package/src/harness/context-client.mjs +144 -0
- package/src/harness/context.mjs +27 -0
- package/src/index.mjs +88 -0
- package/src/project/config.mjs +557 -0
- package/src/project/file-class.mjs +113 -0
- package/src/project/git-ignore.mjs +31 -0
- package/src/project/path-match.mjs +30 -0
- package/src/project/repo-identity.mjs +176 -0
- package/src/projection/alignment-projection.mjs +169 -0
- package/src/projection/policy.mjs +90 -0
- package/src/projection/project.mjs +152 -0
- package/src/readiness/readiness.mjs +312 -0
- package/src/readiness-protocols/bundled-pack.mjs +766 -0
- package/src/readiness-protocols/runtime.mjs +419 -0
- package/src/server/local-sidecar.mjs +640 -0
- package/src/server/security.mjs +229 -0
- package/src/server/server.mjs +42 -0
- package/src/support/feedback-report.mjs +414 -0
- package/src/support/support-bundle.mjs +226 -0
- package/src/ui/html-primitives.mjs +104 -0
- package/src/upgrade/upgrade.mjs +701 -0
- package/src/validate-atelier-export-dry-run.mjs +75 -0
- package/templates/atelier.project.example.json +23 -0
- package/templates/distribution-workspace/.claude/launch.json +12 -0
- package/templates/distribution-workspace/README.md +86 -0
- package/templates/distribution-workspace/atelier.project.json +36 -0
- package/templates/distribution-workspace/boundary-policy.v1.json +61 -0
- package/templates/distribution-workspace/gitignore +29 -0
- package/templates/distribution-workspace/governance/repo-boundary-ledger.md +5 -0
- package/templates/distribution-workspace/project/README.md +19 -0
- package/templates/distribution-workspace/repo-access.v1.json +9 -0
- package/templates/launch.json +12 -0
- package/templates/private-domain-workspace/.claude/launch.json +12 -0
- package/templates/private-domain-workspace/README.md +50 -0
- package/templates/private-domain-workspace/atelier.project.json +28 -0
- package/templates/private-domain-workspace/boundary-policy.v1.json +54 -0
- package/templates/private-domain-workspace/domain/README.md +19 -0
- package/templates/private-domain-workspace/gitignore +29 -0
- package/templates/private-domain-workspace/governance/repo-boundary-ledger.md +4 -0
- package/templates/private-domain-workspace/repo-access.v1.json +9 -0
- package/templates/shared-project-workspace/.claude/launch.json +12 -0
- package/templates/shared-project-workspace/README.md +51 -0
- package/templates/shared-project-workspace/atelier.project.json +28 -0
- package/templates/shared-project-workspace/boundary-policy.v1.json +61 -0
- package/templates/shared-project-workspace/gitignore +29 -0
- package/templates/shared-project-workspace/governance/repo-boundary-ledger.md +5 -0
- package/templates/shared-project-workspace/project/README.md +19 -0
- package/templates/shared-project-workspace/repo-access.v1.json +9 -0
package/package.json
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mnstry/atelier",
|
|
3
|
+
"version": "0.2.0-alpha.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Local-first MNSTRY Atelier workspace for agentic authoring, graph projection, and dry-run runtime readiness.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"atelier": "bin/atelier.mjs",
|
|
9
|
+
"mnstry-atelier": "bin/mnstry-atelier.mjs"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": "./src/index.mjs",
|
|
13
|
+
"./cli": "./src/cli/run.mjs",
|
|
14
|
+
"./project": "./src/project/config.mjs",
|
|
15
|
+
"./graph": "./src/graph/graph.mjs",
|
|
16
|
+
"./projection": "./src/projection/project.mjs",
|
|
17
|
+
"./readiness": "./src/readiness/readiness.mjs",
|
|
18
|
+
"./readiness-protocols": "./src/readiness-protocols/bundled-pack.mjs",
|
|
19
|
+
"./server": "./src/server/local-sidecar.mjs",
|
|
20
|
+
"./harness": "./src/harness/context.mjs",
|
|
21
|
+
"./support": "./src/support/support-bundle.mjs",
|
|
22
|
+
"./egress": "./src/egress/forbidden-egress.mjs",
|
|
23
|
+
"./boundary": "./src/boundary/policy.mjs",
|
|
24
|
+
"./upgrade": "./src/upgrade/upgrade.mjs",
|
|
25
|
+
"./attestation": "./src/attestation/sign.mjs",
|
|
26
|
+
"./extension-packs": "./src/extension-packs/loader.mjs",
|
|
27
|
+
"./analysis/adapter": "./src/analysis/adapter.mjs",
|
|
28
|
+
"./export-contract": "./src/export/atelier-export-contract.mjs",
|
|
29
|
+
"./dry-run": "./src/validate-atelier-export-dry-run.mjs",
|
|
30
|
+
"./contracts/atelier-export.v1.schema.json": "./contracts/atelier-export.v1.schema.json",
|
|
31
|
+
"./fixtures/atelier-export/sample-studio-offer.v1.json": "./fixtures/atelier-export/sample-studio-offer.v1.json"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"contract": "node src/check-atelier-export-contract.mjs",
|
|
35
|
+
"dry-run": "node src/validate-atelier-export-dry-run.mjs fixtures/atelier-export/sample-studio-offer.v1.json",
|
|
36
|
+
"test": "node --test test/*.test.mjs",
|
|
37
|
+
"syntax:check": "find bin src -name '*.mjs' -print0 | xargs -0 -n1 node --check",
|
|
38
|
+
"graph:test": "node --test test/graph.test.mjs test/graph-knowledge-graph.test.mjs test/graph-determinism.test.mjs test/graph-source-formats.test.mjs",
|
|
39
|
+
"project:test": "node --test test/project.test.mjs test/project-config.test.mjs test/projection-policy.test.mjs test/projection-alignment.test.mjs",
|
|
40
|
+
"server:security:test": "node --test test/server.test.mjs test/server-security.test.mjs test/server-proposals.test.mjs",
|
|
41
|
+
"browser:smoke": "node --test test/server.test.mjs",
|
|
42
|
+
"support-bundle:test": "node --test test/support-bundle.test.mjs test/support-egress-analysis.test.mjs",
|
|
43
|
+
"egress:check": "node bin/atelier.mjs egress check",
|
|
44
|
+
"readiness:test": "node --test test/readiness.test.mjs test/readiness-summary.test.mjs test/readiness-protocol-contract.test.mjs test/readiness-protocols.test.mjs test/readiness-protocol-runtime.test.mjs",
|
|
45
|
+
"harness:test": "node --test test/harness.test.mjs test/harness-context.test.mjs",
|
|
46
|
+
"boundary:test": "node --test test/boundary-policy-contract.test.mjs test/boundary-guard.test.mjs",
|
|
47
|
+
"upgrade:test": "node --test test/upgrade-contract.test.mjs test/upgrade.test.mjs",
|
|
48
|
+
"release:audit": "node scripts/check-release-tarball.mjs",
|
|
49
|
+
"repo:check": "node scripts/check-repo-disclosure.mjs",
|
|
50
|
+
"migrations:check": "node scripts/check-breaking-migrations.mjs",
|
|
51
|
+
"contract:compat": "node scripts/check-contract-compat.mjs",
|
|
52
|
+
"consumer:smoke": "node scripts/consumer-smoke.mjs",
|
|
53
|
+
"distribution:smoke": "node scripts/distribution-smoke.mjs",
|
|
54
|
+
"prepublishOnly": "npm run release:audit && npm run repo:check && npm run migrations:check && npm run contract:compat && npm run syntax:check && npm test && npm run consumer:smoke && npm run distribution:smoke"
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"ajv": "8.20.0",
|
|
58
|
+
"ajv-formats": "3.0.1"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@types/node": "^22.0.0"
|
|
62
|
+
},
|
|
63
|
+
"license": "Apache-2.0",
|
|
64
|
+
"repository": {
|
|
65
|
+
"type": "git",
|
|
66
|
+
"url": "git+https://github.com/MNSTRY/atelier.git"
|
|
67
|
+
},
|
|
68
|
+
"homepage": "https://mnstry.org",
|
|
69
|
+
"bugs": {
|
|
70
|
+
"url": "https://github.com/MNSTRY/atelier/issues"
|
|
71
|
+
},
|
|
72
|
+
"engines": {
|
|
73
|
+
"node": ">=22.18.0 <23"
|
|
74
|
+
},
|
|
75
|
+
"files": [
|
|
76
|
+
"README.md",
|
|
77
|
+
"CHANGELOG.md",
|
|
78
|
+
"LICENSE",
|
|
79
|
+
"NOTICE",
|
|
80
|
+
"TRADEMARKS.md",
|
|
81
|
+
"SECURITY.md",
|
|
82
|
+
"bin/",
|
|
83
|
+
"contracts/",
|
|
84
|
+
"fixtures/",
|
|
85
|
+
"skills/",
|
|
86
|
+
"src/",
|
|
87
|
+
"templates/",
|
|
88
|
+
"docs/",
|
|
89
|
+
"announcements/",
|
|
90
|
+
"!fixtures/projects/source-formats-workspace/content/logo.png"
|
|
91
|
+
],
|
|
92
|
+
"publishConfig": {
|
|
93
|
+
"access": "public"
|
|
94
|
+
},
|
|
95
|
+
"overrides": {
|
|
96
|
+
"fast-uri": "3.1.5"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Open the Atelier
|
|
2
|
+
|
|
3
|
+
Use this skill when someone says "open the atelier", "pull up the atelier",
|
|
4
|
+
"show me the portal", or asks what page they are currently viewing.
|
|
5
|
+
|
|
6
|
+
"Open" means **the client's native preview surface**, not the system browser.
|
|
7
|
+
An Atelier is a local sidecar serving a workspace projection; the point is to
|
|
8
|
+
render it where the person is already working.
|
|
9
|
+
|
|
10
|
+
## Route by client
|
|
11
|
+
|
|
12
|
+
| Client | How to open |
|
|
13
|
+
|---|---|
|
|
14
|
+
| Claude Code / Cowork | `preview_start` with the `atelier` launch config, then screenshot |
|
|
15
|
+
| Codex | the harness preview pane if present, otherwise report the URL |
|
|
16
|
+
| Editor with no preview pane | print the URL; do not shell out to `open` |
|
|
17
|
+
|
|
18
|
+
Never use the system `open` command and never fetch the page and describe it —
|
|
19
|
+
that answers a different question than the one being asked.
|
|
20
|
+
|
|
21
|
+
## Starting it
|
|
22
|
+
|
|
23
|
+
The workspace ships `.claude/launch.json` with `autoPort: true`. Start it by
|
|
24
|
+
name (`atelier`) and use the port the harness returns. The equivalent manual
|
|
25
|
+
command is:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
./node_modules/.bin/atelier server
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Use the local binary path. Do **not** run `npx atelier` — this package is not
|
|
32
|
+
yet published to npm, and the unscoped name `atelier` belongs to an unrelated
|
|
33
|
+
third-party package that `npx` would download and execute.
|
|
34
|
+
|
|
35
|
+
`atelier server` resolves its port as **argv > `PORT` env > 8137**, so a
|
|
36
|
+
supervisor can hand it a free port without a config edit.
|
|
37
|
+
|
|
38
|
+
## Do not fight for the canonical port
|
|
39
|
+
|
|
40
|
+
A workspace often keeps a long-lived instance on 8137 for humans and
|
|
41
|
+
cross-service links, frequently under a supervisor that respawns it. A preview
|
|
42
|
+
instance must coexist on its own port rather than evict it:
|
|
43
|
+
|
|
44
|
+
- Keep `autoPort: true`. Never pin a preview instance to the canonical port.
|
|
45
|
+
- "Port 8137 in use by a non-preview server" is the supervisor working, not an
|
|
46
|
+
error to clear. Start on the assigned port instead.
|
|
47
|
+
- Never kill the canonical instance to pick up new code without asking — on
|
|
48
|
+
most setups it is respawned by a supervisor whose rules you may not own.
|
|
49
|
+
|
|
50
|
+
## Boot time is not hang time
|
|
51
|
+
|
|
52
|
+
An Atelier may build or refresh its projection at startup. While it does, the
|
|
53
|
+
port is not yet open and browser calls fail with connection or policy errors
|
|
54
|
+
that read like permission problems. Poll the port or `/api/health` rather than
|
|
55
|
+
retrying the browser, and give a cold workspace room before declaring it broken.
|
|
56
|
+
|
|
57
|
+
## Which view to open
|
|
58
|
+
|
|
59
|
+
- Working inside one repo → that repo's portal, `/<repo>/index.html`
|
|
60
|
+
- Workspace-level work, or "everything" → `/`
|
|
61
|
+
- A repo's file audit → `/<repo>/atelier-ledger.html`
|
|
62
|
+
|
|
63
|
+
## What is the user looking at?
|
|
64
|
+
|
|
65
|
+
Prefer the session-aware context flow over any global "current view" file. A
|
|
66
|
+
recorded current view is a hint, not authority: trust it only when a
|
|
67
|
+
session-bound API response ties the view to the same workspace and a fresh
|
|
68
|
+
observation. Otherwise ask for an explicit target rather than guessing.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# MNSTRY Readiness
|
|
2
|
+
|
|
3
|
+
Use this skill when preparing or reviewing MNSTRY Atelier readiness outputs for
|
|
4
|
+
a tenant or project workspace.
|
|
5
|
+
|
|
6
|
+
## Protocol
|
|
7
|
+
|
|
8
|
+
- Use the repository's Atelier readiness protocols: `docs/tenant-readiness.md`,
|
|
9
|
+
`docs/atelier-runtime.md`, `contracts/atelier-readiness.v1.schema.json`, and
|
|
10
|
+
`contracts/atelier-claim.v1.schema.json`.
|
|
11
|
+
- Treat local source, Git state, project config, repo access, boundary policy,
|
|
12
|
+
and lockfiles as review authority.
|
|
13
|
+
- Treat generated graph, projection, and readiness output as evidence from the
|
|
14
|
+
current package checks, not source authority.
|
|
15
|
+
- Treat model/provider output as proposed `atelier-claim@v1` records only.
|
|
16
|
+
- Keep runtime identity, consent, visibility, provisioning, bookings, commerce,
|
|
17
|
+
sessions, audit, and client-grade sharing under MNSTRY runtime authority.
|
|
18
|
+
|
|
19
|
+
## Output Shape
|
|
20
|
+
|
|
21
|
+
Produce claim-first outputs:
|
|
22
|
+
|
|
23
|
+
- Claim: the readiness statement being made.
|
|
24
|
+
- Evidence: file paths, schema names, commands run, and observed behavior.
|
|
25
|
+
- Authority: source, generated evidence, proposed claim, or runtime-owned.
|
|
26
|
+
- Status: ready, warning, blocked, or proposed.
|
|
27
|
+
- Fix path: the smallest next reviewable change.
|
|
28
|
+
|
|
29
|
+
Do not introduce independent tenant semantics, new visibility terms, hidden
|
|
30
|
+
provider boundaries, or runtime mutation claims. If a check cannot run, report
|
|
31
|
+
the exact command, stderr, and blocker.
|
|
32
|
+
|
|
33
|
+
## Safety And Hygiene
|
|
34
|
+
|
|
35
|
+
- Keep package-facing output generic and placeholder-only.
|
|
36
|
+
- Do not include person-specific, tenant-private, project-private, transcript,
|
|
37
|
+
support-bundle, local absolute path, agent-local state, key, token, or
|
|
38
|
+
credential material.
|
|
39
|
+
- Prefer static inspection and existing defensive tests for security-sensitive
|
|
40
|
+
review work.
|
|
41
|
+
- Frame checks as verifying that a control refuses, blocks, or fails closed.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Open the Atelier
|
|
2
|
+
|
|
3
|
+
Use this skill when someone says "open the atelier", "pull up the atelier",
|
|
4
|
+
"show me the portal", or asks what page they are currently viewing.
|
|
5
|
+
|
|
6
|
+
"Open" means **the client's native preview surface**, not the system browser.
|
|
7
|
+
An Atelier is a local sidecar serving a workspace projection; the point is to
|
|
8
|
+
render it where the person is already working.
|
|
9
|
+
|
|
10
|
+
## Route by client
|
|
11
|
+
|
|
12
|
+
| Client | How to open |
|
|
13
|
+
|---|---|
|
|
14
|
+
| Claude Code / Cowork | `preview_start` with the `atelier` launch config, then screenshot |
|
|
15
|
+
| Codex | the harness preview pane if present, otherwise report the URL |
|
|
16
|
+
| Editor with no preview pane | print the URL; do not shell out to `open` |
|
|
17
|
+
|
|
18
|
+
Never use the system `open` command and never fetch the page and describe it —
|
|
19
|
+
that answers a different question than the one being asked.
|
|
20
|
+
|
|
21
|
+
## Starting it
|
|
22
|
+
|
|
23
|
+
The workspace ships `.claude/launch.json` with `autoPort: true`. Start it by
|
|
24
|
+
name (`atelier`) and use the port the harness returns. The equivalent manual
|
|
25
|
+
command is:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
./node_modules/.bin/atelier server
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Use the local binary path. Do **not** run `npx atelier` — this package is not
|
|
32
|
+
yet published to npm, and the unscoped name `atelier` belongs to an unrelated
|
|
33
|
+
third-party package that `npx` would download and execute.
|
|
34
|
+
|
|
35
|
+
`atelier server` resolves its port as **argv > `PORT` env > 8137**, so a
|
|
36
|
+
supervisor can hand it a free port without a config edit.
|
|
37
|
+
|
|
38
|
+
## Do not fight for the canonical port
|
|
39
|
+
|
|
40
|
+
A workspace often keeps a long-lived instance on 8137 for humans and
|
|
41
|
+
cross-service links, frequently under a supervisor that respawns it. A preview
|
|
42
|
+
instance must coexist on its own port rather than evict it:
|
|
43
|
+
|
|
44
|
+
- Keep `autoPort: true`. Never pin a preview instance to the canonical port.
|
|
45
|
+
- "Port 8137 in use by a non-preview server" is the supervisor working, not an
|
|
46
|
+
error to clear. Start on the assigned port instead.
|
|
47
|
+
- Never kill the canonical instance to pick up new code without asking — on
|
|
48
|
+
most setups it is respawned by a supervisor whose rules you may not own.
|
|
49
|
+
|
|
50
|
+
## Boot time is not hang time
|
|
51
|
+
|
|
52
|
+
An Atelier may build or refresh its projection at startup. While it does, the
|
|
53
|
+
port is not yet open and browser calls fail with connection or policy errors
|
|
54
|
+
that read like permission problems. Poll the port or `/api/health` rather than
|
|
55
|
+
retrying the browser, and give a cold workspace room before declaring it broken.
|
|
56
|
+
|
|
57
|
+
## Which view to open
|
|
58
|
+
|
|
59
|
+
- Working inside one repo → that repo's portal, `/<repo>/index.html`
|
|
60
|
+
- Workspace-level work, or "everything" → `/`
|
|
61
|
+
- A repo's file audit → `/<repo>/atelier-ledger.html`
|
|
62
|
+
|
|
63
|
+
## What is the user looking at?
|
|
64
|
+
|
|
65
|
+
Prefer the session-aware context flow over any global "current view" file. A
|
|
66
|
+
recorded current view is a hint, not authority: trust it only when a
|
|
67
|
+
session-bound API response ties the view to the same workspace and a fresh
|
|
68
|
+
observation. Otherwise ask for an explicit target rather than guessing.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# MNSTRY Readiness
|
|
2
|
+
|
|
3
|
+
Use this skill when preparing or reviewing MNSTRY Atelier readiness outputs for
|
|
4
|
+
a tenant or project workspace.
|
|
5
|
+
|
|
6
|
+
## Protocol
|
|
7
|
+
|
|
8
|
+
- Use the repository's Atelier readiness protocols: `docs/tenant-readiness.md`,
|
|
9
|
+
`docs/atelier-runtime.md`, `contracts/atelier-readiness.v1.schema.json`, and
|
|
10
|
+
`contracts/atelier-claim.v1.schema.json`.
|
|
11
|
+
- Treat local source, Git state, project config, repo access, boundary policy,
|
|
12
|
+
and lockfiles as review authority.
|
|
13
|
+
- Treat generated graph, projection, and readiness output as evidence from the
|
|
14
|
+
current package checks, not source authority.
|
|
15
|
+
- Treat model/provider output as proposed `atelier-claim@v1` records only.
|
|
16
|
+
- Keep runtime identity, consent, visibility, provisioning, bookings, commerce,
|
|
17
|
+
sessions, audit, and client-grade sharing under MNSTRY runtime authority.
|
|
18
|
+
|
|
19
|
+
## Output Shape
|
|
20
|
+
|
|
21
|
+
Produce claim-first outputs:
|
|
22
|
+
|
|
23
|
+
- Claim: the readiness statement being made.
|
|
24
|
+
- Evidence: file paths, schema names, commands run, and observed behavior.
|
|
25
|
+
- Authority: source, generated evidence, proposed claim, or runtime-owned.
|
|
26
|
+
- Status: ready, warning, blocked, or proposed.
|
|
27
|
+
- Fix path: the smallest next reviewable change.
|
|
28
|
+
|
|
29
|
+
Do not introduce independent tenant semantics, new visibility terms, hidden
|
|
30
|
+
provider boundaries, or runtime mutation claims. If a check cannot run, report
|
|
31
|
+
the exact command, stderr, and blocker.
|
|
32
|
+
|
|
33
|
+
## Safety And Hygiene
|
|
34
|
+
|
|
35
|
+
- Keep package-facing output generic and placeholder-only.
|
|
36
|
+
- Do not include person-specific, tenant-private, project-private, transcript,
|
|
37
|
+
support-bundle, local absolute path, agent-local state, key, token, or
|
|
38
|
+
credential material.
|
|
39
|
+
- Prefer static inspection and existing defensive tests for security-sensitive
|
|
40
|
+
review work.
|
|
41
|
+
- Frame checks as verifying that a control refuses, blocks, or fails closed.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
|
|
3
|
+
export function analysisAdapterDryRun(manifestPath = null) {
|
|
4
|
+
const manifest = manifestPath && fs.existsSync(manifestPath) ? JSON.parse(fs.readFileSync(manifestPath, 'utf8')) : {}
|
|
5
|
+
if (manifest.enabled === true) throw new Error('model-assisted analysis execution is disabled in this release')
|
|
6
|
+
if (manifest.endpoint || manifest.token || manifest.apiBase || manifest.proxyUrl) throw new Error('model-assisted analysis manifest must not declare network/provider egress')
|
|
7
|
+
return {
|
|
8
|
+
schema: 'mnstry.atelier-analysis-adapter-dry-run@v1',
|
|
9
|
+
provider: 'analysis',
|
|
10
|
+
enabled: false,
|
|
11
|
+
canonicalMutation: false,
|
|
12
|
+
output: 'atelier-claim@v1 proposed claims only',
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function runAnalysisAdapterCommand(argv = process.argv.slice(2)) {
|
|
17
|
+
const manifestArg = argv.find((arg) => arg.startsWith('--manifest='))
|
|
18
|
+
const report = analysisAdapterDryRun(manifestArg ? manifestArg.slice('--manifest='.length) : null)
|
|
19
|
+
console.log(JSON.stringify(report, null, 2))
|
|
20
|
+
}
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'node:fs'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
|
|
7
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
8
|
+
const packageRoot = path.resolve(__dirname, '../..')
|
|
9
|
+
|
|
10
|
+
export const manifestSchema = 'analysis-adapter-manifest@v1'
|
|
11
|
+
export const claimSchema = 'atelier-claim@v1'
|
|
12
|
+
export const provider = 'analysis'
|
|
13
|
+
export const harnessPolicy = 'claim-only-local-disabled'
|
|
14
|
+
export const localAnalysisRoot = '.mnstry/atelier/analysis'
|
|
15
|
+
export const fixtureRoot = path.join(packageRoot, 'fixtures/analysis')
|
|
16
|
+
|
|
17
|
+
export const defaultAnalysisClaimContract = {
|
|
18
|
+
schema: 'mnstry.atelier-analysis-claim-contract@v1',
|
|
19
|
+
provider,
|
|
20
|
+
claimSchema,
|
|
21
|
+
harnessPolicy,
|
|
22
|
+
authority: {
|
|
23
|
+
claimOnly: true,
|
|
24
|
+
frontMatterMutation: false,
|
|
25
|
+
graphRelationMutation: false,
|
|
26
|
+
publicExportFeed: false,
|
|
27
|
+
mcpFeed: false,
|
|
28
|
+
runtimeImport: false,
|
|
29
|
+
directCanonicalWrite: false,
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const authorityPolicyKeys = new Set([
|
|
34
|
+
'claimOnly',
|
|
35
|
+
'frontMatterMutation',
|
|
36
|
+
'graphRelationMutation',
|
|
37
|
+
'publicExportFeed',
|
|
38
|
+
'mcpFeed',
|
|
39
|
+
'runtimeImport',
|
|
40
|
+
'directCanonicalWrite',
|
|
41
|
+
])
|
|
42
|
+
|
|
43
|
+
const forbiddenAuthorityKeys = new Map([
|
|
44
|
+
['frontMatterMutation', 'front matter mutation'],
|
|
45
|
+
['frontmatterMutation', 'front matter mutation'],
|
|
46
|
+
['frontmatter', 'canonical front matter'],
|
|
47
|
+
['frontMatter', 'canonical front matter'],
|
|
48
|
+
['graphRelationMutation', 'graph relation mutation'],
|
|
49
|
+
['graphRelations', 'graph relations'],
|
|
50
|
+
['relations', 'graph relations'],
|
|
51
|
+
['edges', 'graph relation mutation'],
|
|
52
|
+
['publicExportFeed', 'public export feed'],
|
|
53
|
+
['publicExport', 'public exports'],
|
|
54
|
+
['publicExports', 'public exports'],
|
|
55
|
+
['mcpFeed', 'MCP feed'],
|
|
56
|
+
['runtimeImport', 'runtime import'],
|
|
57
|
+
['runtimeApply', 'runtime import'],
|
|
58
|
+
['directCanonicalWrite', 'direct canonical write'],
|
|
59
|
+
['canonicalWrite', 'direct canonical write'],
|
|
60
|
+
])
|
|
61
|
+
|
|
62
|
+
const hiddenProviderKeys = new Map([
|
|
63
|
+
['modelProvider', 'hidden model provider'],
|
|
64
|
+
['apiKey', 'hidden model provider credential'],
|
|
65
|
+
['apiToken', 'hidden model provider credential'],
|
|
66
|
+
['secret', 'hidden model provider credential'],
|
|
67
|
+
])
|
|
68
|
+
|
|
69
|
+
const executionKeys = new Map([
|
|
70
|
+
['execute', 'model-assisted analysis execution'],
|
|
71
|
+
['executeCommand', 'model-assisted analysis execution command'],
|
|
72
|
+
['runCommand', 'model-assisted analysis execution command'],
|
|
73
|
+
['shellCommand', 'model-assisted analysis execution command'],
|
|
74
|
+
['installCommand', 'model-assisted analysis install command'],
|
|
75
|
+
['network', 'network access'],
|
|
76
|
+
])
|
|
77
|
+
|
|
78
|
+
const manifestRootKeys = new Set(['schema', 'provider', 'enabled', 'outputRoot', 'claimContract', 'harness', 'canonicalMutation', 'authority'])
|
|
79
|
+
const manifestHarnessKeys = new Set(['policy', 'hiddenModelProvider', 'network', 'analysisExecution'])
|
|
80
|
+
const manifestAuthorityKeys = new Set([...authorityPolicyKeys])
|
|
81
|
+
const claimKeys = new Set(['schema', 'claimId', 'subject', 'predicate', 'object', 'provider', 'status', 'promoted', 'confidence', 'evidence', 'createdAt', 'notes'])
|
|
82
|
+
|
|
83
|
+
function isPlainObject(value) {
|
|
84
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function joinPath(base, key) {
|
|
88
|
+
return base ? `${base}.${key}` : String(key)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function valueAttemptsAuthority(value) {
|
|
92
|
+
return value === true || value === 'true' || value === 'enabled' || value === 'apply' || value === 'write'
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function readJson(file) {
|
|
96
|
+
return JSON.parse(fs.readFileSync(file, 'utf8'))
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function collectContractAttempts(value, {
|
|
100
|
+
pathLabel = '',
|
|
101
|
+
attempts = [],
|
|
102
|
+
skipExecutionNetworkKey = false,
|
|
103
|
+
} = {}) {
|
|
104
|
+
if (!value || typeof value !== 'object') return attempts
|
|
105
|
+
for (const [key, item] of Object.entries(value)) {
|
|
106
|
+
const current = joinPath(pathLabel, key)
|
|
107
|
+
if (forbiddenAuthorityKeys.has(key) && valueAttemptsAuthority(item)) {
|
|
108
|
+
attempts.push(`${current} attempts ${forbiddenAuthorityKeys.get(key)}`)
|
|
109
|
+
}
|
|
110
|
+
if (hiddenProviderKeys.has(key) && item != null && item !== false) {
|
|
111
|
+
attempts.push(`${current} attempts ${hiddenProviderKeys.get(key)}`)
|
|
112
|
+
}
|
|
113
|
+
if (executionKeys.has(key) && item != null && item !== false && !(skipExecutionNetworkKey && key === 'network')) {
|
|
114
|
+
if (key === 'network' && item === 'none') {
|
|
115
|
+
// Explicit no-network posture is allowed.
|
|
116
|
+
} else {
|
|
117
|
+
attempts.push(`${current} attempts ${executionKeys.get(key)}`)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (item && typeof item === 'object') {
|
|
121
|
+
collectContractAttempts(item, {
|
|
122
|
+
pathLabel: current,
|
|
123
|
+
attempts,
|
|
124
|
+
skipExecutionNetworkKey,
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return attempts
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function validateLocalOutputRoot(outputRoot) {
|
|
132
|
+
const errors = []
|
|
133
|
+
if (typeof outputRoot !== 'string' || !outputRoot) {
|
|
134
|
+
errors.push('outputRoot is required')
|
|
135
|
+
return errors
|
|
136
|
+
}
|
|
137
|
+
if (path.isAbsolute(outputRoot)) errors.push('outputRoot must not be absolute')
|
|
138
|
+
const normalized = outputRoot.replaceAll('\\', '/')
|
|
139
|
+
if (normalized.split('/').includes('..')) errors.push('outputRoot must not escape via ..')
|
|
140
|
+
if (!(normalized === localAnalysisRoot || normalized.startsWith(`${localAnalysisRoot}/`))) {
|
|
141
|
+
errors.push(`outputRoot must live under ${localAnalysisRoot}`)
|
|
142
|
+
}
|
|
143
|
+
return errors
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function validateContractShape(contract = defaultAnalysisClaimContract) {
|
|
147
|
+
const errors = []
|
|
148
|
+
if (contract?.schema !== 'mnstry.atelier-analysis-claim-contract@v1') {
|
|
149
|
+
errors.push('contract schema must be mnstry.atelier-analysis-claim-contract@v1')
|
|
150
|
+
}
|
|
151
|
+
if (contract?.provider !== provider) errors.push('contract provider must be analysis')
|
|
152
|
+
if (contract?.claimSchema !== claimSchema) errors.push('contract claimSchema must be atelier-claim@v1')
|
|
153
|
+
if (contract?.harnessPolicy !== harnessPolicy) errors.push(`contract harnessPolicy must be ${harnessPolicy}`)
|
|
154
|
+
if (contract?.authority?.claimOnly !== true) errors.push('authority.claimOnly must be true')
|
|
155
|
+
for (const key of authorityPolicyKeys) {
|
|
156
|
+
if (key === 'claimOnly') continue
|
|
157
|
+
if (contract?.authority?.[key] !== false) errors.push(`authority.${key} must be false`)
|
|
158
|
+
}
|
|
159
|
+
errors.push(...collectContractAttempts(contract, { skipExecutionNetworkKey: true }))
|
|
160
|
+
return errors
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function validateManifest(manifest, { contract = defaultAnalysisClaimContract } = {}) {
|
|
164
|
+
const errors = validateContractShape(contract)
|
|
165
|
+
const warnings = []
|
|
166
|
+
const normalized = structuredClone(manifest || {})
|
|
167
|
+
if (!isPlainObject(normalized)) {
|
|
168
|
+
return { errors: ['manifest must be an object'], warnings, manifest: null }
|
|
169
|
+
}
|
|
170
|
+
for (const key of Object.keys(normalized)) {
|
|
171
|
+
if (!manifestRootKeys.has(key)) errors.push(`manifest has unknown property ${key}`)
|
|
172
|
+
}
|
|
173
|
+
if (normalized.schema !== manifestSchema) errors.push(`schema must be ${manifestSchema}`)
|
|
174
|
+
if (normalized.provider !== provider) errors.push('provider must be analysis')
|
|
175
|
+
if (normalized.enabled == null) {
|
|
176
|
+
normalized.enabled = false
|
|
177
|
+
warnings.push('enabled missing; defaulting to false')
|
|
178
|
+
}
|
|
179
|
+
if (normalized.enabled !== false) errors.push('enabled must be false until the operator explicitly installs an adapter')
|
|
180
|
+
errors.push(...validateLocalOutputRoot(normalized.outputRoot))
|
|
181
|
+
if (normalized.claimContract !== claimSchema) errors.push(`claimContract must be ${claimSchema}`)
|
|
182
|
+
|
|
183
|
+
const harness = normalized.harness || {}
|
|
184
|
+
if (!isPlainObject(harness)) errors.push('harness must be an object')
|
|
185
|
+
for (const key of Object.keys(harness)) {
|
|
186
|
+
if (!manifestHarnessKeys.has(key)) errors.push(`harness has unknown property ${key}`)
|
|
187
|
+
}
|
|
188
|
+
if (harness.policy !== harnessPolicy) errors.push(`harness.policy must be ${harnessPolicy}`)
|
|
189
|
+
if (harness.hiddenModelProvider !== false) errors.push('harness.hiddenModelProvider must be false')
|
|
190
|
+
if (harness.network !== 'none') errors.push('harness.network must be none')
|
|
191
|
+
if (harness.analysisExecution !== false) errors.push('harness.analysisExecution must be false')
|
|
192
|
+
|
|
193
|
+
if (normalized.canonicalMutation !== false) errors.push('canonicalMutation must be false')
|
|
194
|
+
const authority = normalized.authority || {}
|
|
195
|
+
if (!isPlainObject(authority)) errors.push('authority must be an object')
|
|
196
|
+
for (const key of Object.keys(authority)) {
|
|
197
|
+
if (!manifestAuthorityKeys.has(key)) errors.push(`authority has unknown property ${key}`)
|
|
198
|
+
}
|
|
199
|
+
if (authority.claimOnly !== true) errors.push('authority.claimOnly must be true')
|
|
200
|
+
for (const key of authorityPolicyKeys) {
|
|
201
|
+
if (key === 'claimOnly') continue
|
|
202
|
+
if (authority[key] !== false) errors.push(`authority.${key} must be false`)
|
|
203
|
+
}
|
|
204
|
+
errors.push(...collectContractAttempts(normalized, { skipExecutionNetworkKey: true }))
|
|
205
|
+
return { errors, warnings, manifest: normalized }
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function normalizeOutputClaims(output) {
|
|
209
|
+
if (Array.isArray(output)) return output
|
|
210
|
+
if (isPlainObject(output) && Array.isArray(output.claims)) return output.claims
|
|
211
|
+
return null
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export function validateAdapterOutput(output, { nodes = null, contract = defaultAnalysisClaimContract } = {}) {
|
|
215
|
+
const errors = validateContractShape(contract)
|
|
216
|
+
if (isPlainObject(output) && (Array.isArray(output.nodes) || Array.isArray(output.edges))) {
|
|
217
|
+
errors.push('model-assisted analysis output must be a single atelier-claim@v1 claim list, not native graph nodes/edges')
|
|
218
|
+
errors.push('native graph output attempts graph relation mutation')
|
|
219
|
+
}
|
|
220
|
+
const claims = normalizeOutputClaims(output)
|
|
221
|
+
if (!claims) {
|
|
222
|
+
errors.push('model-assisted analysis output must be a single atelier-claim@v1 claim list')
|
|
223
|
+
return { errors, claimCount: 0 }
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
for (const [index, claim] of claims.entries()) {
|
|
227
|
+
const label = `claims[${index}]`
|
|
228
|
+
if (!isPlainObject(claim)) {
|
|
229
|
+
errors.push(`${label} must be an object`)
|
|
230
|
+
continue
|
|
231
|
+
}
|
|
232
|
+
for (const key of Object.keys(claim)) {
|
|
233
|
+
if (!claimKeys.has(key)) errors.push(`${label} has unknown key ${key}`)
|
|
234
|
+
}
|
|
235
|
+
if (claim.schema !== claimSchema) errors.push(`${label}.schema must be ${claimSchema}`)
|
|
236
|
+
if (claim.provider !== provider) errors.push(`${label}.provider must be analysis`)
|
|
237
|
+
if (typeof claim.claimId !== 'string' || !claim.claimId.startsWith('claim:analysis:')) {
|
|
238
|
+
errors.push(`${label}.claimId must start with claim:analysis:`)
|
|
239
|
+
}
|
|
240
|
+
for (const key of ['subject', 'predicate', 'object']) {
|
|
241
|
+
if (typeof claim[key] !== 'string' || !claim[key]) errors.push(`${label}.${key} is required`)
|
|
242
|
+
}
|
|
243
|
+
if (claim.status !== 'proposed') errors.push(`${label}.status must be proposed`)
|
|
244
|
+
if (claim.promoted !== false) errors.push(`${label}.promoted must remain false`)
|
|
245
|
+
if (typeof claim.confidence !== 'number' || claim.confidence < 0 || claim.confidence > 1) {
|
|
246
|
+
errors.push(`${label}.confidence must be a number between 0 and 1`)
|
|
247
|
+
}
|
|
248
|
+
if (!Array.isArray(claim.evidence) || claim.evidence.length === 0) {
|
|
249
|
+
errors.push(`${label}.evidence must include at least one source reference`)
|
|
250
|
+
}
|
|
251
|
+
if (nodes && !nodes.some((node) => node?.id === claim.subject)) {
|
|
252
|
+
errors.push(`${label}.subject does not match a known graph node`)
|
|
253
|
+
}
|
|
254
|
+
errors.push(...collectContractAttempts(claim).map((attempt) => `${label}.${attempt}`))
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return { errors, claimCount: claims.length }
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function isJsonFile(file) {
|
|
261
|
+
return file.endsWith('.json')
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export function checkFixtureSet({ root = fixtureRoot, nodes = null } = {}) {
|
|
265
|
+
const errors = []
|
|
266
|
+
let fixtureCount = 0
|
|
267
|
+
let invalidFixtureCount = 0
|
|
268
|
+
const validDir = path.join(root, 'valid')
|
|
269
|
+
const invalidDir = path.join(root, 'invalid')
|
|
270
|
+
|
|
271
|
+
if (fs.existsSync(validDir)) {
|
|
272
|
+
for (const name of fs.readdirSync(validDir).filter(isJsonFile).sort()) {
|
|
273
|
+
fixtureCount += 1
|
|
274
|
+
const result = validateAdapterOutput(readJson(path.join(validDir, name)), { nodes })
|
|
275
|
+
errors.push(...result.errors.map((error) => `${name}: ${error}`))
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (fs.existsSync(invalidDir)) {
|
|
279
|
+
for (const name of fs.readdirSync(invalidDir).filter(isJsonFile).sort()) {
|
|
280
|
+
invalidFixtureCount += 1
|
|
281
|
+
const result = validateAdapterOutput(readJson(path.join(invalidDir, name)), { nodes })
|
|
282
|
+
if (result.errors.length === 0) errors.push(`${name}: invalid fixture unexpectedly passed`)
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return { errors, fixtureCount, invalidFixtureCount }
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export function runAnalysisClaimContractCheck({
|
|
289
|
+
manifestPath = null,
|
|
290
|
+
fixtures = fixtureRoot,
|
|
291
|
+
contract = defaultAnalysisClaimContract,
|
|
292
|
+
} = {}) {
|
|
293
|
+
const report = {
|
|
294
|
+
status: 'disabled',
|
|
295
|
+
enabled: false,
|
|
296
|
+
analysisExecuted: false,
|
|
297
|
+
networkCalls: false,
|
|
298
|
+
canonicalMutation: false,
|
|
299
|
+
errors: [],
|
|
300
|
+
warnings: [],
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
report.errors.push(...validateContractShape(contract))
|
|
304
|
+
if (manifestPath && fs.existsSync(manifestPath)) {
|
|
305
|
+
const manifestResult = validateManifest(readJson(manifestPath), { contract })
|
|
306
|
+
report.errors.push(...manifestResult.errors)
|
|
307
|
+
report.warnings.push(...manifestResult.warnings)
|
|
308
|
+
report.enabled = manifestResult.manifest?.enabled === true
|
|
309
|
+
} else if (manifestPath) {
|
|
310
|
+
report.warnings.push('manifest missing; model-assisted analysis remains disabled')
|
|
311
|
+
}
|
|
312
|
+
const fixtureResult = checkFixtureSet({ root: fixtures })
|
|
313
|
+
report.errors.push(...fixtureResult.errors)
|
|
314
|
+
report.fixtureCount = fixtureResult.fixtureCount
|
|
315
|
+
report.invalidFixtureCount = fixtureResult.invalidFixtureCount
|
|
316
|
+
report.status = report.errors.length ? 'failed' : 'disabled'
|
|
317
|
+
return report
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function formatReport(report) {
|
|
321
|
+
return JSON.stringify(report, null, 2)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function main() {
|
|
325
|
+
const manifestArg = process.argv.find((arg) => arg.startsWith('--manifest='))
|
|
326
|
+
const manifestPath = manifestArg ? manifestArg.slice('--manifest='.length) : null
|
|
327
|
+
const report = runAnalysisClaimContractCheck({ manifestPath })
|
|
328
|
+
console.log(formatReport(report))
|
|
329
|
+
if (report.errors.length) process.exitCode = 1
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const currentFile = fileURLToPath(import.meta.url)
|
|
333
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === currentFile) {
|
|
334
|
+
main()
|
|
335
|
+
}
|