@jeger-ai/opengantry 1.0.0 → 1.1.0
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/README.md +9 -5
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +3 -1
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/verify.d.ts.map +1 -1
- package/dist/cli/commands/verify.js +64 -3
- package/dist/cli/commands/verify.js.map +1 -1
- package/dist/cli/lib/doctor-orchestration.d.ts.map +1 -1
- package/dist/cli/lib/doctor-orchestration.js +9 -2
- package/dist/cli/lib/doctor-orchestration.js.map +1 -1
- package/dist/cli/lib/doctor-substrate-drift.d.ts +7 -0
- package/dist/cli/lib/doctor-substrate-drift.d.ts.map +1 -0
- package/dist/cli/lib/doctor-substrate-drift.js +35 -0
- package/dist/cli/lib/doctor-substrate-drift.js.map +1 -0
- package/dist/cli/lib/file-merge-gxt.d.ts +4 -0
- package/dist/cli/lib/file-merge-gxt.d.ts.map +1 -0
- package/dist/cli/lib/file-merge-gxt.js +35 -0
- package/dist/cli/lib/file-merge-gxt.js.map +1 -0
- package/dist/cli/lib/fix-hints.d.ts +1 -0
- package/dist/cli/lib/fix-hints.d.ts.map +1 -1
- package/dist/cli/lib/fix-hints.js +14 -1
- package/dist/cli/lib/fix-hints.js.map +1 -1
- package/dist/cli/lib/git-repo.d.ts +2 -0
- package/dist/cli/lib/git-repo.d.ts.map +1 -1
- package/dist/cli/lib/git-repo.js +13 -0
- package/dist/cli/lib/git-repo.js.map +1 -1
- package/dist/cli/lib/gxt-error-codes.d.ts +2 -0
- package/dist/cli/lib/gxt-error-codes.d.ts.map +1 -1
- package/dist/cli/lib/gxt-error-codes.js +3 -1
- package/dist/cli/lib/gxt-error-codes.js.map +1 -1
- package/dist/cli/lib/init-asset-catalog.d.ts.map +1 -1
- package/dist/cli/lib/init-asset-catalog.js +6 -0
- package/dist/cli/lib/init-asset-catalog.js.map +1 -1
- package/dist/cli/lib/init-tutorial.d.ts.map +1 -1
- package/dist/cli/lib/init-tutorial.js +1 -0
- package/dist/cli/lib/init-tutorial.js.map +1 -1
- package/dist/cli/lib/mcp-runtime.d.ts +3 -26
- package/dist/cli/lib/mcp-runtime.d.ts.map +1 -1
- package/dist/cli/lib/mcp-runtime.js +7 -70
- package/dist/cli/lib/mcp-runtime.js.map +1 -1
- package/dist/cli/lib/mcp-tools-register.d.ts.map +1 -1
- package/dist/cli/lib/mcp-tools-register.js +2 -1
- package/dist/cli/lib/mcp-tools-register.js.map +1 -1
- package/dist/cli/lib/trace-evidence.d.ts +32 -0
- package/dist/cli/lib/trace-evidence.d.ts.map +1 -0
- package/dist/cli/lib/trace-evidence.js +148 -0
- package/dist/cli/lib/trace-evidence.js.map +1 -0
- package/dist/cli/lib/trace-failure-kind.d.ts +1 -1
- package/dist/cli/lib/trace-failure-kind.d.ts.map +1 -1
- package/dist/cli/lib/trace-failure-kind.js +2 -0
- package/dist/cli/lib/trace-failure-kind.js.map +1 -1
- package/dist/cli/lib/upgrade-apply.d.ts.map +1 -1
- package/dist/cli/lib/upgrade-apply.js +2 -1
- package/dist/cli/lib/upgrade-apply.js.map +1 -1
- package/dist/cli/lib/upgrade-plan.d.ts.map +1 -1
- package/dist/cli/lib/upgrade-plan.js +2 -1
- package/dist/cli/lib/upgrade-plan.js.map +1 -1
- package/dist/cli/lib/verify-engine.d.ts +5 -2
- package/dist/cli/lib/verify-engine.d.ts.map +1 -1
- package/dist/cli/lib/verify-engine.js +27 -4
- package/dist/cli/lib/verify-engine.js.map +1 -1
- package/dist/cli/lib/verify-flow.d.ts +2 -0
- package/dist/cli/lib/verify-flow.d.ts.map +1 -1
- package/dist/cli/lib/verify-flow.js +11 -1
- package/dist/cli/lib/verify-flow.js.map +1 -1
- package/dist/cli/lib/verify-repair.d.ts.map +1 -1
- package/dist/cli/lib/verify-repair.js +3 -1
- package/dist/cli/lib/verify-repair.js.map +1 -1
- package/dist/cli/lib/verify-result-payload.d.ts +41 -0
- package/dist/cli/lib/verify-result-payload.d.ts.map +1 -0
- package/dist/cli/lib/verify-result-payload.js +118 -0
- package/dist/cli/lib/verify-result-payload.js.map +1 -0
- package/dist/cli/lib/verify-types.d.ts +4 -0
- package/dist/cli/lib/verify-types.d.ts.map +1 -1
- package/dist/cli/lib/version.gen.d.ts +1 -1
- package/dist/cli/lib/version.gen.js +1 -1
- package/dist/cli/program-workflow.d.ts.map +1 -1
- package/dist/cli/program-workflow.js +4 -0
- package/dist/cli/program-workflow.js.map +1 -1
- package/package.json +1 -1
- package/templates/.gitagent/foreman/SUBSTRATE.version.json +1 -1
- package/templates/.githooks/pre-push +3 -3
- package/templates/.github/workflows/gxt-validate.yml +19 -0
- package/templates/.gitignore.gxt +0 -1
- package/templates/.prettierignore.gxt +1 -0
- package/templates/integrations/compatibility.json +1 -1
- package/templates/scripts/verify-pr-missions.sh +141 -0
- package/dist/cli/lib/gitignore-gxt.d.ts +0 -2
- package/dist/cli/lib/gitignore-gxt.d.ts.map +0 -1
- package/dist/cli/lib/gitignore-gxt.js +0 -24
- package/dist/cli/lib/gitignore-gxt.js.map +0 -1
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# Validates OpenGantry substrate: Foreman MANIFEST + path-scoped [MSN-NNNN] on PRs.
|
|
2
2
|
#
|
|
3
|
+
# PR governance (pull_request only): mission PRs must target the repo default branch
|
|
4
|
+
# (override: repository variable GXT_INTEGRATION_BRANCH when integration branch differs).
|
|
3
5
|
# MSN policy (pull_request only): commits touching MSN-enforced paths must have
|
|
4
6
|
# subject [MSN-NNNN] (four digits) or a valid gxt-bypass git note.
|
|
7
|
+
# Mission purity: scripts/verify-pr-missions.sh — one [MSN-NNNN] per PR commit range.
|
|
5
8
|
# Paths = fixed substrate (.gitagent/, WORKER_LOG.md, .githooks/, gxt-validate.yml)
|
|
6
9
|
# + all MANIFEST skills[].tmvc_roots (Node via scripts/gxt-manifest-lib.mjs).
|
|
7
10
|
# Logic: scripts/validate-gxt.sh — keep workflow header and script in sync.
|
|
@@ -17,6 +20,19 @@ permissions:
|
|
|
17
20
|
contents: read
|
|
18
21
|
|
|
19
22
|
jobs:
|
|
23
|
+
pr_governance:
|
|
24
|
+
if: github.event_name == 'pull_request'
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
steps:
|
|
27
|
+
- name: Enforce base branch isolation
|
|
28
|
+
run: |
|
|
29
|
+
base="${{ github.event.pull_request.base.ref }}"
|
|
30
|
+
expected="${{ vars.GXT_INTEGRATION_BRANCH || github.event.repository.default_branch }}"
|
|
31
|
+
if [ "$base" != "$expected" ]; then
|
|
32
|
+
echo "::error::Governance Violation: Mission PR targets '$base' instead of '$expected'. Stacking missions violates blast-radius isolation. Re-target the PR to '$expected'."
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
|
|
20
36
|
manifest:
|
|
21
37
|
runs-on: ubuntu-latest
|
|
22
38
|
steps:
|
|
@@ -47,6 +63,7 @@ jobs:
|
|
|
47
63
|
|
|
48
64
|
code_quality:
|
|
49
65
|
if: github.event_name == 'pull_request'
|
|
66
|
+
needs: pr_governance
|
|
50
67
|
runs-on: ubuntu-latest
|
|
51
68
|
steps:
|
|
52
69
|
- uses: actions/checkout@v6
|
|
@@ -86,6 +103,7 @@ jobs:
|
|
|
86
103
|
|
|
87
104
|
msn_commits:
|
|
88
105
|
if: github.event_name == 'pull_request'
|
|
106
|
+
needs: pr_governance
|
|
89
107
|
runs-on: ubuntu-latest
|
|
90
108
|
steps:
|
|
91
109
|
- uses: actions/checkout@v6
|
|
@@ -104,6 +122,7 @@ jobs:
|
|
|
104
122
|
|
|
105
123
|
mission_verify:
|
|
106
124
|
if: github.event_name == 'pull_request'
|
|
125
|
+
needs: pr_governance
|
|
107
126
|
runs-on: ubuntu-latest
|
|
108
127
|
steps:
|
|
109
128
|
- uses: actions/checkout@v6
|
package/templates/.gitignore.gxt
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
WORKER_LOG.md
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# PR / branch mission verify: mission purity, triple-dot file diff, full gapman verify on changed missions.
|
|
3
|
+
# Usage:
|
|
4
|
+
# BASE_SHA=<base> HEAD_SHA=<head> ./scripts/verify-pr-missions.sh
|
|
5
|
+
# ./scripts/verify-pr-missions.sh <base-ref> <head-ref> # rev-parse refs to SHAs
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
ROOT="$(git rev-parse --show-toplevel 2>/dev/null)" || {
|
|
9
|
+
echo "verify-pr-missions: not inside a git repository" >&2
|
|
10
|
+
exit 1
|
|
11
|
+
}
|
|
12
|
+
cd "$ROOT"
|
|
13
|
+
|
|
14
|
+
GXT_MANIFEST_LIB="scripts/gxt-manifest-lib.mjs"
|
|
15
|
+
MISSIONS_PREFIX=".gitagent/missions/"
|
|
16
|
+
|
|
17
|
+
resolve_sha() {
|
|
18
|
+
git rev-parse --verify "${1}^{commit}" 2>/dev/null
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if [[ -n "${1:-}" && -n "${2:-}" ]]; then
|
|
22
|
+
BASE_SHA="$(resolve_sha "$1")" || {
|
|
23
|
+
echo "verify-pr-missions: invalid base ref: $1" >&2
|
|
24
|
+
exit 2
|
|
25
|
+
}
|
|
26
|
+
HEAD_SHA="$(resolve_sha "$2")" || {
|
|
27
|
+
echo "verify-pr-missions: invalid head ref: $2" >&2
|
|
28
|
+
exit 2
|
|
29
|
+
}
|
|
30
|
+
elif [[ -n "${BASE_SHA:-}" && -n "${HEAD_SHA:-}" ]]; then
|
|
31
|
+
BASE_SHA="$(resolve_sha "$BASE_SHA")" || {
|
|
32
|
+
echo "verify-pr-missions: invalid BASE_SHA" >&2
|
|
33
|
+
exit 2
|
|
34
|
+
}
|
|
35
|
+
HEAD_SHA="$(resolve_sha "$HEAD_SHA")" || {
|
|
36
|
+
echo "verify-pr-missions: invalid HEAD_SHA" >&2
|
|
37
|
+
exit 2
|
|
38
|
+
}
|
|
39
|
+
else
|
|
40
|
+
echo "verify-pr-missions: set BASE_SHA and HEAD_SHA, or pass <base-ref> <head-ref>" >&2
|
|
41
|
+
echo " CI: BASE_SHA=\${{ github.event.pull_request.base.sha }} HEAD_SHA=\${{ github.event.pull_request.head.sha }}" >&2
|
|
42
|
+
exit 2
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
mapfile -t UNIQUE_MSNS < <(
|
|
46
|
+
git log --no-merges --format=%s "${BASE_SHA}..${HEAD_SHA}" \
|
|
47
|
+
| grep -Eo '\[MSN-[0-9]{4}\]' | sort -u || true
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
if [[ ${#UNIQUE_MSNS[@]} -gt 1 ]]; then
|
|
51
|
+
echo "verify-pr-missions FAILED: mission contamination detected" >&2
|
|
52
|
+
echo " This PR contains commits from multiple missions:" >&2
|
|
53
|
+
printf ' %s\n' "${UNIQUE_MSNS[@]}" >&2
|
|
54
|
+
echo " OpenGantry requires strict blast-radius isolation. Rebase this branch onto the integration branch (e.g. origin/main)." >&2
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
if [[ -f dist/cli/index.js ]]; then
|
|
59
|
+
GAPMAN=(node dist/cli/index.js)
|
|
60
|
+
elif command -v gapman >/dev/null 2>&1; then
|
|
61
|
+
GAPMAN=(gapman)
|
|
62
|
+
else
|
|
63
|
+
echo "verify-pr-missions: build gapman first (npm run build)" >&2
|
|
64
|
+
exit 1
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
is_verifiable_mission() {
|
|
68
|
+
local p="$1"
|
|
69
|
+
[[ "$p" == "${MISSIONS_PREFIX}"* ]] || return 1
|
|
70
|
+
[[ "$p" =~ \.(ya?ml|md)$ ]] || return 1
|
|
71
|
+
[[ "$(basename "$p")" == "README.md" ]] && return 1
|
|
72
|
+
return 0
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
is_msn_enforced_path() {
|
|
76
|
+
local p="$1"
|
|
77
|
+
local prefix
|
|
78
|
+
for prefix in "${MSN_PREFIXES[@]}"; do
|
|
79
|
+
[[ -z "$prefix" ]] && continue
|
|
80
|
+
if [[ "$p" == "$prefix" ]]; then return 0; fi
|
|
81
|
+
if [[ "$prefix" == */ ]] && [[ "$p" == "$prefix"* ]]; then return 0; fi
|
|
82
|
+
if [[ "$prefix" != */ ]] && [[ "$p" == "$prefix"/* ]]; then return 0; fi
|
|
83
|
+
done
|
|
84
|
+
return 1
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
mapfile -t MSN_PREFIXES < <(node "$GXT_MANIFEST_LIB" prefixes "$ROOT")
|
|
88
|
+
|
|
89
|
+
mapfile -t DIFF_FILES < <(
|
|
90
|
+
git diff --name-only --diff-filter=ACMRT "${BASE_SHA}...${HEAD_SHA}" || true
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
needs_mission=0
|
|
94
|
+
for f in "${DIFF_FILES[@]}"; do
|
|
95
|
+
[[ -n "$f" ]] || continue
|
|
96
|
+
if is_msn_enforced_path "$f"; then
|
|
97
|
+
needs_mission=1
|
|
98
|
+
break
|
|
99
|
+
fi
|
|
100
|
+
done
|
|
101
|
+
|
|
102
|
+
mapfile -t CHANGED_MISSIONS < <(
|
|
103
|
+
for f in "${DIFF_FILES[@]}"; do
|
|
104
|
+
[[ -n "$f" ]] || continue
|
|
105
|
+
if is_verifiable_mission "$f" && [[ -f "$f" ]]; then
|
|
106
|
+
echo "$f"
|
|
107
|
+
fi
|
|
108
|
+
done | sort -u
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
if [[ "$needs_mission" -eq 1 && ${#CHANGED_MISSIONS[@]} -eq 0 ]]; then
|
|
112
|
+
echo "verify-pr-missions FAILED: diff touches MSN-enforced paths but no mission file under ${MISSIONS_PREFIX}" >&2
|
|
113
|
+
echo " Fix: gapman legislate \"<intent>\" --msn MSN-NNNN --skill-key gapman && include mission YAML in this PR" >&2
|
|
114
|
+
exit 1
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
if [[ ${#CHANGED_MISSIONS[@]} -eq 0 ]]; then
|
|
118
|
+
echo "verify-pr-missions: no changed mission files (${BASE_SHA}...${HEAD_SHA})"
|
|
119
|
+
exit 0
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
if [[ ${#UNIQUE_MSNS[@]} -eq 1 ]]; then
|
|
123
|
+
purity_msn="${UNIQUE_MSNS[0]}"
|
|
124
|
+
purity_msn="${purity_msn#[}"
|
|
125
|
+
purity_msn="${purity_msn%]}"
|
|
126
|
+
for mission in "${CHANGED_MISSIONS[@]}"; do
|
|
127
|
+
base="$(basename "$mission")"
|
|
128
|
+
if [[ "$base" != "${purity_msn}."* ]]; then
|
|
129
|
+
echo "verify-pr-missions FAILED: changed mission file does not match commit MSN tag" >&2
|
|
130
|
+
echo " commits: [${purity_msn}] mission file: ${mission}" >&2
|
|
131
|
+
exit 1
|
|
132
|
+
fi
|
|
133
|
+
done
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
for mission in "${CHANGED_MISSIONS[@]}"; do
|
|
137
|
+
echo "verify-pr-missions: gapman verify --mission ${mission}" >&2
|
|
138
|
+
"${GAPMAN[@]}" verify --mission "$mission" --audience verifier || exit 1
|
|
139
|
+
done
|
|
140
|
+
|
|
141
|
+
echo "verify-pr-missions OK (${#CHANGED_MISSIONS[@]} mission(s))"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gitignore-gxt.d.ts","sourceRoot":"","sources":["../../../src/cli/lib/gitignore-gxt.ts"],"names":[],"mappings":"AAKA,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAmBxF"}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { CLI_NAME } from "./constants.js";
|
|
4
|
-
import { logInfo } from "./cli-io.js";
|
|
5
|
-
export function mergeGitignoreFromTemplate(repoRoot, templatesRoot) {
|
|
6
|
-
const fragmentPath = path.join(templatesRoot, ".gitignore.gxt");
|
|
7
|
-
if (!fs.existsSync(fragmentPath))
|
|
8
|
-
return;
|
|
9
|
-
const lines = fs
|
|
10
|
-
.readFileSync(fragmentPath, "utf8")
|
|
11
|
-
.split(/\r?\n/)
|
|
12
|
-
.map((l) => l.trim())
|
|
13
|
-
.filter((l) => l.length > 0 && !l.startsWith("#"));
|
|
14
|
-
const gitignorePath = path.join(repoRoot, ".gitignore");
|
|
15
|
-
const existing = fs.existsSync(gitignorePath) ? fs.readFileSync(gitignorePath, "utf8") : "";
|
|
16
|
-
const missing = lines.filter((line) => !existing.includes(line));
|
|
17
|
-
if (missing.length === 0)
|
|
18
|
-
return;
|
|
19
|
-
const prefix = existing.length > 0 && !existing.endsWith("\n") ? "\n" : existing.length > 0 ? "" : "";
|
|
20
|
-
const block = `${prefix}\n# OpenGantry (gapman init)\n${missing.join("\n")}\n`;
|
|
21
|
-
fs.writeFileSync(gitignorePath, existing + block, "utf8");
|
|
22
|
-
logInfo(`${CLI_NAME}: appended ${missing.length} line(s) to .gitignore`);
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=gitignore-gxt.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gitignore-gxt.js","sourceRoot":"","sources":["../../../src/cli/lib/gitignore-gxt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,MAAM,UAAU,0BAA0B,CAAC,QAAgB,EAAE,aAAqB;IAChF,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;IAChE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO;IAEzC,MAAM,KAAK,GAAG,EAAE;SACb,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC;SAClC,KAAK,CAAC,OAAO,CAAC;SACd,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAErD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5F,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IACjE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEjC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACtG,MAAM,KAAK,GAAG,GAAG,MAAM,iCAAiC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IAC/E,EAAE,CAAC,aAAa,CAAC,aAAa,EAAE,QAAQ,GAAG,KAAK,EAAE,MAAM,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,QAAQ,cAAc,OAAO,CAAC,MAAM,wBAAwB,CAAC,CAAC;AAC3E,CAAC"}
|