cabloy 5.1.190 → 5.1.192
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/.cabloy-version +1 -1
- package/.github/workflows/agent-governance.yml +39 -0
- package/.github/workflows/docs-pages.yml +1 -0
- package/.gitignore +3 -0
- package/CHANGELOG.md +17 -0
- package/README.md +2 -2
- package/package.json +11 -5
- package/repo-agent-governance/adapters/claude/contract-loop-gate.ts +199 -0
- package/{.claude → repo-agent-governance}/commands/release.md +20 -20
- package/repo-agent-governance/managed-assets.json +887 -0
- package/repo-agent-governance/manifest.json +56 -0
- package/{CLAUDE.md → repo-agent-governance/policies/repository.md} +4 -2
- package/repo-agent-governance/scripts/governance.mjs +570 -0
- package/repo-agent-governance/scripts/pack-check.mjs +43 -0
- package/{.claude → repo-agent-governance}/skills/cabloy-contract-loop/references/contract-loop-map.md +4 -4
- package/{.claude → repo-agent-governance}/skills/cabloy-master-detail/SKILL.md +1 -1
- package/{.claude → repo-agent-governance}/skills/cabloy-module-removal/SKILL.md +1 -1
- package/{.claude → repo-agent-governance}/skills/cabloy-spec-execution/SKILL.md +1 -1
- package/{.claude → repo-agent-governance}/skills/cabloy-spec-execution/references/execution-protocol.md +8 -8
- package/{.claude → repo-agent-governance}/skills/cabloy-spec-execution/references/status-and-evidence.md +9 -9
- package/{.claude → repo-agent-governance}/skills/cabloy-spec-generation/SKILL.md +2 -2
- package/{.claude → repo-agent-governance}/skills/cabloy-spec-generation/references/repo-aware-discovery.md +7 -7
- package/{.claude → repo-agent-governance}/skills/cabloy-spec-generation/references/repo-specs-document-set.md +30 -30
- package/{.claude → repo-agent-governance}/skills/cabloy-spec-generation/references/traceability-and-status-rules.md +9 -9
- package/{.claude → repo-agent-governance}/skills/cabloy-workflow/SKILL.md +7 -8
- package/{.claude → repo-agent-governance}/skills/cabloy-worktree-environment/SKILL.md +9 -9
- package/{.claude → repo-agent-governance}/skills/cabloy-zova-source-reading/SKILL.md +5 -5
- package/repo-agent-governance/tests/governance.test.mjs +295 -0
- package/repo-agent-governance/tools/contract-loop/check.mjs +71 -0
- package/repo-agent-governance/tools/contract-loop/core.mjs +189 -0
- package/repo-agent-governance/tools/spec-charts/generate-implementation-charts.mjs +858 -0
- package/{.claude/skills/cabloy-spec-generation/scripts → repo-agent-governance/tools/spec-charts}/generate-implementation-charts.test.mjs +95 -20
- package/repo-docs/.vitepress/config.mjs +2 -0
- package/repo-docs/ai/agent-governance.md +80 -0
- package/repo-docs/ai/cli-to-skill-map.md +3 -3
- package/repo-docs/ai/docs-skills-rules-mapping.md +27 -26
- package/repo-docs/ai/edition-consistency-checklist.md +8 -6
- package/repo-docs/ai/future-skill-roadmap.md +2 -2
- package/repo-docs/ai/introduction.md +7 -6
- package/repo-docs/ai/repo-guidance.md +3 -2
- package/repo-docs/ai/rules-and-config.md +23 -15
- package/repo-docs/ai/skills.md +7 -7
- package/repo-docs/ai/verification.md +2 -1
- package/repo-docs/demo.md +12 -0
- package/repo-docs/fullstack/contract-loop-playbook.md +1 -1
- package/repo-docs/fullstack/quickstart.md +1 -1
- package/repo-docs/index.md +3 -0
- package/repo-docs/reference/package-map.md +3 -2
- package/repo-docs/reference/repo-scripts.md +17 -2
- package/scripts/bootstrapAgentGovernance.mjs +81 -0
- package/scripts/init.ts +1 -0
- package/scripts/release.ts +15 -0
- package/scripts/upgrade.ts +66 -7
- package/zova/packages-zova/zova/package.json +2 -2
- package/zova/pnpm-lock.yaml +3 -3
- package/zova/src/suite/a-home/modules/home-passport/src/model/passport.ts +2 -7
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/tableCell.actionOperationsRow.tsx +19 -13
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/blockDetails/controller.tsx +11 -0
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/blockToolbarBulk/controller.tsx +7 -4
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/formFieldDetails/controller.tsx +14 -0
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/lib/detailsPermissions.ts +65 -0
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/lib/index.ts +1 -0
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/lib/utils.ts +3 -3
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/types/details.ts +6 -1
- package/zova/src/suite/cabloy-basic/modules/basic-details/test/lib/detailsPermissions.test.ts +125 -0
- package/zova/src/suite-vendor/a-zova/modules/a-openapi/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/permissions.ts +2 -8
- package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-table/src/component/table/controller.tsx +2 -1
- package/zova/src/suite-vendor/a-zova/package.json +3 -3
- package/.claude/hooks/contract-loop-gate.ts +0 -421
- package/.claude/scheduled_tasks.lock +0 -1
- package/.claude/skills/cabloy-spec-generation/scripts/generate-implementation-charts.mjs +0 -385
- /package/{.claude → repo-agent-governance/adapters/claude}/settings.json +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-backend-scaffold/SKILL.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-backend-scaffold/evals/evals.json +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-backend-scaffold/references/backend-thread-map.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-contract-loop/SKILL.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-contract-loop/evals/evals.json +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-contract-loop/references/resource-custom-state-pattern.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-contract-loop/references/verification-checklist.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-domain-planning/SKILL.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-frontend-scaffold/SKILL.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-frontend-scaffold/evals/evals.json +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-frontend-scaffold/references/follow-up-checklist.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-frontend-scaffold/references/frontend-thread-map.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-resource-field-update/SKILL.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-resource-field-update/evals/evals.json +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-resource-field-update/references/custom-renderer-demo-checklist.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-resource-field-update/references/field-update-decision-tree.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-resource-field-update/references/follow-up-checklist.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-resource-field-update/references/verification-checklist.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-spec-execution/evals/evals.json +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-spec-generation/evals/evals.json +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-workflow/evals/evals.json +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-workflow/references/cli-strategy.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-workflow/references/edition-detection.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-worktree-environment/evals/evals.json +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-zova-source-reading/references/analysis-modes.md +0 -0
- /package/{.claude → repo-agent-governance}/skills/cabloy-zova-source-reading/references/core-reading-paths.md +0 -0
package/repo-docs/ai/skills.md
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
Skills are the procedural layer of Cabloy’s AI development model.
|
|
4
4
|
|
|
5
|
-
## Using a Skill
|
|
5
|
+
## Using a Skill
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Root Cabloy skill bundles are authored in `repo-agent-governance/skills/` and rendered to configured Claude Code, Codex, and Cursor adapter locations. Codex and Cursor skill discovery must be confirmed by a version-pinned external smoke check before being presented as supported client behavior. Use the invocation UI and syntax of the active agent; for example, in Claude Code:
|
|
8
8
|
|
|
9
9
|
```text
|
|
10
10
|
/cabloy-spec-generation <business description>
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
The AI guides you through the task-specific confirmation and next steps. See [Generate a Cabloy Suite Specification](/ai/playbook-spec-generation) for the complete planning experience.
|
|
13
|
+
The AI guides you through the task-specific confirmation and next steps. See [Generate a Cabloy Suite Specification](/ai/playbook-spec-generation) for the complete planning experience. See [Agent Governance](/ai/agent-governance) for adapter and capability details.
|
|
14
14
|
|
|
15
15
|
## What a skill should do here
|
|
16
16
|
|
|
@@ -29,8 +29,8 @@ If a generator or refactor command exists, the skill should orchestrate it inste
|
|
|
29
29
|
|
|
30
30
|
## Skill placement
|
|
31
31
|
|
|
32
|
-
-
|
|
33
|
-
- Use subtree-local
|
|
32
|
+
- Author cross-stack, monorepo-wide workflow bundles in `repo-agent-governance/skills/`; generated root adapter copies are not a second authoring surface.
|
|
33
|
+
- Use subtree-local agent skill directories only when a workflow is truly specific to one framework area and has not been approved for portable root governance.
|
|
34
34
|
|
|
35
35
|
## Skill structure recommendation
|
|
36
36
|
|
|
@@ -48,7 +48,7 @@ For edition-aware skills, use [Cabloy Editions: For AI Development](/editions/ov
|
|
|
48
48
|
|
|
49
49
|
## Current root workflow skills
|
|
50
50
|
|
|
51
|
-
The repository currently
|
|
51
|
+
The repository currently authors these cross-stack and monorepo-wide workflows in `repo-agent-governance/skills/` and renders them to root platform adapters; Codex and Cursor discovery remains subject to external client validation:
|
|
52
52
|
|
|
53
53
|
- `cabloy-workflow` for choosing the correct Cabloy work path before implementation
|
|
54
54
|
- `cabloy-domain-planning` for proposing and confirming providerId, suite, and initial module names before scaffolding a new business domain
|
|
@@ -65,7 +65,7 @@ The repository currently provides these cross-stack and monorepo-wide workflows
|
|
|
65
65
|
|
|
66
66
|
The specification workflows show the same boundary: [AI Spec-Driven Development](/ai/ai-spec-driven-development) explains the public Traceable Spec Delivery method, while [Generate a Cabloy Suite Specification](/ai/playbook-spec-generation) and [Execute an Approved Cabloy Specification Increment](/ai/playbook-spec-execution) explain its operational paths. The skills retain branching, confirmation gates, specialist routing, and evidence protocol; suite-local records remain the authority for a specific increment.
|
|
67
67
|
|
|
68
|
-
The module-removal workflow is a good example of why skills belong in
|
|
68
|
+
The module-removal workflow is a good example of why skills belong in `repo-agent-governance/skills/` instead of the concise repository policy: the task needs branching, cleanup order, recovery guidance for generated runtime directories such as `vona/.vona` and `zova/.zova`, and a verification checklist that would be too large for a short repo-wide rule. The canonical bundle is rendered to each supported platform skill adapter.
|
|
69
69
|
|
|
70
70
|
## Advanced subtree-local diagnostics
|
|
71
71
|
|
|
@@ -17,7 +17,8 @@ For skills and repo guidance:
|
|
|
17
17
|
|
|
18
18
|
- confirm the workflow still points to real command entrypoints
|
|
19
19
|
- confirm edition branches match the active repo markers and scripts
|
|
20
|
-
- confirm public docs,
|
|
20
|
+
- confirm public docs, canonical `repo-agent-governance/` assets, and generated platform adapters tell the same story
|
|
21
|
+
- run the deterministic governance checker after changing shared rules, skills, tools, or adapter metadata
|
|
21
22
|
- review edition-aware changes against [Edition Consistency Checklist](/ai/edition-consistency-checklist)
|
|
22
23
|
|
|
23
24
|
## Code-generation verification
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Demo
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Demo
|
|
6
|
+
|
|
7
|
+
Explore the Cabloy demonstration sites:
|
|
8
|
+
|
|
9
|
+
| Site | URL |
|
|
10
|
+
| ---------- | ---------------------------------------------------------------- |
|
|
11
|
+
| Web site | [https://demo.cabloy.com/](https://demo.cabloy.com/) |
|
|
12
|
+
| Admin site | [https://demo.cabloy.com/admin/](https://demo.cabloy.com/admin/) |
|
|
@@ -235,7 +235,7 @@ That means:
|
|
|
235
235
|
|
|
236
236
|
For resource-bound custom endpoints, prefer `rest-resource.model.resource` as the state owner. A module-local model may still exist, but it should remain a semantic facade instead of becoming a second cache owner. When Admin Resource consumption and Web self-service consumption have genuinely different API, scope, projection, or SSR semantics, see [Admin Resource and Web Self-Service](/fullstack/admin-resource-and-web-self-service) for the boundary between Admin owner reuse and a dedicated Web model.
|
|
237
237
|
|
|
238
|
-
See the downstream pattern in
|
|
238
|
+
See the canonical downstream pattern in `repo-agent-governance/skills/cabloy-contract-loop/references/resource-custom-state-pattern.md`.
|
|
239
239
|
|
|
240
240
|
### Stage 5: Consumer verification
|
|
241
241
|
|
|
@@ -24,7 +24,7 @@ Before creating a new Cabloy project, make sure your environment has:
|
|
|
24
24
|
npm create cabloy
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
The generated project
|
|
27
|
+
The generated project includes `repo-agent-governance/` plus committed adapters for Claude Code, Codex, and Cursor. This path creates a Cabloy Basic project baseline. Open it in a supported coding agent and start with the project-specific guidance; regenerate adapters from the canonical governance source rather than editing generated files directly.
|
|
28
28
|
|
|
29
29
|
`npm create cabloy` automatically runs `npm run init` after creating the project. If you later need to reinstall the project's frontend and backend dependencies, you can run `npm run init` directly.
|
|
30
30
|
|
package/repo-docs/index.md
CHANGED
|
@@ -7,11 +7,12 @@ This monorepo is organized around a small set of stable top-level areas.
|
|
|
7
7
|
- `package.json` — shared scripts and release entrypoints
|
|
8
8
|
- `lerna.json` — package topology
|
|
9
9
|
- `repo-docs-internal/` — edition-local maintainer notes and ADRs
|
|
10
|
-
-
|
|
10
|
+
- `repo-agent-governance/` — authored portable agent rules, root skill bundles, adapter definitions, and deterministic tools
|
|
11
|
+
- `CLAUDE.md`, `AGENTS.md`, `.claude/`, `.agents/`, `.cursor/` — generated platform adapters plus platform-specific runtime integration
|
|
11
12
|
- `repo-docs/` — unified public docs
|
|
12
13
|
- `repo-specs/` — suite-local product, technical, delivery, ATP, progress, observed-evidence, and ADR authority
|
|
13
14
|
|
|
14
|
-
`repo-specs/` is distinct from `repo-docs/`, which explains reusable public guidance,
|
|
15
|
+
`repo-specs/` is distinct from `repo-docs/`, which explains reusable public guidance, `repo-agent-governance/`, which owns portable executable workflow behavior and adapter generation, and `repo-docs-internal/`, which preserves supporting maintainer rationale. For the public planning workflow, see [Generate a Cabloy Suite Specification](/ai/playbook-spec-generation).
|
|
15
16
|
|
|
16
17
|
## Backend side
|
|
17
18
|
|
|
@@ -60,7 +60,7 @@ npm run spec:charts -- <suite>
|
|
|
60
60
|
npm run spec:charts:check -- <suite>
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
`spec:charts` refreshes the generated Gantt and burndown SVG views for a chart-compatible `repo-specs/<suite>/` record. `spec:charts:check` validates the supported input contract and detects stale generated views; `test:spec-charts` runs the chart-tool test suite.
|
|
63
|
+
`spec:charts` refreshes the generated Gantt and burndown SVG views for a chart-compatible `repo-specs/<suite>/` record. `spec:charts:check` validates the supported input contract and detects stale generated views; `test:spec-charts` runs the chart-tool test suite. The deterministic implementation lives in `repo-agent-governance/tools/spec-charts/`, not inside a provider-specific skill discovery directory.
|
|
64
64
|
|
|
65
65
|
### Chart input contract
|
|
66
66
|
|
|
@@ -75,6 +75,21 @@ A legacy suite with a different WBS or progress-table layout is not chart-compat
|
|
|
75
75
|
|
|
76
76
|
These commands do not create planning authority, implement a WBS task, execute an ATP, produce acceptance evidence, or replace traceability/status review. Confirm the active root `package.json` and script input expectations before assuming equivalent behavior in Cabloy Start or another repository.
|
|
77
77
|
|
|
78
|
+
## Agent-governance maintenance
|
|
79
|
+
|
|
80
|
+
Use these Cabloy Basic maintenance commands when changing shared agent rules, root skill bundles, or adapter tooling:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npm run agent:governance:render
|
|
84
|
+
npm run agent:governance:check
|
|
85
|
+
npm run agent:governance:adopt
|
|
86
|
+
npm run agent:governance:pack-check
|
|
87
|
+
npm run test:agent-governance
|
|
88
|
+
npm run contract:gate -- --file <source-path> --format json
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The renderer updates committed Claude Code, Codex, and Cursor adapters from `repo-agent-governance/`. The checker is read-only. Adoption preserves locally modified or unowned adapter files as conflicts rather than overwriting them. The contract gate is advisory and does not run builds automatically; use the active edition's verified contract-loop workflow for completion evidence.
|
|
92
|
+
|
|
78
93
|
## Cabloy Start entrypoints
|
|
79
94
|
|
|
80
95
|
Cabloy Start exposes the equivalent Start repository surface:
|
|
@@ -104,7 +119,7 @@ Cabloy Start does not expose Basic Commerce or root documentation wrappers.
|
|
|
104
119
|
|
|
105
120
|
## Upgrade
|
|
106
121
|
|
|
107
|
-
Run `npm run upgrade:dry-run` before `npm run upgrade` to inspect framework files and root manifest entries that an upgrade would synchronize.
|
|
122
|
+
Run `npm run upgrade:dry-run` before `npm run upgrade` to inspect framework files and root manifest entries that an upgrade would synchronize. The upgrader replaces the framework-owned `repo-agent-governance/` source, reconciles only its named package scripts, and uses ownership-aware adapter adoption. It preserves locally modified or legacy adapter outputs as conflicts for explicit review instead of blindly overwriting root Claude, Codex, or Cursor files.
|
|
108
123
|
|
|
109
124
|
### Cabloy Basic public projects
|
|
110
125
|
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { cpSync, existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, resolve } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const ROOT_DIR = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
7
|
+
const UPGRADE_SOURCE_DIR = resolve(ROOT_DIR, 'node_modules/.cabloy-upgrade');
|
|
8
|
+
const GOVERNANCE_SCRIPT_NAMES = [
|
|
9
|
+
'test:spec-charts',
|
|
10
|
+
'spec:charts',
|
|
11
|
+
'spec:charts:check',
|
|
12
|
+
'agent:governance:render',
|
|
13
|
+
'agent:governance:check',
|
|
14
|
+
'agent:governance:adopt',
|
|
15
|
+
'agent:governance:pack-check',
|
|
16
|
+
'test:agent-governance',
|
|
17
|
+
'contract:gate',
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
function reconcileGovernancePackageJson(sourceRoot) {
|
|
21
|
+
const sourcePackagePath = resolve(sourceRoot, 'package.json');
|
|
22
|
+
if (!existsSync(sourcePackagePath)) return;
|
|
23
|
+
const projectPackagePath = resolve(ROOT_DIR, 'package.json');
|
|
24
|
+
const sourcePackage = JSON.parse(readFileSync(sourcePackagePath, 'utf-8'));
|
|
25
|
+
const projectPackage = JSON.parse(readFileSync(projectPackagePath, 'utf-8'));
|
|
26
|
+
let changed = false;
|
|
27
|
+
for (const name of GOVERNANCE_SCRIPT_NAMES) {
|
|
28
|
+
const command = sourcePackage.scripts?.[name];
|
|
29
|
+
if (!command) {
|
|
30
|
+
throw new Error(`Expected governance script in ${sourcePackagePath}: ${name}`);
|
|
31
|
+
}
|
|
32
|
+
if (projectPackage.scripts?.[name] === command) continue;
|
|
33
|
+
projectPackage.scripts ??= {};
|
|
34
|
+
projectPackage.scripts[name] = command;
|
|
35
|
+
changed = true;
|
|
36
|
+
}
|
|
37
|
+
if (changed) {
|
|
38
|
+
writeFileSync(projectPackagePath, `${JSON.stringify(projectPackage, null, 2)}\n`);
|
|
39
|
+
// eslint-disable-next-line no-console
|
|
40
|
+
console.log('[init] Reconciled agent-governance package scripts');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function adoptAgentGovernance() {
|
|
45
|
+
const executable = resolve(ROOT_DIR, 'repo-agent-governance/scripts/governance.mjs');
|
|
46
|
+
if (!existsSync(executable)) return;
|
|
47
|
+
try {
|
|
48
|
+
execFileSync(process.execPath, [executable, 'adopt', '--apply'], {
|
|
49
|
+
cwd: ROOT_DIR,
|
|
50
|
+
env: {
|
|
51
|
+
...process.env,
|
|
52
|
+
CABLOY_GOVERNANCE_ROOT: ROOT_DIR,
|
|
53
|
+
},
|
|
54
|
+
stdio: 'inherit',
|
|
55
|
+
});
|
|
56
|
+
} catch (error) {
|
|
57
|
+
if (error.status !== 2) throw error;
|
|
58
|
+
// eslint-disable-next-line no-console
|
|
59
|
+
console.log(
|
|
60
|
+
'[init] Agent-governance adoption preserved locally modified or legacy adapter outputs. Review the reported conflicts before explicitly forcing an individual managed target.',
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function bootstrapAgentGovernance() {
|
|
66
|
+
const sourceDir = resolve(UPGRADE_SOURCE_DIR, 'repo-agent-governance');
|
|
67
|
+
const targetDir = resolve(ROOT_DIR, 'repo-agent-governance');
|
|
68
|
+
if (existsSync(sourceDir)) {
|
|
69
|
+
// A pre-governance upgrader has already loaded its own upgrade.ts before it overwrites
|
|
70
|
+
// scripts/. Replace the canonical source here, before the current initializer adopts
|
|
71
|
+
// individual adapter outputs.
|
|
72
|
+
rmSync(targetDir, { recursive: true, force: true });
|
|
73
|
+
cpSync(sourceDir, targetDir, { recursive: true });
|
|
74
|
+
reconcileGovernancePackageJson(UPGRADE_SOURCE_DIR);
|
|
75
|
+
}
|
|
76
|
+
// The npm package deliberately excludes generated adapter outputs for the migration
|
|
77
|
+
// release. This also covers a fresh project, where no staged upgrade source exists.
|
|
78
|
+
adoptAgentGovernance();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
bootstrapAgentGovernance();
|
package/scripts/init.ts
CHANGED
package/scripts/release.ts
CHANGED
|
@@ -107,6 +107,19 @@ function readPackageJson(): Record<string, any> {
|
|
|
107
107
|
return readJson(PACKAGE_JSON_PATH);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
function runGovernancePreflight(dryRun?: boolean): void {
|
|
111
|
+
const commands = [
|
|
112
|
+
'npm run test:agent-governance',
|
|
113
|
+
'npm run agent:governance:check',
|
|
114
|
+
'npm run agent:governance:pack-check',
|
|
115
|
+
];
|
|
116
|
+
// eslint-disable-next-line
|
|
117
|
+
console.log('\n🔎 Validating agent-governance assets...');
|
|
118
|
+
for (const command of commands) {
|
|
119
|
+
execInherited(command, dryRun);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
110
123
|
function assertPublicBasicReleaseSurface(): void {
|
|
111
124
|
const edition = resolveEdition();
|
|
112
125
|
if (edition !== 'basic') {
|
|
@@ -949,6 +962,8 @@ async function release(options: ReleaseOptions): Promise<void> {
|
|
|
949
962
|
process.exit(1);
|
|
950
963
|
}
|
|
951
964
|
|
|
965
|
+
runGovernancePreflight(options.dryRun);
|
|
966
|
+
|
|
952
967
|
// Determine the version to use
|
|
953
968
|
let version: string;
|
|
954
969
|
|
package/scripts/upgrade.ts
CHANGED
|
@@ -30,6 +30,7 @@ const OVERWRITE_DIRS: string[] = [
|
|
|
30
30
|
'.husky',
|
|
31
31
|
'repo-docs',
|
|
32
32
|
'repo-observability',
|
|
33
|
+
'repo-agent-governance',
|
|
33
34
|
// vona
|
|
34
35
|
'vona/packages-vona',
|
|
35
36
|
'vona/packages-cli',
|
|
@@ -72,10 +73,6 @@ const FRAMEWORK_E2E_SCRIPT_NAMES_CABLOY_BASIC: string[] = ['test:e2e', 'test:e2e
|
|
|
72
73
|
const FRAMEWORK_E2E_DEV_DEPENDENCY_CABLOY_BASIC = '@playwright/test';
|
|
73
74
|
|
|
74
75
|
const MERGE_DIRS: string[] = [
|
|
75
|
-
// Claude project assets
|
|
76
|
-
'.claude/commands',
|
|
77
|
-
'.claude/hooks',
|
|
78
|
-
'.claude/skills',
|
|
79
76
|
// Vona Claude project assets
|
|
80
77
|
'vona/.claude/commands',
|
|
81
78
|
'vona/.claude/skills',
|
|
@@ -91,8 +88,6 @@ const BLACKLIST_DIRS: string[] = [
|
|
|
91
88
|
|
|
92
89
|
const WHITELIST_FILES: string[] = [
|
|
93
90
|
// root
|
|
94
|
-
'CLAUDE.md',
|
|
95
|
-
'.claude/settings.json',
|
|
96
91
|
'tsconfig.json',
|
|
97
92
|
'tsconfig.base.json',
|
|
98
93
|
'tsconfig.base.esm.json',
|
|
@@ -280,6 +275,64 @@ function mergeFrameworkE2eAssets(dryRun?: boolean): void {
|
|
|
280
275
|
}
|
|
281
276
|
}
|
|
282
277
|
|
|
278
|
+
function reconcileGovernancePackageJson(dryRun?: boolean): void {
|
|
279
|
+
const projectPackagePath = resolve(ROOT_DIR, 'package.json');
|
|
280
|
+
const sourcePackagePath = resolve(TEMP_DIR, 'package.json');
|
|
281
|
+
const projectPackage = readPackageJson(projectPackagePath);
|
|
282
|
+
const sourcePackage = readPackageJson(sourcePackagePath);
|
|
283
|
+
const baselineScripts = ['test:spec-charts', 'spec:charts', 'spec:charts:check'];
|
|
284
|
+
const governanceScripts = [
|
|
285
|
+
'agent:governance:render',
|
|
286
|
+
'agent:governance:check',
|
|
287
|
+
'agent:governance:adopt',
|
|
288
|
+
'agent:governance:pack-check',
|
|
289
|
+
'test:agent-governance',
|
|
290
|
+
'contract:gate',
|
|
291
|
+
];
|
|
292
|
+
const managedScripts = [...baselineScripts, ...governanceScripts];
|
|
293
|
+
let changed = false;
|
|
294
|
+
for (const name of managedScripts) {
|
|
295
|
+
const sourceValue = sourcePackage.scripts?.[name];
|
|
296
|
+
if (!sourceValue) {
|
|
297
|
+
if (
|
|
298
|
+
governanceScripts.includes(name) &&
|
|
299
|
+
!existsSync(resolve(TEMP_DIR, 'repo-agent-governance'))
|
|
300
|
+
) {
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
throw new Error(`Expected agent-governance script in package.json: ${name}`);
|
|
304
|
+
}
|
|
305
|
+
if (projectPackage.scripts?.[name] === sourceValue) continue;
|
|
306
|
+
changed = true;
|
|
307
|
+
if (dryRun) {
|
|
308
|
+
log(` [dry-run] Set package.json scripts.${name}`);
|
|
309
|
+
} else {
|
|
310
|
+
projectPackage.scripts ??= {};
|
|
311
|
+
projectPackage.scripts[name] = sourceValue;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
if (changed && !dryRun) {
|
|
315
|
+
writeFileSync(projectPackagePath, `${JSON.stringify(projectPackage, null, 2)}\n`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function reconcileGovernanceAssets(dryRun?: boolean): void {
|
|
320
|
+
const command = 'node repo-agent-governance/scripts/governance.mjs adopt --apply';
|
|
321
|
+
if (dryRun) {
|
|
322
|
+
log(` [dry-run] Run non-destructive governance adoption: ${command}`);
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
try {
|
|
326
|
+
execSync(command, { cwd: ROOT_DIR, stdio: 'inherit' });
|
|
327
|
+
} catch (error) {
|
|
328
|
+
const status = (error as { status?: number }).status;
|
|
329
|
+
if (status !== 2) throw error;
|
|
330
|
+
log(
|
|
331
|
+
' Agent-governance adoption preserved locally modified or legacy adapter outputs. Review the reported conflicts before explicitly forcing an individual managed target.',
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
283
336
|
function reconcileFrameworkE2ePackageJson(dryRun?: boolean): void {
|
|
284
337
|
if (!isCabloyBasic()) return;
|
|
285
338
|
|
|
@@ -545,7 +598,13 @@ async function main(): Promise<void> {
|
|
|
545
598
|
selectiveOverwrite(dryRun);
|
|
546
599
|
log('');
|
|
547
600
|
|
|
548
|
-
// 4. Reconcile
|
|
601
|
+
// 4. Reconcile agent-governance manifest entries and managed adapters
|
|
602
|
+
log('Reconciling agent-governance package entries and managed adapters...');
|
|
603
|
+
reconcileGovernancePackageJson(dryRun);
|
|
604
|
+
reconcileGovernanceAssets(dryRun);
|
|
605
|
+
log('');
|
|
606
|
+
|
|
607
|
+
// 5. Reconcile Cabloy Basic framework E2E manifest entries
|
|
549
608
|
if (isCabloyBasic()) {
|
|
550
609
|
log('Reconciling framework-owned E2E package entries...');
|
|
551
610
|
reconcileFrameworkE2ePackageJson(dryRun);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zova",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.167",
|
|
4
4
|
"gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
|
|
5
5
|
"description": "A vue3 framework with ioc",
|
|
6
6
|
"keywords": [
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"zova-core": "^5.1.92",
|
|
49
|
-
"zova-suite-a-zova": "^5.1.
|
|
49
|
+
"zova-suite-a-zova": "^5.1.166"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"clean-package": "^2.2.0",
|
package/zova/pnpm-lock.yaml
CHANGED
|
@@ -876,7 +876,7 @@ importers:
|
|
|
876
876
|
specifier: ^5.1.92
|
|
877
877
|
version: link:../zova-core
|
|
878
878
|
zova-suite-a-zova:
|
|
879
|
-
specifier: ^5.1.
|
|
879
|
+
specifier: ^5.1.166
|
|
880
880
|
version: link:../../src/suite-vendor/a-zova
|
|
881
881
|
devDependencies:
|
|
882
882
|
clean-package:
|
|
@@ -1109,7 +1109,7 @@ importers:
|
|
|
1109
1109
|
specifier: ^5.1.37
|
|
1110
1110
|
version: link:modules/a-model
|
|
1111
1111
|
zova-module-a-openapi:
|
|
1112
|
-
specifier: ^5.1.
|
|
1112
|
+
specifier: ^5.1.55
|
|
1113
1113
|
version: link:modules/a-openapi
|
|
1114
1114
|
zova-module-a-router:
|
|
1115
1115
|
specifier: ^5.1.41
|
|
@@ -1133,7 +1133,7 @@ importers:
|
|
|
1133
1133
|
specifier: ^5.1.35
|
|
1134
1134
|
version: link:modules/a-style
|
|
1135
1135
|
zova-module-a-table:
|
|
1136
|
-
specifier: ^5.1.
|
|
1136
|
+
specifier: ^5.1.44
|
|
1137
1137
|
version: link:modules/a-table
|
|
1138
1138
|
zova-module-a-zod:
|
|
1139
1139
|
specifier: ^5.1.37
|
|
@@ -10,12 +10,7 @@ import type {
|
|
|
10
10
|
import { combineQueries, isNil } from '@cabloy/utils';
|
|
11
11
|
import { SchemaObject } from 'openapi3-ts/oas31';
|
|
12
12
|
import { $QueryEnsureFresh, $QueryGetFresh, BeanModelBase, Model } from 'zova-module-a-model';
|
|
13
|
-
import {
|
|
14
|
-
IPermissionHintGeneral,
|
|
15
|
-
IResourceFormActionRowNameRecord,
|
|
16
|
-
IResourceTableActionNameRecord,
|
|
17
|
-
TypeOpenapiPermissions,
|
|
18
|
-
} from 'zova-module-a-openapi';
|
|
13
|
+
import { IPermissionHintGeneral, TypeOpenapiPermissions } from 'zova-module-a-openapi';
|
|
19
14
|
import { ApiApiHomeUserPassportloginOauthPath, OpenApiBaseURL } from 'zova-module-home-api';
|
|
20
15
|
import { isRoleSiteAdmitted } from 'zova-module-home-base';
|
|
21
16
|
|
|
@@ -272,7 +267,7 @@ export class ModelPassport extends BeanModelBase {
|
|
|
272
267
|
|
|
273
268
|
public checkPermission(
|
|
274
269
|
permissions: TypeOpenapiPermissions | undefined,
|
|
275
|
-
actionName?:
|
|
270
|
+
actionName?: string,
|
|
276
271
|
permissionHint?: IPermissionHintGeneral,
|
|
277
272
|
currentData?: Record<string, unknown> | readonly Record<string, unknown>[],
|
|
278
273
|
): boolean {
|
package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/tableCell.actionOperationsRow.tsx
CHANGED
|
@@ -14,7 +14,8 @@ import { VNode } from 'vue';
|
|
|
14
14
|
import { BeanBase } from 'zova';
|
|
15
15
|
import { TableCell } from 'zova-module-a-table';
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import { filterDetailsRowActions } from '../lib/detailsPermissions.js';
|
|
18
|
+
import { checkFormScene } from '../lib/utils.js';
|
|
18
19
|
|
|
19
20
|
declare module 'zova-module-a-openapi' {
|
|
20
21
|
export interface IResourceDetailsActionRowRecord {
|
|
@@ -37,16 +38,16 @@ export class TableCellActionOperationsRow extends BeanBase implements ITableCell
|
|
|
37
38
|
const { $celScope, $$table } = renderContext;
|
|
38
39
|
const actions = options.actions;
|
|
39
40
|
if (!actions || actions.length === 0) return false;
|
|
40
|
-
|
|
41
|
+
const $$details = $celScope.$$details!;
|
|
42
|
+
const actionsVisible = actions.filter(action => {
|
|
43
|
+
return checkFormScene($$details.formScene, action.options?.permission);
|
|
44
|
+
});
|
|
41
45
|
const renders: TypeTableCellRenderComponent[] = [];
|
|
42
|
-
for (const action of
|
|
46
|
+
for (const action of actionsVisible) {
|
|
43
47
|
const actionName = action.name;
|
|
44
48
|
const actionRender = action.render;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (!actionRender) throw new Error(`should specify action render: ${actionName}`);
|
|
48
|
-
renders.push(actionRender);
|
|
49
|
-
}
|
|
49
|
+
if (!actionRender) throw new Error(`should specify action render: ${actionName}`);
|
|
50
|
+
renders.push(actionRender);
|
|
50
51
|
}
|
|
51
52
|
await $$table.cellRenderPrepare(renders);
|
|
52
53
|
return renders.length > 0;
|
|
@@ -60,13 +61,18 @@ export class TableCellActionOperationsRow extends BeanBase implements ITableCell
|
|
|
60
61
|
const { $celScope, $$table } = renderContext;
|
|
61
62
|
const actions = options.actions;
|
|
62
63
|
if (!actions || actions.length === 0) return;
|
|
64
|
+
const $$details = $celScope.$$details!;
|
|
65
|
+
const actionsAllowed = filterDetailsRowActions(
|
|
66
|
+
$$details.formScene,
|
|
67
|
+
$$details.checkPermission.bind($$details),
|
|
68
|
+
actions,
|
|
69
|
+
);
|
|
63
70
|
const domActions: VNode[] = [];
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
const options2 = Object.assign({ key: index }, action.options);
|
|
68
|
-
domActions.push($$table.cellRender(action.render!, options2, renderContext));
|
|
71
|
+
actionsAllowed.forEach((action, index) => {
|
|
72
|
+
const actionOptions = Object.assign({ key: index }, action.options);
|
|
73
|
+
domActions.push($$table.cellRender(action.render!, actionOptions, renderContext));
|
|
69
74
|
});
|
|
75
|
+
if (domActions.length === 0) return;
|
|
70
76
|
return <div class={options.class}>{domActions}</div>;
|
|
71
77
|
}
|
|
72
78
|
}
|
package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/blockDetails/controller.tsx
CHANGED
|
@@ -13,6 +13,8 @@ import {
|
|
|
13
13
|
} from 'zova-module-a-openapi';
|
|
14
14
|
import { BeanControllerTableBase } from 'zova-module-a-table';
|
|
15
15
|
|
|
16
|
+
import type { TypeDetailsCheckPermission } from '../../types/details.js';
|
|
17
|
+
|
|
16
18
|
declare module 'zova-module-a-openapi' {
|
|
17
19
|
export interface IResourceBlockRecord {
|
|
18
20
|
'basic-details:blockDetails'?: ControllerBlockDetailsProps;
|
|
@@ -26,6 +28,7 @@ export interface ControllerBlockDetailsProps<
|
|
|
26
28
|
formMeta?: IFormMeta;
|
|
27
29
|
schemaRow?: ISchemaObjectExtensionField;
|
|
28
30
|
schemaForm?: ISchemaObjectExtensionField;
|
|
31
|
+
checkPermission?: TypeDetailsCheckPermission;
|
|
29
32
|
getDetailItems?: () => TData[] | undefined;
|
|
30
33
|
setDetailItems?: (detailItems: TData[]) => void;
|
|
31
34
|
}
|
|
@@ -70,6 +73,14 @@ export class ControllerBlockDetails<TData extends {} = {}> extends BeanControlle
|
|
|
70
73
|
return this.$props.schemaForm!;
|
|
71
74
|
}
|
|
72
75
|
|
|
76
|
+
checkPermission(...args: Parameters<TypeDetailsCheckPermission>) {
|
|
77
|
+
const checkPermission = this.$props.checkPermission;
|
|
78
|
+
if (!checkPermission) {
|
|
79
|
+
throw new Error('should provide enclosing Resource permission checker for details');
|
|
80
|
+
}
|
|
81
|
+
return checkPermission(...args);
|
|
82
|
+
}
|
|
83
|
+
|
|
73
84
|
public async setTableRef(tableRef: BeanControllerTableBase<TData> | undefined) {
|
|
74
85
|
this.tableRef = tableRef;
|
|
75
86
|
}
|
|
@@ -9,7 +9,7 @@ import { VNode } from 'vue';
|
|
|
9
9
|
import { BeanControllerBase, Use } from 'zova';
|
|
10
10
|
import { Controller } from 'zova-module-a-bean';
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { filterDetailsBulkActions } from '../../lib/detailsPermissions.js';
|
|
13
13
|
|
|
14
14
|
declare module 'zova-module-a-openapi' {
|
|
15
15
|
export interface IResourceBlockRecord {
|
|
@@ -46,9 +46,12 @@ export class ControllerBlockToolbarBulk extends BeanControllerBase {
|
|
|
46
46
|
const actions = this.$props.actions;
|
|
47
47
|
if (!actions || actions.length === 0) return;
|
|
48
48
|
const domActions: VNode[] = [];
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const allowedActions = filterDetailsBulkActions(
|
|
50
|
+
$$details.formScene,
|
|
51
|
+
$$details.checkPermission.bind($$details),
|
|
52
|
+
actions,
|
|
53
|
+
);
|
|
54
|
+
allowedActions.forEach((action, index) => {
|
|
52
55
|
const options = Object.assign({ key: index }, action.options);
|
|
53
56
|
const domAction = $jsx.render(action.render!, options, $celScope, this.$$renderContext);
|
|
54
57
|
if (!domAction) return;
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
IResourceFormFieldOptionsBase,
|
|
9
9
|
ISchemaObjectExtensionField,
|
|
10
10
|
TypeFormScene,
|
|
11
|
+
TypeOpenapiPermissions,
|
|
11
12
|
} from 'zova-module-a-openapi';
|
|
12
13
|
|
|
13
14
|
import { VNode } from 'vue';
|
|
@@ -16,6 +17,10 @@ import { ZovaJsx } from 'zova-jsx';
|
|
|
16
17
|
import { Controller } from 'zova-module-a-bean';
|
|
17
18
|
import { formMetaFromFormScene, ZFormField } from 'zova-module-a-form';
|
|
18
19
|
|
|
20
|
+
import type { TypeDetailsCheckPermission } from '../../types/details.js';
|
|
21
|
+
|
|
22
|
+
import { createDetailsPermissionChecker } from '../../lib/detailsPermissions.js';
|
|
23
|
+
|
|
19
24
|
declare module 'zova-module-a-openapi' {
|
|
20
25
|
export interface IResourceFormFieldRecord {
|
|
21
26
|
'basic-details:formFieldDetails'?: IResourceFormFieldDetailsOptions;
|
|
@@ -76,6 +81,14 @@ export class ControllerFormFieldDetails extends BeanControllerBase {
|
|
|
76
81
|
// blocks
|
|
77
82
|
const blocks = schemaRow?.rest?.blocks;
|
|
78
83
|
if (!blocks || blocks.length === 0) return;
|
|
84
|
+
const checkPermission: TypeDetailsCheckPermission = createDetailsPermissionChecker(
|
|
85
|
+
() =>
|
|
86
|
+
(formFieldRenderContext.celScope as { permissions?: TypeOpenapiPermissions }).permissions,
|
|
87
|
+
() => $$formField.$$form.formState.values as Record<string, unknown>,
|
|
88
|
+
(permissions, actionName, permissionHint, currentData) => {
|
|
89
|
+
return this.$passport.checkPermission(permissions, actionName, permissionHint, currentData);
|
|
90
|
+
},
|
|
91
|
+
);
|
|
79
92
|
const domBlocks: VNode[] = [];
|
|
80
93
|
blocks.forEach((block, index) => {
|
|
81
94
|
const options = deepExtend(
|
|
@@ -92,6 +105,7 @@ export class ControllerFormFieldDetails extends BeanControllerBase {
|
|
|
92
105
|
},
|
|
93
106
|
},
|
|
94
107
|
block.options,
|
|
108
|
+
{ checkPermission },
|
|
95
109
|
);
|
|
96
110
|
const domBlock = this.jsxZova.render(block.render!, options);
|
|
97
111
|
if (!domBlock) return;
|