@thinkingai/ae-cli 6.0.52 → 6.0.53
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 +7 -1
- package/README.zh.md +7 -1
- package/dist/{auth-XZNXFRJS.js → auth-LHM7NQPR.js} +167 -7
- package/dist/{capability-RJZ4KRGP.js → capability-F2RIR5DS.js} +11 -6
- package/dist/{chunk-57RRFUEZ.js → chunk-5XRQ3CZR.js} +4 -4
- package/dist/{chunk-L2QUIZTS.js → chunk-647BRKZK.js} +3 -3
- package/dist/{chunk-EQ255HKO.js → chunk-7WZACOAI.js} +2 -2
- package/dist/{chunk-DX5CDO34.js → chunk-BW7JUDEI.js} +84 -19
- package/dist/{chunk-7XGFSUOM.js → chunk-DU72X2IO.js} +271 -76
- package/dist/{chunk-V2NUHPXF.js → chunk-GK7WDY7E.js} +1 -1
- package/dist/{chunk-7FTTULED.js → chunk-IG3DYEIR.js} +4 -1
- package/dist/{chunk-HBGADCKA.js → chunk-KJDOTPYU.js} +3 -3
- package/dist/{chunk-4NRCTUZJ.js → chunk-KS4DE3MX.js} +4 -4
- package/dist/{chunk-JOCDD4ON.js → chunk-N4BLPJC7.js} +1 -1
- package/dist/{chunk-WEPZ5M3Z.js → chunk-PGCIKZRE.js} +7 -4
- package/dist/{chunk-HFGZGYCG.js → chunk-QYXDJOLA.js} +252 -6
- package/dist/{chunk-DVMLWQD4.js → chunk-SO5LKIWP.js} +2 -2
- package/dist/{chunk-MAPZ7VB6.js → chunk-YVGXGTD6.js} +13 -0
- package/dist/{community-report-client-CU22W53K.js → community-report-client-6VJDDMJJ.js} +1 -1
- package/dist/{config-XO3LI3SA.js → config-XQWOPDHN.js} +25 -6
- package/dist/{context-IFJI3LIT.js → context-M3HDGEIR.js} +4 -4
- package/dist/{data-integration-HNGUKFIC.js → data-integration-XBTCGXQT.js} +6 -6
- package/dist/index.js +77 -40
- package/dist/{local-data-upload-client-GTRIT64F.js → local-data-upload-client-3P7NIVQ4.js} +1 -1
- package/dist/{memory-QGPSNCQS.js → memory-6APEB2JB.js} +4 -4
- package/dist/{metadata-JAQW7KGZ.js → metadata-V5ZDTKWZ.js} +7 -7
- package/dist/{model-RNPQXIBI.js → model-ZS7HVGKN.js} +4 -4
- package/dist/{personal-semantic-preference-QCZ2IZTK.js → personal-semantic-preference-2XANU3F6.js} +8 -6
- package/dist/{project-semantic-64JURXKF.js → project-semantic-LP3LY7QP.js} +7 -7
- package/dist/{sync-O45NXEQY.js → sync-EQLSTUS7.js} +7 -7
- package/dist/{te-agent-K5MSPNHJ.js → te-agent-Z3HCTKR7.js} +348 -55
- package/dist/{te-analysis-KQKCAI5H.js → te-analysis-3EVYQ3IO.js} +803 -57
- package/dist/{te-community-4OYU3BDA.js → te-community-Z7JACGF3.js} +3 -3
- package/dist/{te-dataops-NFIPB6FX.js → te-dataops-F7GQOIS6.js} +644 -276
- package/dist/{te-engage-HSVSRW22.js → te-engage-LFBU6WWH.js} +6 -6
- package/dist/{te-kb-3TS73NO6.js → te-kb-QJLJEX5K.js} +323 -181
- package/dist/{te-system-STMHLS5J.js → te-system-IXC43QHZ.js} +6 -6
- package/dist/{te-team-3I5AOX3N.js → te-team-BIZIKIHZ.js} +6 -6
- package/dist/{update-RZXLPCRH.js → update-W2SGQNKT.js} +4 -4
- package/package.json +11 -4
- package/skills/ae-agent/SKILL.md +9 -4
- package/skills/ae-agent/references/notification.md +40 -0
- package/skills/ae-analysis/SKILL.md +64 -12
- package/skills/ae-analysis/references/agent_review_submit_to_page.md +2 -0
- package/skills/ae-analysis/references/ai_models/event.md +6 -1
- package/skills/ae-analysis/references/ai_models/funnel.md +7 -1
- package/skills/ae-analysis/references/ai_models/heat_map.md +23 -0
- package/skills/ae-analysis/references/ai_models/interval.md +24 -0
- package/skills/ae-analysis/references/ai_models/path.md +20 -0
- package/skills/ae-analysis/references/ai_models/prop_analysis.md +2 -0
- package/skills/ae-analysis/references/ai_models/rank_list.md +30 -0
- package/skills/ae-analysis/references/ai_models/retention.md +45 -1
- package/skills/ae-analysis/references/ai_models/revenue.md +20 -2
- package/skills/ae-analysis/references/ai_models/tag.md +2 -0
- package/skills/ae-analysis/references/ai_models.md +69 -0
- package/skills/ae-analysis/references/analysis_data_retrieval.md +4 -0
- package/skills/ae-analysis/references/asset_batch_info_export.md +10 -0
- package/skills/ae-analysis/references/asset_batch_sql_export.md +13 -1
- package/skills/ae-analysis/references/asset_export.md +12 -1
- package/skills/ae-analysis/references/asset_list.md +1 -0
- package/skills/ae-analysis/references/asset_search.md +11 -5
- package/skills/ae-analysis/references/bi_panel_list.md +1 -1
- package/skills/ae-analysis/references/catalog_list.md +1 -1
- package/skills/ae-analysis/references/collaboration.md +48 -0
- package/skills/ae-analysis/references/command_index.md +16 -15
- package/skills/ae-analysis/references/dashboard_list.md +4 -4
- package/skills/ae-analysis/references/dashboard_report_data_export.md +2 -0
- package/skills/ae-analysis/references/event_export.md +3 -1
- package/skills/ae-analysis/references/governance_recommendation_auto_review.md +71 -0
- package/skills/ae-analysis/references/governance_recommendation_export.md +11 -0
- package/skills/ae-analysis/references/metadata_resolution.md +3 -3
- package/skills/ae-analysis/references/metric_export.md +3 -1
- package/skills/ae-analysis/references/metric_list.md +1 -1
- package/skills/ae-analysis/references/operation_record_export.md +10 -0
- package/skills/ae-analysis/references/personal_semantic_preference_add.md +2 -2
- package/skills/ae-analysis/references/personal_semantic_preference_get.md +6 -4
- package/skills/ae-analysis/references/personal_semantic_preference_list.md +5 -3
- package/skills/ae-analysis/references/project_semantic_knowledge_wiki.md +1 -1
- package/skills/ae-analysis/references/property_export.md +3 -1
- package/skills/ae-analysis/references/report_create.md +4 -0
- package/skills/ae-analysis/references/report_data_export.md +6 -0
- package/skills/ae-analysis/references/report_get.md +2 -0
- package/skills/ae-analysis/references/report_list.md +5 -5
- package/skills/ae-analysis/references/report_update.md +6 -0
- package/skills/ae-analysis/references/sql_table_columns.md +4 -4
- package/skills/ae-analysis/references/sql_table_list.md +5 -5
- package/skills/ae-analysis/references/user_cluster_models.md +8 -0
- package/skills/ae-analysis/references/user_tag_create.md +7 -1
- package/skills/ae-analysis/references/user_tag_get.md +1 -1
- package/skills/ae-analysis/references/user_tag_models.md +18 -2
- package/skills/ae-analysis/references/user_tag_refresh.md +1 -1
- package/skills/ae-analysis/references/user_tag_update.md +2 -2
- package/skills/ae-capability/SKILL.md +63 -1
- package/skills/ae-capability/references/collaboration.md +48 -0
- package/skills/ae-community/SKILL.md +5 -1
- package/skills/ae-community/references/collaboration.md +48 -0
- package/skills/ae-data-integration/SKILL.md +4 -0
- package/skills/ae-data-integration/references/collaboration.md +48 -0
- package/skills/ae-dataops/SKILL.md +54 -74
- package/skills/ae-dataops/references/collaboration.md +48 -0
- package/skills/ae-dataops/references/dataops-backfill.md +23 -18
- package/skills/ae-dataops/references/dataops-flow-create.md +74 -23
- package/skills/ae-dataops/references/dataops-flow-monitor.md +45 -13
- package/skills/ae-dataops/references/dataops-integration.md +57 -30
- package/skills/ae-dataops/references/dataops-query.md +21 -4
- package/skills/ae-dataops/references/dataops-table.md +143 -11
- package/skills/ae-engage/SKILL.md +21 -6
- package/skills/ae-engage/references/channel-mgmt.md +3 -3
- package/skills/ae-engage/references/collaboration.md +48 -0
- package/skills/ae-engage/references/scene-config-channel.md +4 -4
- package/skills/ae-generate-tracking-plan/SKILL.md +4 -0
- package/skills/ae-generate-tracking-plan/references/collaboration.md +48 -0
- package/skills/ae-kb/SKILL.md +9 -1
- package/skills/ae-kb/references/collaboration.md +48 -0
- package/skills/ae-kb/references/schema-import.md +30 -0
- package/skills/ae-kb-discovery/SKILL.md +7 -2
- package/skills/ae-kb-discovery/references/collaboration.md +48 -0
- package/skills/ae-metadata/SKILL.md +20 -12
- package/skills/ae-metadata/references/collaboration.md +48 -0
|
@@ -7,12 +7,12 @@ import {
|
|
|
7
7
|
waitForAnalysisRun,
|
|
8
8
|
withAsyncArtifactLifecycle,
|
|
9
9
|
withInterruptSignal
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-PGCIKZRE.js";
|
|
11
11
|
import {
|
|
12
12
|
createCapabilityCommand,
|
|
13
13
|
definitionIntentSnapshotFlag,
|
|
14
14
|
modelDefinitionIntentSnapshotFlag
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-647BRKZK.js";
|
|
16
16
|
import {
|
|
17
17
|
registerCapabilityGatewayRoute,
|
|
18
18
|
resolveGatewayDomain
|
|
@@ -26,19 +26,20 @@ import {
|
|
|
26
26
|
requestCapabilityGateway,
|
|
27
27
|
requestCapabilityGatewayWithEnvelope,
|
|
28
28
|
uploadInputFile,
|
|
29
|
-
validateCapability
|
|
30
|
-
|
|
29
|
+
validateCapability,
|
|
30
|
+
validateCapabilityWithEnvelope
|
|
31
|
+
} from "./chunk-QYXDJOLA.js";
|
|
31
32
|
import {
|
|
32
33
|
withOutputMetadata
|
|
33
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-BW7JUDEI.js";
|
|
34
35
|
import "./chunk-Y74WTIKJ.js";
|
|
35
36
|
import {
|
|
36
37
|
getCliToken
|
|
37
|
-
} from "./chunk-
|
|
38
|
-
import "./chunk-
|
|
38
|
+
} from "./chunk-DU72X2IO.js";
|
|
39
|
+
import "./chunk-IG3DYEIR.js";
|
|
39
40
|
import {
|
|
40
41
|
CliValidationError
|
|
41
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-YVGXGTD6.js";
|
|
42
43
|
|
|
43
44
|
// src/commands/te-analysis/capability-shared.ts
|
|
44
45
|
var ANALYSIS_GATEWAY_CLI_SERVICES = /* @__PURE__ */ new Set(["project", "system"]);
|
|
@@ -148,7 +149,7 @@ var sqlTableUsageFlag = {
|
|
|
148
149
|
name: "usage",
|
|
149
150
|
type: "string",
|
|
150
151
|
required: false,
|
|
151
|
-
desc: "Authorized table set: analysis (default) or
|
|
152
|
+
desc: "Authorized table set: analysis (default), tag_cluster for SQL tags/clusters, or sql_datatable for SQL-built data tables. Use the same usage for list and columns."
|
|
152
153
|
};
|
|
153
154
|
var reportListLimitFlag = {
|
|
154
155
|
name: "limit",
|
|
@@ -288,7 +289,7 @@ function certificationScopeInput(ctx) {
|
|
|
288
289
|
}
|
|
289
290
|
return value;
|
|
290
291
|
}
|
|
291
|
-
function dashboardReportDataInput(ctx) {
|
|
292
|
+
function dashboardReportDataInput(ctx, includeCache = true) {
|
|
292
293
|
return compactInput({
|
|
293
294
|
...projectInput(ctx),
|
|
294
295
|
dashboard_id: ctx.num("dashboard-id"),
|
|
@@ -299,7 +300,7 @@ function dashboardReportDataInput(ctx) {
|
|
|
299
300
|
cluster_query_scope: optionalString(ctx, "cluster-query-scope"),
|
|
300
301
|
slave_cluster_id: optionalString(ctx, "slave-cluster-id"),
|
|
301
302
|
zone_offset: optionalNumber(ctx, "zone-offset"),
|
|
302
|
-
use_cache: optionalBoolean(ctx, "use-cache"),
|
|
303
|
+
...includeCache ? { use_cache: optionalBoolean(ctx, "use-cache") } : {},
|
|
303
304
|
request_id: optionalString(ctx, "request-id"),
|
|
304
305
|
preview_rows: optionalNumber(ctx, "preview-rows"),
|
|
305
306
|
timeout_seconds: optionalNumber(ctx, "timeout-seconds"),
|
|
@@ -756,6 +757,7 @@ var metadataEventExport = createAnalysisMetaCapabilityCommand({
|
|
|
756
757
|
queriesFlag,
|
|
757
758
|
fieldsFlag,
|
|
758
759
|
{ name: "authenticated-only", type: "boolean", required: false, desc: "When true, export only authenticated events." },
|
|
760
|
+
certificationScopeFlag,
|
|
759
761
|
metadataExportOutputFlag
|
|
760
762
|
],
|
|
761
763
|
risk: "read",
|
|
@@ -764,7 +766,8 @@ var metadataEventExport = createAnalysisMetaCapabilityCommand({
|
|
|
764
766
|
...projectInput(ctx),
|
|
765
767
|
queries: optionalQueries(ctx),
|
|
766
768
|
fields: optionalJson(ctx, "fields"),
|
|
767
|
-
authenticated_only: optionalBoolean(ctx, "authenticated-only")
|
|
769
|
+
authenticated_only: optionalBoolean(ctx, "authenticated-only"),
|
|
770
|
+
certification_scope: certificationScopeInput(ctx)
|
|
768
771
|
}),
|
|
769
772
|
postProcess: metadataExportPostProcess("event", "events")
|
|
770
773
|
});
|
|
@@ -947,6 +950,7 @@ var metadataPropertyExport = createAnalysisMetaCapabilityCommand({
|
|
|
947
950
|
queriesFlag,
|
|
948
951
|
fieldsFlag,
|
|
949
952
|
{ name: "authenticated-only", type: "boolean", required: false, desc: "When true, export only authenticated properties." },
|
|
953
|
+
certificationScopeFlag,
|
|
950
954
|
metadataExportOutputFlag
|
|
951
955
|
],
|
|
952
956
|
risk: "read",
|
|
@@ -958,7 +962,8 @@ var metadataPropertyExport = createAnalysisMetaCapabilityCommand({
|
|
|
958
962
|
event_name: optionalString(ctx, "event-name"),
|
|
959
963
|
queries: optionalQueries(ctx),
|
|
960
964
|
fields: optionalJson(ctx, "fields"),
|
|
961
|
-
authenticated_only: optionalBoolean(ctx, "authenticated-only")
|
|
965
|
+
authenticated_only: optionalBoolean(ctx, "authenticated-only"),
|
|
966
|
+
certification_scope: certificationScopeInput(ctx)
|
|
962
967
|
}),
|
|
963
968
|
postProcess: metadataExportPostProcess("property", "properties")
|
|
964
969
|
});
|
|
@@ -1350,6 +1355,7 @@ var metadataMetricExport = createAnalysisMetaCapabilityCommand({
|
|
|
1350
1355
|
queriesFlag,
|
|
1351
1356
|
fieldsFlag,
|
|
1352
1357
|
{ name: "authenticated-only", type: "boolean", required: false, desc: "When true, export only authenticated metrics." },
|
|
1358
|
+
certificationScopeFlag,
|
|
1353
1359
|
metadataExportOutputFlag
|
|
1354
1360
|
],
|
|
1355
1361
|
risk: "read",
|
|
@@ -1359,7 +1365,8 @@ var metadataMetricExport = createAnalysisMetaCapabilityCommand({
|
|
|
1359
1365
|
ignore_authentication: optionalBoolean(ctx, "ignore-authentication"),
|
|
1360
1366
|
queries: optionalQueries(ctx),
|
|
1361
1367
|
fields: optionalJson(ctx, "fields"),
|
|
1362
|
-
authenticated_only: optionalBoolean(ctx, "authenticated-only")
|
|
1368
|
+
authenticated_only: optionalBoolean(ctx, "authenticated-only"),
|
|
1369
|
+
certification_scope: certificationScopeInput(ctx)
|
|
1363
1370
|
}),
|
|
1364
1371
|
postProcess: metadataExportPostProcess("metric", "metrics")
|
|
1365
1372
|
});
|
|
@@ -1500,13 +1507,13 @@ var ownTypesFlag = {
|
|
|
1500
1507
|
var requiredQueriesFlag = {
|
|
1501
1508
|
...queriesFlag,
|
|
1502
1509
|
required: true,
|
|
1503
|
-
desc: "Required JSON array of 1 to 20 keyword filters. For first-pass asset discovery, use one broad search without --asset-types
|
|
1510
|
+
desc: "Required JSON array of 1 to 20 keyword filters. For first-pass asset discovery, use one broad search without --asset-types and request a large page; when has_more is true and no strong candidate is present, continue with next_offset before narrowing or rewriting keywords."
|
|
1504
1511
|
};
|
|
1505
1512
|
var analysisAssetSearch = createAnalysisCapabilityCommand({
|
|
1506
1513
|
resource: "asset",
|
|
1507
1514
|
command: "search",
|
|
1508
1515
|
capabilityId: "analysis.asset.search",
|
|
1509
|
-
description: "Search
|
|
1516
|
+
description: "Search readable saved analysis assets by keyword, including shared read-only and editable dashboards and reports. Results are ranked before pagination by match quality, certification, recent heat/users, and governance impact. Omit --asset-types for first-pass discovery.",
|
|
1510
1517
|
flags: [
|
|
1511
1518
|
projectIdFlag,
|
|
1512
1519
|
requiredQueriesFlag,
|
|
@@ -1635,7 +1642,16 @@ var statusFlag = { name: "status", type: "json", required: false, desc: "Operati
|
|
|
1635
1642
|
var sortFieldFlag = { name: "sort-field", type: "string", required: false, desc: "Sort field." };
|
|
1636
1643
|
var sortOrderFlag = { name: "sort-order", type: "string", required: false, desc: "Sort order: asc or desc." };
|
|
1637
1644
|
var recordIdFlag = { name: "record-id", type: "number", required: false, desc: "Operation record ID." };
|
|
1645
|
+
var governanceExportFlags = (format) => [
|
|
1646
|
+
requestIdFlag,
|
|
1647
|
+
{ ...artifactFormatFlag, desc: `Artifact format: ${format}. This capability supports only ${format}.` },
|
|
1648
|
+
{ ...asyncTimeoutSecondsFlag, max: 7200, desc: "Async export runtime in seconds. Default: 3600, max: 7200." }
|
|
1649
|
+
];
|
|
1650
|
+
var governanceExportFields = ["request_id", "format", "timeout_seconds"];
|
|
1638
1651
|
var readers = {
|
|
1652
|
+
request_id: (ctx) => optionalString(ctx, "request-id"),
|
|
1653
|
+
format: (ctx) => optionalString(ctx, "artifact-format"),
|
|
1654
|
+
timeout_seconds: (ctx) => optionalNumber(ctx, "timeout-seconds"),
|
|
1639
1655
|
node_id: (ctx) => optionalString(ctx, "node-id"),
|
|
1640
1656
|
resource_id: (ctx) => optionalString(ctx, "resource-id"),
|
|
1641
1657
|
resource_type: (ctx) => optionalString(ctx, "resource-type"),
|
|
@@ -2238,6 +2254,715 @@ var metadataGovernanceRecommendationSubmit = createAnalysisMetaCapabilityCommand
|
|
|
2238
2254
|
})
|
|
2239
2255
|
});
|
|
2240
2256
|
|
|
2257
|
+
// src/commands/te-analysis/meta/governance-recommendation/auto-review.ts
|
|
2258
|
+
import { randomUUID } from "crypto";
|
|
2259
|
+
var windowDaysFlag3 = {
|
|
2260
|
+
name: "window-days",
|
|
2261
|
+
type: "number",
|
|
2262
|
+
required: false,
|
|
2263
|
+
min: 1,
|
|
2264
|
+
max: 365,
|
|
2265
|
+
desc: "Usage window in days for the recommendation batch. Default: 90."
|
|
2266
|
+
};
|
|
2267
|
+
var limitFlag4 = {
|
|
2268
|
+
name: "limit",
|
|
2269
|
+
type: "number",
|
|
2270
|
+
required: false,
|
|
2271
|
+
min: 1,
|
|
2272
|
+
max: 100,
|
|
2273
|
+
desc: "Maximum hot dashboard evidence packages selected before automatic asset review. Omit for CLI bounded expansion over top-20/top-50/top-100; pass explicitly for a fixed diagnostic scope."
|
|
2274
|
+
};
|
|
2275
|
+
var GOVERNANCE_RECOMMENDATION_AUTO_REVIEW_HELP = [
|
|
2276
|
+
"Automatic asset certification contract:",
|
|
2277
|
+
"- Use this command only when the user explicitly asks to automatically review or automatically certify recommended assets.",
|
|
2278
|
+
"- Do not call this command for a plain recommendation request.",
|
|
2279
|
+
"- Do not call this command when the user asks to submit recommendations to the review page.",
|
|
2280
|
+
"- The command first validates project config agent_auto_asset_certification_enabled and project_semantic_enable. If disabled, report the returned config error and stop before collecting recommendations.",
|
|
2281
|
+
"- When --limit is omitted, the CLI performs the same bounded expansion used by recurring page-review jobs: inspect top-20 pending material, then top-50/top-100 only when pending assets or pending dashboard branches are insufficient.",
|
|
2282
|
+
"- Expansion is read-only. The CLI Agent builds automatic decisions once from the final selected material, then submits those decisions for execution and audit.",
|
|
2283
|
+
"- When --limit is explicitly provided, respect that scope and do not expand it.",
|
|
2284
|
+
"- Automatic review only certifies eligible asset candidates from the current recommendation batch. It does not create recommended metrics.",
|
|
2285
|
+
"- CLI Agent blocks semantic duplicates, copy-like assets, synonym properties and ambiguous close definitions; every duplicate skip must name the conflicting asset targets.",
|
|
2286
|
+
"- The result includes manual_review_handoff for assets still uncertified after automatic review. Use it only when the user later asks to submit those assets to the review page.",
|
|
2287
|
+
"- For that later page submission, build the review packet from manual_review_handoff.page_review_items and relations so skipped assets keep their dashboard/report parent context; manual_review_handoff.items remains the exact unapproved review workload.",
|
|
2288
|
+
"- Automatic decisions are recorded for audit. Page-visible reasons must be reviewer-readable Chinese; keep raw source/rule codes only in debug exports.",
|
|
2289
|
+
"- Returned SKIP decisions mean the asset remains for manual review; do not describe skipped items as certified."
|
|
2290
|
+
].join("\n");
|
|
2291
|
+
var AUTO_REVIEW_CAPABILITY_ID = "metadata.governance_recommendation.auto_review";
|
|
2292
|
+
var EXPORT_CAPABILITY_ID = "metadata.governance_recommendation.export";
|
|
2293
|
+
var SUBMIT_CAPABILITY_ID = "metadata.governance_recommendation.submit";
|
|
2294
|
+
var DEFAULT_LIMIT = 20;
|
|
2295
|
+
var EXPANSION_LIMITS = [20, 50, 100];
|
|
2296
|
+
var MIN_PENDING_ASSETS = 10;
|
|
2297
|
+
var MIN_PENDING_WORK_UNITS = 3;
|
|
2298
|
+
var AUTO_REVIEW_DECISION_LIMIT = 100;
|
|
2299
|
+
var AUTO_REVIEW_MIN_HEAT = 50;
|
|
2300
|
+
var AUTO_REVIEW_MIN_USERS = 5;
|
|
2301
|
+
var AUTO_REVIEW_MIN_IMPACT = 2;
|
|
2302
|
+
var metadataGovernanceRecommendationAutoReview = {
|
|
2303
|
+
service: "analysis-meta",
|
|
2304
|
+
resource: "governance-recommendation",
|
|
2305
|
+
command: "auto-review",
|
|
2306
|
+
capabilityId: AUTO_REVIEW_CAPABILITY_ID,
|
|
2307
|
+
description: "Automatically review and certify eligible recommended assets when the project switch is enabled.",
|
|
2308
|
+
helpText: GOVERNANCE_RECOMMENDATION_AUTO_REVIEW_HELP,
|
|
2309
|
+
flags: [projectIdFlag, windowDaysFlag3, limitFlag4],
|
|
2310
|
+
risk: "write",
|
|
2311
|
+
preflight: (ctx) => {
|
|
2312
|
+
autoReviewInput(ctx);
|
|
2313
|
+
},
|
|
2314
|
+
validateInput: async (ctx) => validateCapability(
|
|
2315
|
+
ctx.host(),
|
|
2316
|
+
gatewayDomain(),
|
|
2317
|
+
AUTO_REVIEW_CAPABILITY_ID,
|
|
2318
|
+
autoReviewInput(ctx)
|
|
2319
|
+
),
|
|
2320
|
+
dryRun: async (ctx) => dryRunCapability(
|
|
2321
|
+
ctx.host(),
|
|
2322
|
+
gatewayDomain(),
|
|
2323
|
+
AUTO_REVIEW_CAPABILITY_ID,
|
|
2324
|
+
autoReviewInput(ctx)
|
|
2325
|
+
),
|
|
2326
|
+
execute: async (ctx) => {
|
|
2327
|
+
const input = autoReviewInput(ctx);
|
|
2328
|
+
if (hasExplicitLimit(ctx)) {
|
|
2329
|
+
await validateCapabilityWithEnvelope(ctx.host(), gatewayDomain(), AUTO_REVIEW_CAPABILITY_ID, input);
|
|
2330
|
+
const finalExport = await exportRecommendationMaterial(ctx, input, numberValue(input.limit) || DEFAULT_LIMIT);
|
|
2331
|
+
const result2 = await executeCliAgentAutoReview(ctx, input, finalExport.data);
|
|
2332
|
+
return withOutputMetadata({
|
|
2333
|
+
...record(result2.data),
|
|
2334
|
+
manual_review_handoff: buildManualReviewHandoff(result2.data, finalExport.data)
|
|
2335
|
+
}, result2.meta);
|
|
2336
|
+
}
|
|
2337
|
+
const plan = await planBoundedExpansion(ctx, input);
|
|
2338
|
+
const expansion = plan.expansion;
|
|
2339
|
+
const finalInput = { ...input, limit: expansion.final_limit };
|
|
2340
|
+
const result = await executeCliAgentAutoReview(ctx, finalInput, plan.finalExport);
|
|
2341
|
+
if (result.data && typeof result.data === "object" && !Array.isArray(result.data)) {
|
|
2342
|
+
return withOutputMetadata({
|
|
2343
|
+
...result.data,
|
|
2344
|
+
auto_review_expansion: expansion,
|
|
2345
|
+
manual_review_handoff: buildManualReviewHandoff(result.data, plan.finalExport)
|
|
2346
|
+
}, result.meta);
|
|
2347
|
+
}
|
|
2348
|
+
return withOutputMetadata(result.data, result.meta);
|
|
2349
|
+
}
|
|
2350
|
+
};
|
|
2351
|
+
function autoReviewInput(ctx) {
|
|
2352
|
+
return compactInput({
|
|
2353
|
+
...projectInput(ctx),
|
|
2354
|
+
window_days: optionalNumber(ctx, "window-days"),
|
|
2355
|
+
limit: optionalNumber(ctx, "limit")
|
|
2356
|
+
});
|
|
2357
|
+
}
|
|
2358
|
+
function gatewayDomain() {
|
|
2359
|
+
return resolveGatewayDomain("analysis-meta", "analysis");
|
|
2360
|
+
}
|
|
2361
|
+
function hasExplicitLimit(ctx) {
|
|
2362
|
+
return typeof ctx.has === "function" ? ctx.has("limit") : ctx.str("limit") !== "";
|
|
2363
|
+
}
|
|
2364
|
+
async function executeCliAgentAutoReview(ctx, input, exportResult) {
|
|
2365
|
+
const review = buildCliAgentAutoReview(input, exportResult);
|
|
2366
|
+
if (review.decisions.length === 0) {
|
|
2367
|
+
return {
|
|
2368
|
+
data: {
|
|
2369
|
+
...review.base,
|
|
2370
|
+
total: 0,
|
|
2371
|
+
applied: 0,
|
|
2372
|
+
recorded: 0,
|
|
2373
|
+
failed: 0,
|
|
2374
|
+
items: []
|
|
2375
|
+
},
|
|
2376
|
+
meta: {}
|
|
2377
|
+
};
|
|
2378
|
+
}
|
|
2379
|
+
const submitted = await executeCapabilityWithEnvelope(ctx.host(), gatewayDomain(), SUBMIT_CAPABILITY_ID, {
|
|
2380
|
+
...input,
|
|
2381
|
+
run_id: review.runId,
|
|
2382
|
+
snapshot_hash: review.snapshotHash,
|
|
2383
|
+
topic_id: "agent_auto_asset_certification",
|
|
2384
|
+
topic_name: "Agent \u81EA\u52A8\u8BA4\u8BC1\u8D44\u4EA7",
|
|
2385
|
+
decisions: review.decisions
|
|
2386
|
+
});
|
|
2387
|
+
const submittedData = record(submitted.data);
|
|
2388
|
+
return {
|
|
2389
|
+
data: {
|
|
2390
|
+
...review.base,
|
|
2391
|
+
total: submittedData.total,
|
|
2392
|
+
applied: submittedData.applied,
|
|
2393
|
+
recorded: submittedData.recorded,
|
|
2394
|
+
failed: submittedData.failed,
|
|
2395
|
+
items: autoReviewItemsWithDisplayReason(submittedData.items)
|
|
2396
|
+
},
|
|
2397
|
+
meta: submitted.meta
|
|
2398
|
+
};
|
|
2399
|
+
}
|
|
2400
|
+
async function planBoundedExpansion(ctx, input) {
|
|
2401
|
+
await validateCapabilityWithEnvelope(ctx.host(), gatewayDomain(), AUTO_REVIEW_CAPABILITY_ID, {
|
|
2402
|
+
...input,
|
|
2403
|
+
limit: DEFAULT_LIMIT
|
|
2404
|
+
});
|
|
2405
|
+
const attempts = [];
|
|
2406
|
+
let finalExport = {};
|
|
2407
|
+
let finalLimit = DEFAULT_LIMIT;
|
|
2408
|
+
let stopReason = "top_100_inspected";
|
|
2409
|
+
for (const limit of EXPANSION_LIMITS) {
|
|
2410
|
+
const exported = await exportRecommendationMaterial(ctx, input, limit);
|
|
2411
|
+
finalExport = exported.data;
|
|
2412
|
+
const summary = summarizeExport(exported.data, limit);
|
|
2413
|
+
attempts.push(summary);
|
|
2414
|
+
finalLimit = limit;
|
|
2415
|
+
const pendingAssets = numberValue(summary.pending_asset_candidates);
|
|
2416
|
+
const pendingWorkUnits = numberValue(summary.pending_work_units);
|
|
2417
|
+
const hasMore = summary.has_more === true;
|
|
2418
|
+
if (pendingAssets >= MIN_PENDING_ASSETS && pendingWorkUnits >= MIN_PENDING_WORK_UNITS) {
|
|
2419
|
+
stopReason = "sufficient_pending_scope";
|
|
2420
|
+
break;
|
|
2421
|
+
}
|
|
2422
|
+
if (!hasMore) {
|
|
2423
|
+
stopReason = "dashboard_pool_exhausted";
|
|
2424
|
+
break;
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
return {
|
|
2428
|
+
expansion: {
|
|
2429
|
+
strategy: "bounded_hot_dashboard_expansion",
|
|
2430
|
+
initial_limit: DEFAULT_LIMIT,
|
|
2431
|
+
final_limit: finalLimit,
|
|
2432
|
+
inspected_limits: attempts.map((attempt) => attempt.dashboard_limit),
|
|
2433
|
+
min_pending_asset_candidates: MIN_PENDING_ASSETS,
|
|
2434
|
+
min_pending_work_units: MIN_PENDING_WORK_UNITS,
|
|
2435
|
+
attempts,
|
|
2436
|
+
stop_reason: stopReason,
|
|
2437
|
+
write_policy: "single_auto_review_execute_after_read_only_expansion"
|
|
2438
|
+
},
|
|
2439
|
+
finalExport
|
|
2440
|
+
};
|
|
2441
|
+
}
|
|
2442
|
+
function exportRecommendationMaterial(ctx, input, limit) {
|
|
2443
|
+
return executeCapabilityWithEnvelope(
|
|
2444
|
+
ctx.host(),
|
|
2445
|
+
gatewayDomain(),
|
|
2446
|
+
EXPORT_CAPABILITY_ID,
|
|
2447
|
+
compactInput({ ...input, limit, include_completed: false })
|
|
2448
|
+
);
|
|
2449
|
+
}
|
|
2450
|
+
function summarizeExport(result, requestedLimit) {
|
|
2451
|
+
const data = record(result);
|
|
2452
|
+
const workUnits = array(data.work_units);
|
|
2453
|
+
const coverage = record(data.coverage);
|
|
2454
|
+
const pendingAssetCandidates = countPendingAssetCandidates(workUnits);
|
|
2455
|
+
return {
|
|
2456
|
+
dashboard_limit: numberValue(data.dashboard_limit) || requestedLimit,
|
|
2457
|
+
run_id: stringValue(data.run_id),
|
|
2458
|
+
snapshot_hash: stringValue(data.snapshot_hash),
|
|
2459
|
+
selected_dashboards: numberValue(coverage.selected_dashboards),
|
|
2460
|
+
returned_work_units: workUnits.length,
|
|
2461
|
+
pending_work_units: workUnits.filter((unit) => numberValue(record(unit).actionable_count) > 0).length,
|
|
2462
|
+
pending_asset_candidates: pendingAssetCandidates,
|
|
2463
|
+
has_more: coverage.has_more === true
|
|
2464
|
+
};
|
|
2465
|
+
}
|
|
2466
|
+
function countPendingAssetCandidates(workUnits) {
|
|
2467
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2468
|
+
for (const unit of workUnits) {
|
|
2469
|
+
for (const candidate of array(record(unit).asset_candidates)) {
|
|
2470
|
+
const item = record(candidate);
|
|
2471
|
+
if (item.actionable !== true || item.action_state !== "PENDING") {
|
|
2472
|
+
continue;
|
|
2473
|
+
}
|
|
2474
|
+
const type = stringValue(item.resource_type);
|
|
2475
|
+
const key = stringValue(item.resource_key);
|
|
2476
|
+
if (type && key) {
|
|
2477
|
+
seen.add(`${type}|${key}`);
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
return seen.size;
|
|
2482
|
+
}
|
|
2483
|
+
function buildCliAgentAutoReview(input, exportResult) {
|
|
2484
|
+
const exported = record(exportResult);
|
|
2485
|
+
const material = record(exported.review_material_package);
|
|
2486
|
+
const candidates = array(material.candidate_assets).map(record);
|
|
2487
|
+
const runId = `rec_auto_${randomUUID().replace(/-/g, "")}`;
|
|
2488
|
+
const snapshotHash = stringValue(exported.snapshot_hash);
|
|
2489
|
+
const semanticConflicts = semanticDuplicateConflicts(candidates);
|
|
2490
|
+
const decisions = [];
|
|
2491
|
+
let approved = 0;
|
|
2492
|
+
let skipped = 0;
|
|
2493
|
+
let overflow = 0;
|
|
2494
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2495
|
+
for (const candidate of candidates) {
|
|
2496
|
+
const target = record(candidate.target_ref);
|
|
2497
|
+
const type = stringValue(target.type);
|
|
2498
|
+
const key = stringValue(target.key);
|
|
2499
|
+
if (!type || !key || !seen.add(`${type}|${key}`)) continue;
|
|
2500
|
+
if (candidate.actionable !== true || candidate.action_state !== "PENDING") continue;
|
|
2501
|
+
if (decisions.length >= AUTO_REVIEW_DECISION_LIMIT) {
|
|
2502
|
+
overflow++;
|
|
2503
|
+
continue;
|
|
2504
|
+
}
|
|
2505
|
+
const verdict = cliAgentAutoReviewVerdict(candidate, semanticConflicts.get(`${type}|${key}`));
|
|
2506
|
+
if (verdict.decision === "APPROVE") approved++;
|
|
2507
|
+
else skipped++;
|
|
2508
|
+
decisions.push({
|
|
2509
|
+
item_type: "asset",
|
|
2510
|
+
decision: verdict.decision,
|
|
2511
|
+
resource_type: type,
|
|
2512
|
+
resource_key: key,
|
|
2513
|
+
evidence_hash: candidate.evidence_hash,
|
|
2514
|
+
reason: verdict.reason
|
|
2515
|
+
});
|
|
2516
|
+
}
|
|
2517
|
+
return {
|
|
2518
|
+
runId,
|
|
2519
|
+
snapshotHash,
|
|
2520
|
+
decisions,
|
|
2521
|
+
base: {
|
|
2522
|
+
schema_version: "1.0",
|
|
2523
|
+
run_id: runId,
|
|
2524
|
+
project_id: input.project_id ?? exported.project_id,
|
|
2525
|
+
window_days: input.window_days ?? exported.window_days,
|
|
2526
|
+
dashboard_limit: input.limit ?? exported.dashboard_limit,
|
|
2527
|
+
snapshot_hash: snapshotHash,
|
|
2528
|
+
rule_version: "agent_auto_asset_certification_v1",
|
|
2529
|
+
config_key: "agent_auto_asset_certification_enabled",
|
|
2530
|
+
semantic_config_key: "project_semantic_enable",
|
|
2531
|
+
auto_approved: approved,
|
|
2532
|
+
skipped,
|
|
2533
|
+
overflow
|
|
2534
|
+
}
|
|
2535
|
+
};
|
|
2536
|
+
}
|
|
2537
|
+
function cliAgentAutoReviewVerdict(candidate, semanticConflict) {
|
|
2538
|
+
if (semanticConflict) {
|
|
2539
|
+
return {
|
|
2540
|
+
decision: "SKIP",
|
|
2541
|
+
reason: autoReviewReason(`semantic_duplicate_targets=${encodeReasonPayload(semanticConflict)}`)
|
|
2542
|
+
};
|
|
2543
|
+
}
|
|
2544
|
+
if (listIncludes(candidate.conflict_risks, "same_evidence_rejected_before")) {
|
|
2545
|
+
return {
|
|
2546
|
+
decision: "SKIP",
|
|
2547
|
+
reason: autoReviewReason("same_evidence_rejected_before")
|
|
2548
|
+
};
|
|
2549
|
+
}
|
|
2550
|
+
if (array(candidate.source_evidence).length === 0 && candidate.recommendation_role !== "source_dashboard") {
|
|
2551
|
+
return {
|
|
2552
|
+
decision: "SKIP",
|
|
2553
|
+
reason: autoReviewReason("source_evidence_missing")
|
|
2554
|
+
};
|
|
2555
|
+
}
|
|
2556
|
+
const heat = numberValue(candidate.heat_count90d);
|
|
2557
|
+
const users = numberValue(candidate.user_count90d);
|
|
2558
|
+
const impact = numberValue(candidate.impact_degree);
|
|
2559
|
+
const matched = [];
|
|
2560
|
+
if (heat >= AUTO_REVIEW_MIN_HEAT) matched.push(`heat_count90d>=${AUTO_REVIEW_MIN_HEAT}`);
|
|
2561
|
+
if (users >= AUTO_REVIEW_MIN_USERS) matched.push(`user_count90d>=${AUTO_REVIEW_MIN_USERS}`);
|
|
2562
|
+
if (impact > AUTO_REVIEW_MIN_IMPACT) matched.push(`impact_degree>${AUTO_REVIEW_MIN_IMPACT}.0`);
|
|
2563
|
+
if (matched.length === 0) {
|
|
2564
|
+
return {
|
|
2565
|
+
decision: "SKIP",
|
|
2566
|
+
reason: autoReviewReason(`signals_below_threshold: heat_count90d=${heat}, user_count90d=${users}, impact_degree=${impact}`)
|
|
2567
|
+
};
|
|
2568
|
+
}
|
|
2569
|
+
return {
|
|
2570
|
+
decision: "APPROVE",
|
|
2571
|
+
reason: autoReviewReason(`matched=${matched.join(",")}; role=${stringValue(candidate.recommendation_role) ?? "asset"}`)
|
|
2572
|
+
};
|
|
2573
|
+
}
|
|
2574
|
+
function autoReviewReason(reason) {
|
|
2575
|
+
return `source=AGENT_AUTO_REVIEW; rule_version=agent_auto_asset_certification_v1; ${reason}`;
|
|
2576
|
+
}
|
|
2577
|
+
function autoReviewItemsWithDisplayReason(items) {
|
|
2578
|
+
return array(items).map((value) => {
|
|
2579
|
+
const item = record(value);
|
|
2580
|
+
const copy = {
|
|
2581
|
+
...item,
|
|
2582
|
+
semantic_duplicate_targets: semanticDuplicateTargetsFromReason(stringValue(item.reason) ?? "")
|
|
2583
|
+
};
|
|
2584
|
+
if (item.decision !== "APPROVE") {
|
|
2585
|
+
copy.display_reason = autoReviewDisplayReason(item);
|
|
2586
|
+
}
|
|
2587
|
+
return copy;
|
|
2588
|
+
});
|
|
2589
|
+
}
|
|
2590
|
+
function semanticDuplicateConflicts(candidates) {
|
|
2591
|
+
const result = /* @__PURE__ */ new Map();
|
|
2592
|
+
const comparable = candidates.map((candidate) => comparableAsset(candidate)).filter((candidate) => !!candidate);
|
|
2593
|
+
for (const candidate of comparable) {
|
|
2594
|
+
if (candidate.actionable !== true || candidate.actionState !== "PENDING") continue;
|
|
2595
|
+
const matches = [];
|
|
2596
|
+
for (const other of comparable) {
|
|
2597
|
+
if (candidate.assetKey === other.assetKey) continue;
|
|
2598
|
+
const basis = semanticDuplicateBasis(candidate, other);
|
|
2599
|
+
if (basis) matches.push({ asset: other, basis });
|
|
2600
|
+
}
|
|
2601
|
+
if (!matches.length) continue;
|
|
2602
|
+
matches.sort((left, right) => duplicateRank(right.asset) - duplicateRank(left.asset));
|
|
2603
|
+
const targets = matches.slice(0, 3).map(({ asset, basis }) => ({
|
|
2604
|
+
target_ref: { type: asset.type, key: asset.key },
|
|
2605
|
+
display_name: asset.displayName,
|
|
2606
|
+
resource_type: asset.type,
|
|
2607
|
+
resource_key: asset.key,
|
|
2608
|
+
authentication_status: asset.authenticationStatus,
|
|
2609
|
+
action_state: asset.actionState,
|
|
2610
|
+
reason: duplicateBasisText(basis)
|
|
2611
|
+
}));
|
|
2612
|
+
result.set(candidate.assetKey, {
|
|
2613
|
+
targets,
|
|
2614
|
+
basis: Array.from(new Set(matches.map((match) => match.basis))).map(duplicateBasisText)
|
|
2615
|
+
});
|
|
2616
|
+
}
|
|
2617
|
+
return result;
|
|
2618
|
+
}
|
|
2619
|
+
function comparableAsset(candidate) {
|
|
2620
|
+
const target = record(candidate.target_ref);
|
|
2621
|
+
const type = stringValue(target.type);
|
|
2622
|
+
const key = stringValue(target.key);
|
|
2623
|
+
if (!type || !key) return void 0;
|
|
2624
|
+
const displayName = stringValue(candidate.display_name) ?? key;
|
|
2625
|
+
const evidence = record(candidate.evidence_snapshot);
|
|
2626
|
+
const evidenceAsset = record(evidence.asset);
|
|
2627
|
+
const description = stringValue(record(candidate.evidence_snapshot).description) ?? stringValue(evidenceAsset.description) ?? stringValue(candidate.description) ?? "";
|
|
2628
|
+
return {
|
|
2629
|
+
assetKey: `${type}|${key}`,
|
|
2630
|
+
type,
|
|
2631
|
+
key,
|
|
2632
|
+
displayName,
|
|
2633
|
+
description,
|
|
2634
|
+
authenticationStatus: numberValue(evidenceAsset.authentication_status ?? candidate.authentication_status),
|
|
2635
|
+
actionState: stringValue(candidate.action_state) ?? "",
|
|
2636
|
+
actionable: candidate.actionable === true,
|
|
2637
|
+
normalizedName: normalizeSemanticText(displayName || key),
|
|
2638
|
+
canonicalName: canonicalDuplicateText(displayName || key),
|
|
2639
|
+
aliasName: aliasDuplicateText(displayName || key),
|
|
2640
|
+
normalizedDescription: normalizeSemanticText(description),
|
|
2641
|
+
heat: numberValue(candidate.heat_count90d),
|
|
2642
|
+
users: numberValue(candidate.user_count90d),
|
|
2643
|
+
impact: numberValue(candidate.impact_degree)
|
|
2644
|
+
};
|
|
2645
|
+
}
|
|
2646
|
+
function semanticDuplicateBasis(left, right) {
|
|
2647
|
+
if (!left.normalizedName || !right.normalizedName) return void 0;
|
|
2648
|
+
if (left.normalizedName.length >= 3 && left.normalizedName === right.normalizedName) return "same_display_name";
|
|
2649
|
+
if (left.canonicalName.length >= 3 && left.canonicalName === right.canonicalName) return "copy_or_suffix_variant";
|
|
2650
|
+
if (left.aliasName.length >= 3 && left.aliasName === right.aliasName && relatedAssetTypes(left.type, right.type)) {
|
|
2651
|
+
return "business_alias_equivalent";
|
|
2652
|
+
}
|
|
2653
|
+
if (left.normalizedDescription.length >= 6 && left.normalizedDescription === right.normalizedDescription) {
|
|
2654
|
+
return "same_description";
|
|
2655
|
+
}
|
|
2656
|
+
return void 0;
|
|
2657
|
+
}
|
|
2658
|
+
function relatedAssetTypes(left, right) {
|
|
2659
|
+
if (left === right) return true;
|
|
2660
|
+
return left.endsWith("_prop") && right.endsWith("_prop");
|
|
2661
|
+
}
|
|
2662
|
+
function duplicateRank(asset) {
|
|
2663
|
+
return (asset.authenticationStatus === 1 ? 1e5 : 0) + (asset.actionState === "AUTHENTICATED" ? 5e4 : 0) + asset.heat + asset.users * 10 + asset.impact * 100;
|
|
2664
|
+
}
|
|
2665
|
+
function normalizeSemanticText(value) {
|
|
2666
|
+
return value.toLowerCase().replace(/[\s_\-—–/\\|::,,.。"'`【】\[\]()(){}<>《》]/g, "").trim();
|
|
2667
|
+
}
|
|
2668
|
+
function canonicalDuplicateText(value) {
|
|
2669
|
+
return normalizeSemanticText(value).replace(/(副本|复制|拷贝|备份|copy|backup|bak|test|测试|临时|tmp)+$/g, "").replace(/v\d+$/g, "").replace(/\d+$/g, "");
|
|
2670
|
+
}
|
|
2671
|
+
function aliasDuplicateText(value) {
|
|
2672
|
+
return canonicalDuplicateText(value).replace(/(公司|企业|客户|客戶|client|customer|company|account)/g, "\u5BA2\u6237").replace(/(项目|工程|project)/g, "\u9879\u76EE").replace(/(用户|玩家|会员|user|player|member)/g, "\u7528\u6237");
|
|
2673
|
+
}
|
|
2674
|
+
function duplicateBasisText(value) {
|
|
2675
|
+
switch (value) {
|
|
2676
|
+
case "same_display_name":
|
|
2677
|
+
return "\u8D44\u4EA7\u540D\u79F0\u4E00\u81F4";
|
|
2678
|
+
case "copy_or_suffix_variant":
|
|
2679
|
+
return "\u540D\u79F0\u4EC5\u5B58\u5728\u526F\u672C\u3001\u7248\u672C\u6216\u4E34\u65F6\u540E\u7F00\u5DEE\u5F02";
|
|
2680
|
+
case "business_alias_equivalent":
|
|
2681
|
+
return "\u4E1A\u52A1\u5BF9\u8C61\u8868\u8FF0\u76F8\u8FD1\uFF0C\u53EF\u80FD\u662F\u540C\u4E49\u5C5E\u6027\u6216\u76F8\u8FD1\u53E3\u5F84";
|
|
2682
|
+
case "same_description":
|
|
2683
|
+
return "\u8D44\u4EA7\u63CF\u8FF0\u4E00\u81F4";
|
|
2684
|
+
default:
|
|
2685
|
+
return value;
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2688
|
+
function encodeReasonPayload(value) {
|
|
2689
|
+
return Buffer.from(JSON.stringify(value), "utf8").toString("base64url");
|
|
2690
|
+
}
|
|
2691
|
+
function decodeReasonPayload(value) {
|
|
2692
|
+
try {
|
|
2693
|
+
return record(JSON.parse(Buffer.from(value, "base64url").toString("utf8")));
|
|
2694
|
+
} catch {
|
|
2695
|
+
return {};
|
|
2696
|
+
}
|
|
2697
|
+
}
|
|
2698
|
+
function semanticDuplicateTargetsFromReason(reason) {
|
|
2699
|
+
const encoded = /semantic_duplicate_targets=([A-Za-z0-9_-]+)/.exec(reason)?.[1];
|
|
2700
|
+
if (!encoded) return [];
|
|
2701
|
+
return array(decodeReasonPayload(encoded).targets);
|
|
2702
|
+
}
|
|
2703
|
+
function listIncludes(value, expected) {
|
|
2704
|
+
return array(value).some((item) => item === expected);
|
|
2705
|
+
}
|
|
2706
|
+
function buildManualReviewHandoff(autoReviewResult, exportResult) {
|
|
2707
|
+
const result = record(autoReviewResult);
|
|
2708
|
+
const exported = record(exportResult);
|
|
2709
|
+
const material = record(exported.review_material_package);
|
|
2710
|
+
const decisions = decisionsByAsset(result.items);
|
|
2711
|
+
const candidates = array(material.candidate_assets);
|
|
2712
|
+
const relations = array(material.relations).map(record);
|
|
2713
|
+
const handoffItems = [];
|
|
2714
|
+
const approved = /* @__PURE__ */ new Set();
|
|
2715
|
+
for (const decision of decisions.values()) {
|
|
2716
|
+
if (decision.decision === "APPROVE" && decision.landing_status === "APPLIED") {
|
|
2717
|
+
approved.add(decision.assetKey);
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2720
|
+
const autoCertifiedItems = buildAutoCertifiedItems(decisions, candidates);
|
|
2721
|
+
for (const value of candidates) {
|
|
2722
|
+
const candidate = record(value);
|
|
2723
|
+
const target = record(candidate.target_ref);
|
|
2724
|
+
const type = stringValue(target.type);
|
|
2725
|
+
const key = stringValue(target.key);
|
|
2726
|
+
if (!type || !key) {
|
|
2727
|
+
continue;
|
|
2728
|
+
}
|
|
2729
|
+
const assetKey = `${type}|${key}`;
|
|
2730
|
+
if (approved.has(assetKey)) {
|
|
2731
|
+
continue;
|
|
2732
|
+
}
|
|
2733
|
+
const decision = decisions.get(assetKey);
|
|
2734
|
+
const actionable = candidate.actionable === true;
|
|
2735
|
+
if (!decision && !actionable) {
|
|
2736
|
+
continue;
|
|
2737
|
+
}
|
|
2738
|
+
const reviewReason = decision ? manualReviewReason(decision, candidate) : "\u672C\u6B21\u81EA\u52A8\u8BA4\u8BC1\u672A\u4EA7\u751F\u660E\u786E\u7ED3\u8BBA\uFF0C\u53EF\u80FD\u662F\u5019\u9009\u8D44\u4EA7\u8D85\u51FA\u672C\u6B21\u81EA\u52A8\u8BA4\u8BC1\u5904\u7406\u4E0A\u9650\u6216\u88AB\u53BB\u91CD\uFF0C\u8BF7\u4EBA\u5DE5\u786E\u8BA4\u3002";
|
|
2739
|
+
handoffItems.push({
|
|
2740
|
+
...candidate,
|
|
2741
|
+
auto_review_decision: decision ? decision.raw : {
|
|
2742
|
+
decision: "NOT_REVIEWED",
|
|
2743
|
+
reason: reviewReason
|
|
2744
|
+
},
|
|
2745
|
+
semantic_duplicate_targets: decision ? array(decision.raw.semantic_duplicate_targets) : [],
|
|
2746
|
+
manual_review_reason: reviewReason
|
|
2747
|
+
});
|
|
2748
|
+
}
|
|
2749
|
+
const pageReviewItems = buildPageReviewItems(handoffItems, candidates, relations, decisions);
|
|
2750
|
+
const pageReviewIds = new Set(pageReviewItems.map((item) => stringValue(item.client_item_id)).filter(Boolean));
|
|
2751
|
+
return {
|
|
2752
|
+
schema_version: "1.0",
|
|
2753
|
+
handoff_type: "auto_review_uncertified_assets_to_page_review",
|
|
2754
|
+
project_id: result.project_id ?? exported.project_id,
|
|
2755
|
+
source_auto_review_run_id: result.run_id,
|
|
2756
|
+
source_export_run_id: exported.run_id,
|
|
2757
|
+
snapshot_hash: exported.snapshot_hash ?? result.snapshot_hash,
|
|
2758
|
+
dashboard_limit: exported.dashboard_limit ?? result.dashboard_limit,
|
|
2759
|
+
auto_review_trace: {
|
|
2760
|
+
run_id: result.run_id,
|
|
2761
|
+
rule_version: result.rule_version,
|
|
2762
|
+
auto_approved: result.auto_approved,
|
|
2763
|
+
skipped: result.skipped,
|
|
2764
|
+
overflow: result.overflow,
|
|
2765
|
+
approved_items: autoCertifiedItems,
|
|
2766
|
+
skipped_items: handoffItems.map((item) => ({
|
|
2767
|
+
target_ref: record(item.target_ref),
|
|
2768
|
+
display_name: item.display_name,
|
|
2769
|
+
manual_review_reason: item.manual_review_reason
|
|
2770
|
+
}))
|
|
2771
|
+
},
|
|
2772
|
+
auto_certified_items: autoCertifiedItems,
|
|
2773
|
+
candidate_count: handoffItems.length,
|
|
2774
|
+
items: handoffItems,
|
|
2775
|
+
page_review_items: pageReviewItems,
|
|
2776
|
+
page_review_context_count: pageReviewItems.length - handoffItems.length,
|
|
2777
|
+
relations: relations.filter((edge) => pageReviewIds.has(stringValue(edge.parent)) && pageReviewIds.has(stringValue(edge.child))),
|
|
2778
|
+
source_index: array(material.source_index).map(record).filter((source) => pageReviewIds.has(stringValue(source.client_item_id))),
|
|
2779
|
+
quality_gates: array(material.quality_gates),
|
|
2780
|
+
definition_policy: record(material.definition_policy),
|
|
2781
|
+
submit_to_page_policy: {
|
|
2782
|
+
command: "analysis-meta agent-review submit-to-page",
|
|
2783
|
+
scope: "Submit page_review_items so unapproved assets keep dashboard/report parent context; only items without manual_review_context require human certification decisions.",
|
|
2784
|
+
reason_field: "manual_review_reason",
|
|
2785
|
+
source_metadata: "When submitting leftovers, copy manual_review_handoff.auto_review_trace to submit-to-page source_metadata.auto_review_trace so the page audit records show the assets Agent already certified.",
|
|
2786
|
+
requires_user_submission_intent: true
|
|
2787
|
+
}
|
|
2788
|
+
};
|
|
2789
|
+
}
|
|
2790
|
+
function buildPageReviewItems(handoffItems, candidates, relations, decisions) {
|
|
2791
|
+
const byId = /* @__PURE__ */ new Map();
|
|
2792
|
+
const requiredIds = /* @__PURE__ */ new Set();
|
|
2793
|
+
for (const value of candidates) {
|
|
2794
|
+
const candidate = record(value);
|
|
2795
|
+
const id = stringValue(candidate.client_item_id);
|
|
2796
|
+
if (id) byId.set(id, candidate);
|
|
2797
|
+
}
|
|
2798
|
+
for (const item of handoffItems) {
|
|
2799
|
+
const id = stringValue(item.client_item_id);
|
|
2800
|
+
if (id) requiredIds.add(id);
|
|
2801
|
+
}
|
|
2802
|
+
let changed = true;
|
|
2803
|
+
while (changed) {
|
|
2804
|
+
changed = false;
|
|
2805
|
+
for (const edge of relations) {
|
|
2806
|
+
const parent = stringValue(edge.parent);
|
|
2807
|
+
const child = stringValue(edge.child);
|
|
2808
|
+
if (parent && child && requiredIds.has(child) && !requiredIds.has(parent) && byId.has(parent)) {
|
|
2809
|
+
requiredIds.add(parent);
|
|
2810
|
+
changed = true;
|
|
2811
|
+
}
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
const handoffById = new Map(handoffItems.map((item) => [stringValue(item.client_item_id), item]).filter((entry) => !!entry[0]));
|
|
2815
|
+
return candidates.map(record).filter((candidate) => {
|
|
2816
|
+
const id = stringValue(candidate.client_item_id);
|
|
2817
|
+
return id !== void 0 && requiredIds.has(id);
|
|
2818
|
+
}).map((candidate) => {
|
|
2819
|
+
const id = stringValue(candidate.client_item_id) ?? "";
|
|
2820
|
+
const handoff = handoffById.get(id);
|
|
2821
|
+
if (handoff) return handoff;
|
|
2822
|
+
const target = record(candidate.target_ref);
|
|
2823
|
+
const type = stringValue(target.type);
|
|
2824
|
+
const key = stringValue(target.key);
|
|
2825
|
+
const decision = type && key ? decisions.get(`${type}|${key}`) : void 0;
|
|
2826
|
+
return markContextCandidate(candidate, decision);
|
|
2827
|
+
});
|
|
2828
|
+
}
|
|
2829
|
+
function markContextCandidate(candidate, decision) {
|
|
2830
|
+
const item = { ...candidate };
|
|
2831
|
+
item.manual_review_context = true;
|
|
2832
|
+
item.manual_review_reason = "\u8BE5\u8D44\u4EA7\u7528\u4E8E\u4FDD\u7559\u81EA\u52A8\u53D1\u73B0\u9875\u9762\u7684\u7236\u5B50\u5C42\u7EA7\u548C\u6765\u6E90\u4E0A\u4E0B\u6587\uFF0C\u4E0D\u4F5C\u4E3A\u672C\u6B21\u4EBA\u5DE5\u5BA1\u6838\u5BF9\u8C61\u3002";
|
|
2833
|
+
if (decision?.decision === "APPROVE" && decision.landing_status === "APPLIED") {
|
|
2834
|
+
item.auto_review_decision = decision.raw;
|
|
2835
|
+
item.auto_review_context_reason = autoReviewDisplayReason(decision.raw, candidate);
|
|
2836
|
+
item.evidence_snapshot = markEvidenceAuthenticated(record(candidate.evidence_snapshot));
|
|
2837
|
+
}
|
|
2838
|
+
return item;
|
|
2839
|
+
}
|
|
2840
|
+
function markEvidenceAuthenticated(evidence) {
|
|
2841
|
+
const snapshot = { ...evidence };
|
|
2842
|
+
const asset = record(snapshot.asset);
|
|
2843
|
+
if (Object.keys(asset).length) {
|
|
2844
|
+
snapshot.asset = { ...asset, authentication_status: 1 };
|
|
2845
|
+
}
|
|
2846
|
+
return snapshot;
|
|
2847
|
+
}
|
|
2848
|
+
function decisionsByAsset(value) {
|
|
2849
|
+
const result = /* @__PURE__ */ new Map();
|
|
2850
|
+
for (const itemValue of array(value)) {
|
|
2851
|
+
const item = record(itemValue);
|
|
2852
|
+
if (item.item_type !== "asset") {
|
|
2853
|
+
continue;
|
|
2854
|
+
}
|
|
2855
|
+
const type = stringValue(item.resource_type);
|
|
2856
|
+
const key = stringValue(item.resource_key);
|
|
2857
|
+
if (!type || !key) {
|
|
2858
|
+
continue;
|
|
2859
|
+
}
|
|
2860
|
+
const assetKey = `${type}|${key}`;
|
|
2861
|
+
result.set(assetKey, {
|
|
2862
|
+
assetKey,
|
|
2863
|
+
decision: stringValue(item.decision) ?? "",
|
|
2864
|
+
landing_status: stringValue(item.landing_status) ?? "",
|
|
2865
|
+
raw: item
|
|
2866
|
+
});
|
|
2867
|
+
}
|
|
2868
|
+
return result;
|
|
2869
|
+
}
|
|
2870
|
+
function buildAutoCertifiedItems(decisions, candidates) {
|
|
2871
|
+
const byAsset = /* @__PURE__ */ new Map();
|
|
2872
|
+
for (const value of candidates) {
|
|
2873
|
+
const candidate = record(value);
|
|
2874
|
+
const target = record(candidate.target_ref);
|
|
2875
|
+
const type = stringValue(target.type);
|
|
2876
|
+
const key = stringValue(target.key);
|
|
2877
|
+
if (type && key) byAsset.set(`${type}|${key}`, candidate);
|
|
2878
|
+
}
|
|
2879
|
+
const items = [];
|
|
2880
|
+
for (const decision of decisions.values()) {
|
|
2881
|
+
if (decision.decision !== "APPROVE" || decision.landing_status !== "APPLIED") continue;
|
|
2882
|
+
const candidate = byAsset.get(decision.assetKey) ?? {};
|
|
2883
|
+
items.push({
|
|
2884
|
+
target_ref: record(candidate.target_ref),
|
|
2885
|
+
display_name: candidate.display_name ?? decision.raw.resource_key,
|
|
2886
|
+
auto_review_reason: autoReviewDisplayReason(decision.raw, candidate),
|
|
2887
|
+
landing_message: decision.raw.landing_message
|
|
2888
|
+
});
|
|
2889
|
+
}
|
|
2890
|
+
return items;
|
|
2891
|
+
}
|
|
2892
|
+
function manualReviewReason(decision, context) {
|
|
2893
|
+
const reason = autoReviewDisplayReason(decision.raw, context);
|
|
2894
|
+
if (decision.decision === "SKIP") {
|
|
2895
|
+
return reason;
|
|
2896
|
+
}
|
|
2897
|
+
if (decision.decision === "APPROVE" && decision.landing_status !== "APPLIED") {
|
|
2898
|
+
const landing = stringValue(decision.raw.landing_message);
|
|
2899
|
+
return landing ? `${reason}; landing_${decision.landing_status.toLowerCase()}: ${landing}` : `${reason}; landing_${decision.landing_status.toLowerCase()}`;
|
|
2900
|
+
}
|
|
2901
|
+
return reason;
|
|
2902
|
+
}
|
|
2903
|
+
function autoReviewDisplayReason(raw, context = {}) {
|
|
2904
|
+
const display = stringValue(raw.display_reason);
|
|
2905
|
+
if (display) return display;
|
|
2906
|
+
const reason = stringValue(raw.reason);
|
|
2907
|
+
if (!reason) return "\u672C\u6B21\u81EA\u52A8\u8BA4\u8BC1\u6CA1\u6709\u8FD4\u56DE\u539F\u56E0\uFF0C\u8BF7\u4EBA\u5DE5\u786E\u8BA4\u3002";
|
|
2908
|
+
return humanizeAutoReviewReason(reason, context);
|
|
2909
|
+
}
|
|
2910
|
+
function humanizeAutoReviewReason(reason, context) {
|
|
2911
|
+
if (reason.includes("semantic_duplicate_targets=")) {
|
|
2912
|
+
const targets = semanticDuplicateTargetsFromReason(reason).map(record).map((target) => {
|
|
2913
|
+
const ref = record(target.target_ref);
|
|
2914
|
+
const label = stringValue(target.display_name) ?? stringValue(target.resource_key) ?? stringValue(ref.key) ?? "\u672A\u77E5\u8D44\u4EA7";
|
|
2915
|
+
const type = stringValue(target.resource_type) ?? stringValue(ref.type) ?? "asset";
|
|
2916
|
+
const key = stringValue(target.resource_key) ?? stringValue(ref.key) ?? "-";
|
|
2917
|
+
const targetReason = stringValue(target.reason);
|
|
2918
|
+
return `${label}\uFF08${type}:${key}${targetReason ? `\uFF0C${targetReason}` : ""}\uFF09`;
|
|
2919
|
+
});
|
|
2920
|
+
const targetText = targets.length ? targets.join("\uFF1B") : "\u76F8\u8FD1\u8D44\u4EA7";
|
|
2921
|
+
return `\u672A\u81EA\u52A8\u8BA4\u8BC1\u539F\u56E0\uFF1A\u7591\u4F3C\u4E0E ${targetText} \u8BED\u4E49\u91CD\u590D\u6216\u53E3\u5F84\u76F8\u8FD1\u3002\u8BF7\u4EBA\u5DE5\u786E\u8BA4\u662F\u5426\u5E94\u4F5C\u4E3A\u72EC\u7ACB\u8D44\u4EA7\u8BA4\u8BC1\uFF1B\u5982\u679C\u53EA\u662F\u526F\u672C\u3001\u540C\u4E49\u5C5E\u6027\u6216\u76F8\u8FD1\u53E3\u5F84\uFF0C\u8BF7\u4F18\u5148\u9009\u62E9\u66F4\u6807\u51C6\u7684\u8D44\u4EA7\u3002`;
|
|
2922
|
+
}
|
|
2923
|
+
if (reason.includes("previous_decision_exists_for_different_evidence")) {
|
|
2924
|
+
return "\u672A\u81EA\u52A8\u8BA4\u8BC1\u539F\u56E0\uFF1A\u68C0\u6D4B\u5230\u8BE5\u8D44\u4EA7\u5B58\u5728\u5386\u53F2\u5904\u7406\u8BB0\u5F55\uFF0C\u4F46\u672C\u6B21\u672A\u8FD4\u56DE\u53EF\u6838\u9A8C\u7684\u91CD\u590D\u5BF9\u8C61\u3002\u8BF7\u6309\u5F53\u524D\u8D44\u4EA7\u5B9A\u4E49\u548C\u6765\u6E90\u8BC1\u636E\u4EBA\u5DE5\u786E\u8BA4\uFF1B\u8FD9\u4E0D\u4EE3\u8868\u7CFB\u7EDF\u53D1\u73B0\u4E86\u91CD\u590D\u8D44\u4EA7\u3002";
|
|
2925
|
+
}
|
|
2926
|
+
if (reason.includes("same_evidence_rejected_before")) {
|
|
2927
|
+
return "\u672A\u81EA\u52A8\u8BA4\u8BC1\u539F\u56E0\uFF1A\u76F8\u540C\u8BA4\u8BC1\u5EFA\u8BAE\u6B64\u524D\u5DF2\u88AB\u4EBA\u5DE5\u9A73\u56DE\uFF0C\u81EA\u52A8\u8BA4\u8BC1\u4E0D\u4F1A\u8986\u76D6\u4EBA\u5DE5\u7ED3\u8BBA\u3002\u5982\u4E1A\u52A1\u53E3\u5F84\u5DF2\u8C03\u6574\uFF0C\u8BF7\u4EBA\u5DE5\u91CD\u65B0\u786E\u8BA4\u662F\u5426\u8BA4\u8BC1\u3002";
|
|
2928
|
+
}
|
|
2929
|
+
if (reason.includes("source_evidence_missing")) {
|
|
2930
|
+
return "\u81EA\u52A8\u8BA4\u8BC1\u672A\u901A\u8FC7\uFF1A\u7F3A\u5C11\u53EF\u6838\u9A8C\u7684\u6765\u6E90\u8D44\u4EA7\u8BC1\u636E\uFF0C\u8BF7\u4EBA\u5DE5\u786E\u8BA4\u8D44\u4EA7\u6765\u6E90\u3001\u5B9A\u4E49\u548C\u4F9D\u8D56\u5173\u7CFB\u540E\u518D\u8BA4\u8BC1\u3002";
|
|
2931
|
+
}
|
|
2932
|
+
if (reason.includes("signals_below_threshold")) {
|
|
2933
|
+
const heat = /heat_count90d=(\d+)/.exec(reason)?.[1];
|
|
2934
|
+
const users = /user_count90d=(\d+)/.exec(reason)?.[1];
|
|
2935
|
+
const impact = /impact_degree=([0-9.]+)/.exec(reason)?.[1];
|
|
2936
|
+
return `\u81EA\u52A8\u8BA4\u8BC1\u672A\u901A\u8FC7\uFF1A\u8BE5\u8D44\u4EA7\u8FD1 90 \u5929\u8BBF\u95EE/\u4F7F\u7528 ${heat ?? "\u672A\u77E5"} \u6B21\u3001\u4F7F\u7528\u4EBA\u6570 ${users ?? "\u672A\u77E5"}\uFF0C\u5F71\u54CD\u5EA6 ${impact ?? "\u672A\u77E5"}\uFF0C\u672A\u8FBE\u5230\u81EA\u52A8\u8BA4\u8BC1\u9608\u503C\uFF0C\u8BF7\u4EBA\u5DE5\u786E\u8BA4\u662F\u5426\u4ECD\u9700\u8981\u8BA4\u8BC1\u3002`;
|
|
2937
|
+
}
|
|
2938
|
+
if (reason.includes("matched=")) {
|
|
2939
|
+
const matched = [];
|
|
2940
|
+
if (reason.includes("heat_count90d>=")) matched.push("\u8BBF\u95EE/\u4F7F\u7528\u6B21\u6570\u8FBE\u5230\u9608\u503C");
|
|
2941
|
+
if (reason.includes("user_count90d>=")) matched.push("\u4F7F\u7528\u4EBA\u6570\u8FBE\u5230\u9608\u503C");
|
|
2942
|
+
if (reason.includes("impact_degree>")) matched.push("\u5F71\u54CD\u5EA6\u8FBE\u5230\u9608\u503C");
|
|
2943
|
+
const matchedText = matched.length ? matched.join("\u3001") : "\u547D\u4E2D\u81EA\u52A8\u8BA4\u8BC1\u89C4\u5219";
|
|
2944
|
+
return `Agent \u81EA\u52A8\u8BA4\u8BC1\u901A\u8FC7\uFF1A\u8BE5\u8D44\u4EA7\u8FD1 90 \u5929\u8BBF\u95EE/\u4F7F\u7528 ${displaySignal(context.heat_count90d)} \u6B21\u3001\u4F7F\u7528\u4EBA\u6570 ${displaySignal(context.user_count90d)}\uFF0C\u5F71\u54CD\u5EA6 ${displaySignal(context.impact_degree)}\uFF1B\u672A\u53D1\u73B0\u8BED\u4E49\u91CD\u590D\u98CE\u9669\uFF0C\u4E14${matchedText}\u3002`;
|
|
2945
|
+
}
|
|
2946
|
+
return reason.replace(/^source=AGENT_AUTO_REVIEW;\s*/, "").replace(/rule_version=[^;]+;\s*/, "").replace(/conflict_risks=\[[^\]]*]/, "\u81EA\u52A8\u8BA4\u8BC1\u672A\u901A\u8FC7\uFF1A\u5B58\u5728\u9700\u8981\u4EBA\u5DE5\u786E\u8BA4\u7684\u5BA1\u6838\u98CE\u9669\u3002").replace(/conflict_risks=/, "\u81EA\u52A8\u8BA4\u8BC1\u672A\u901A\u8FC7\uFF1A\u5B58\u5728\u9700\u8981\u4EBA\u5DE5\u786E\u8BA4\u7684\u5BA1\u6838\u98CE\u9669\u3002");
|
|
2947
|
+
}
|
|
2948
|
+
function displaySignal(value) {
|
|
2949
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
2950
|
+
if (typeof value === "string" && value.trim()) return value;
|
|
2951
|
+
return "\u672A\u77E5";
|
|
2952
|
+
}
|
|
2953
|
+
function record(value) {
|
|
2954
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2955
|
+
}
|
|
2956
|
+
function array(value) {
|
|
2957
|
+
return Array.isArray(value) ? value : [];
|
|
2958
|
+
}
|
|
2959
|
+
function numberValue(value) {
|
|
2960
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
2961
|
+
}
|
|
2962
|
+
function stringValue(value) {
|
|
2963
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
2964
|
+
}
|
|
2965
|
+
|
|
2241
2966
|
// src/commands/te-analysis/meta/governance-recommendation/decisions.ts
|
|
2242
2967
|
var runIdFlag2 = {
|
|
2243
2968
|
name: "run-id",
|
|
@@ -2245,7 +2970,7 @@ var runIdFlag2 = {
|
|
|
2245
2970
|
required: false,
|
|
2246
2971
|
desc: "Optional run_id filter."
|
|
2247
2972
|
};
|
|
2248
|
-
var
|
|
2973
|
+
var limitFlag5 = {
|
|
2249
2974
|
name: "limit",
|
|
2250
2975
|
type: "number",
|
|
2251
2976
|
required: false,
|
|
@@ -2258,7 +2983,7 @@ var metadataGovernanceRecommendationDecisions = createAnalysisMetaCapabilityComm
|
|
|
2258
2983
|
command: "decisions",
|
|
2259
2984
|
capabilityId: "metadata.governance_recommendation.decisions",
|
|
2260
2985
|
description: "List recent CLI Agent recommendation approval decisions.",
|
|
2261
|
-
flags: [projectIdFlag, runIdFlag2,
|
|
2986
|
+
flags: [projectIdFlag, runIdFlag2, limitFlag5],
|
|
2262
2987
|
risk: "read",
|
|
2263
2988
|
buildInput: (ctx) => compactInput({
|
|
2264
2989
|
...projectInput(ctx),
|
|
@@ -2271,6 +2996,7 @@ var metadataGovernanceRecommendationDecisions = createAnalysisMetaCapabilityComm
|
|
|
2271
2996
|
var commands11 = [
|
|
2272
2997
|
metadataGovernanceRecommendationExport,
|
|
2273
2998
|
metadataGovernanceRecommendationSubmit,
|
|
2999
|
+
metadataGovernanceRecommendationAutoReview,
|
|
2274
3000
|
metadataGovernanceRecommendationDecisions
|
|
2275
3001
|
];
|
|
2276
3002
|
var governance_recommendation_default = commands11;
|
|
@@ -2322,7 +3048,7 @@ function object(value, name) {
|
|
|
2322
3048
|
}
|
|
2323
3049
|
return value;
|
|
2324
3050
|
}
|
|
2325
|
-
function
|
|
3051
|
+
function array2(value, name) {
|
|
2326
3052
|
if (!Array.isArray(value) || value.length < 1 || value.length > 5e3) {
|
|
2327
3053
|
throw new Error(`${name} must contain 1 to 5000 items.`);
|
|
2328
3054
|
}
|
|
@@ -2367,6 +3093,7 @@ var SUBMIT_TO_PAGE_HELP = [
|
|
|
2367
3093
|
"- relations should let the page render dashboard -> report -> metadata with contains/uses edges. Use an empty relations array only when the package truly has no known parent-child evidence.",
|
|
2368
3094
|
"- Each submitted item must keep source_link or evidence_links[].url so reviewers can jump to source evidence.",
|
|
2369
3095
|
"- item.ai_summary.summary is the per-item recommendation reason. It must cite concrete item evidence, not generic review boilerplate. batch ai_summary.summary is only the batch overview.",
|
|
3096
|
+
"- When submitting manual_review_handoff leftovers, copy manual_review_handoff.auto_review_trace into source_metadata.auto_review_trace so page audit records include the assets already certified automatically.",
|
|
2370
3097
|
"- For reports and SQL reports, item.ai_summary.analysis_explanation must explain reviewer-readable calculations or measures from packaged evidence_snapshot.analysis. A purpose-only summary is incomplete and is rejected locally before dispatch.",
|
|
2371
3098
|
"- Reviewer-visible text should follow the project-KB source style: one business Chinese Agent summary that explains purpose, calculation caliber, filters, time scope, boundaries, and concrete reviewer questions. Keep raw SQL, parser labels, temporary aliases, parameter placeholders, hashes, and evidence paths in evidence_snapshot only; independent Agent preflight flags visible implementation terms as quality findings.",
|
|
2372
3099
|
"- The command output includes review_page_url when review_url is present. Return review_page_url to the user; do not prepend the Common/API host to review_url yourself.",
|
|
@@ -2378,6 +3105,7 @@ var SUBMIT_TO_PAGE_HELP = [
|
|
|
2378
3105
|
' "title": "<review batch title>",',
|
|
2379
3106
|
' "source_run_id": "<export.run_id>",',
|
|
2380
3107
|
' "source_task_id": "<optional preauthorized task id>",',
|
|
3108
|
+
' "source_metadata": { "auto_review_trace": "<optional trace from manual_review_handoff.auto_review_trace>" },',
|
|
2381
3109
|
' "ai_summary": { "summary": "<batch overview>" },',
|
|
2382
3110
|
' "presentation_snapshot": {',
|
|
2383
3111
|
' "project": { "id": 1, "name": "<project name>" },',
|
|
@@ -2465,7 +3193,7 @@ var agentReviewSubmitToPage = createAnalysisMetaCapabilityCommand({
|
|
|
2465
3193
|
postProcess: (result, _input, ctx) => normalizeSubmitResult(result, resolvePublicWebHost(ctx.host()), ctx.host())
|
|
2466
3194
|
});
|
|
2467
3195
|
function validateInput(input) {
|
|
2468
|
-
const items =
|
|
3196
|
+
const items = array2(input.items, "items").map((value) => {
|
|
2469
3197
|
const item = object(value, "items[]");
|
|
2470
3198
|
fields(item, [
|
|
2471
3199
|
"client_item_id",
|
|
@@ -2512,6 +3240,7 @@ function validateInput(input) {
|
|
|
2512
3240
|
"title",
|
|
2513
3241
|
"source_run_id",
|
|
2514
3242
|
"source_task_id",
|
|
3243
|
+
"source_metadata",
|
|
2515
3244
|
"ai_summary",
|
|
2516
3245
|
"presentation_snapshot",
|
|
2517
3246
|
"items"
|
|
@@ -2581,7 +3310,7 @@ function validateEvidenceLinks(item) {
|
|
|
2581
3310
|
const sourceLink = typeof item.source_link === "string" && item.source_link.trim();
|
|
2582
3311
|
let evidenceLink = false;
|
|
2583
3312
|
if ("evidence_links" in item) {
|
|
2584
|
-
evidenceLink =
|
|
3313
|
+
evidenceLink = array2(item.evidence_links, "items[].evidence_links").some((value) => {
|
|
2585
3314
|
const link = object(value, "items[].evidence_links[]");
|
|
2586
3315
|
return typeof link.url === "string" && !!link.url.trim();
|
|
2587
3316
|
});
|
|
@@ -2592,17 +3321,17 @@ function validateEvidenceLinks(item) {
|
|
|
2592
3321
|
}
|
|
2593
3322
|
function validatePresentation(presentation, itemIds) {
|
|
2594
3323
|
const displayed = /* @__PURE__ */ new Set();
|
|
2595
|
-
for (const topicValue of
|
|
3324
|
+
for (const topicValue of array2(presentation.topics, "presentation_snapshot.topics")) {
|
|
2596
3325
|
const topic = object(topicValue, "presentation_snapshot.topics[]");
|
|
2597
3326
|
if ("items" in topic) {
|
|
2598
3327
|
throw new Error("presentation_snapshot.topics[] must use groups[].items, not top-level items.");
|
|
2599
3328
|
}
|
|
2600
|
-
for (const groupValue of
|
|
3329
|
+
for (const groupValue of array2(topic.groups, "presentation_snapshot.topics[].groups")) {
|
|
2601
3330
|
const group = object(groupValue, "presentation_snapshot.topics[].groups[]");
|
|
2602
3331
|
if (typeof group.id !== "string" || !group.id.trim() || typeof group.name !== "string" || !group.name.trim()) {
|
|
2603
3332
|
throw new Error("presentation_snapshot.topics[].groups[] requires nonempty string id and name.");
|
|
2604
3333
|
}
|
|
2605
|
-
for (const itemValue of
|
|
3334
|
+
for (const itemValue of array2(group.items, "presentation_snapshot.topics[].groups[].items")) {
|
|
2606
3335
|
const item = object(itemValue, "presentation_snapshot.topics[].groups[].items[]");
|
|
2607
3336
|
if (typeof item.id !== "string" || !item.id.trim()) {
|
|
2608
3337
|
throw new Error("presentation_snapshot display items require nonempty string id.");
|
|
@@ -2649,7 +3378,7 @@ var agentReviewReview = createAnalysisMetaCapabilityCommand({
|
|
|
2649
3378
|
{ name: "decisions", type: "json", required: true, desc: "Versioned decisions: item_id (string), version (integer), decision APPROVE/DEFER/REJECT, reason (required for DEFER/REJECT)." }
|
|
2650
3379
|
],
|
|
2651
3380
|
buildInput: (ctx) => {
|
|
2652
|
-
const decisions =
|
|
3381
|
+
const decisions = array2(ctx.json("decisions"), "--decisions").map((value) => {
|
|
2653
3382
|
const decision = object(value, "decisions[]");
|
|
2654
3383
|
fields(decision, ["item_id", "version", "decision", "reason"], "decisions[]");
|
|
2655
3384
|
decimalId(decision.item_id, "decisions[].item_id");
|
|
@@ -2686,7 +3415,7 @@ var agentReviewRetry = createAnalysisMetaCapabilityCommand({
|
|
|
2686
3415
|
{ name: "item-ids", type: "json", required: true, desc: "1 to 5000 failed item IDs as decimal strings. Successful items must not be retried." }
|
|
2687
3416
|
],
|
|
2688
3417
|
buildInput: (ctx) => {
|
|
2689
|
-
const ids =
|
|
3418
|
+
const ids = array2(ctx.json("item-ids"), "--item-ids").map((id) => decimalId(id, "item_ids[]"));
|
|
2690
3419
|
unique(ids, "item_ids");
|
|
2691
3420
|
return { ...batchInput(ctx), client_request_id: text(ctx, "client-request-id"), item_ids: ids };
|
|
2692
3421
|
}
|
|
@@ -2770,9 +3499,9 @@ var analysisMetaAssetUsageList = createAnalysisGovernanceCapabilityCommand({
|
|
|
2770
3499
|
command: "list",
|
|
2771
3500
|
capabilityId: "governance.asset.list",
|
|
2772
3501
|
description: "List assets for usage governance.",
|
|
2773
|
-
flags: [projectIdFlag, queryFlag, searchsFlag, ruleFlag, operationTypeFlag, directoryLimitFlag, directoryOffsetFlag, payloadFlag],
|
|
3502
|
+
flags: [projectIdFlag, nodeIdFlag, queryFlag, searchsFlag, ruleFlag, operationTypeFlag, directoryLimitFlag, directoryOffsetFlag, payloadFlag],
|
|
2774
3503
|
risk: "read",
|
|
2775
|
-
buildInput: (ctx) => assetGovernanceInput(ctx, ["query", "searchs", "rule", "operation_type", "limit", "offset"])
|
|
3504
|
+
buildInput: (ctx) => assetGovernanceInput(ctx, ["node_id", "query", "searchs", "rule", "operation_type", "limit", "offset"])
|
|
2776
3505
|
});
|
|
2777
3506
|
|
|
2778
3507
|
// src/commands/te-analysis/meta/asset/usage-export.ts
|
|
@@ -2780,10 +3509,11 @@ var analysisMetaAssetUsageExport = createAnalysisGovernanceCapabilityCommand({
|
|
|
2780
3509
|
resource: "asset",
|
|
2781
3510
|
command: "export",
|
|
2782
3511
|
capabilityId: "governance.asset.export",
|
|
2783
|
-
description: "Export asset usage governance rows as an
|
|
2784
|
-
flags: [projectIdFlag, queryFlag, searchsFlag, ruleFlag, operationTypeFlag, limitFlag, offsetFlag, payloadFlag],
|
|
3512
|
+
description: "Export asset usage governance rows as an asynchronous artifact; optionally wait and download.",
|
|
3513
|
+
flags: [projectIdFlag, nodeIdFlag, queryFlag, searchsFlag, ruleFlag, operationTypeFlag, limitFlag, offsetFlag, payloadFlag, ...governanceExportFlags("jsonl")],
|
|
2785
3514
|
risk: "read",
|
|
2786
|
-
|
|
3515
|
+
asyncArtifact: true,
|
|
3516
|
+
buildInput: (ctx) => assetGovernanceInput(ctx, [...governanceExportFields, "node_id", "query", "searchs", "rule", "operation_type", "limit", "offset"])
|
|
2787
3517
|
});
|
|
2788
3518
|
|
|
2789
3519
|
// src/commands/te-analysis/meta/asset/lineage-get.ts
|
|
@@ -2891,9 +3621,10 @@ var analysisMetaAssetBatchInfoExport = createAnalysisGovernanceCapabilityCommand
|
|
|
2891
3621
|
command: "batch-info-export",
|
|
2892
3622
|
capabilityId: "governance.asset.batch_export_info",
|
|
2893
3623
|
description: "Batch export asset information.",
|
|
2894
|
-
flags: [projectIdFlag, nodeIdsFlag, payloadFlag],
|
|
3624
|
+
flags: [projectIdFlag, nodeIdsFlag, payloadFlag, ...governanceExportFlags("xlsx")],
|
|
2895
3625
|
risk: "read",
|
|
2896
|
-
|
|
3626
|
+
asyncArtifact: true,
|
|
3627
|
+
buildInput: (ctx) => assetGovernanceInput(ctx, [...governanceExportFields, "node_ids"])
|
|
2897
3628
|
});
|
|
2898
3629
|
|
|
2899
3630
|
// src/commands/te-analysis/meta/asset/batch-sql-export.ts
|
|
@@ -2902,9 +3633,10 @@ var analysisMetaAssetBatchSqlExport = createAnalysisGovernanceCapabilityCommand(
|
|
|
2902
3633
|
command: "batch-sql-export",
|
|
2903
3634
|
capabilityId: "governance.asset.batch_export_sql",
|
|
2904
3635
|
description: "Batch export asset SQL definitions.",
|
|
2905
|
-
flags: [projectIdFlag, nodeIdsFlag, payloadFlag],
|
|
3636
|
+
flags: [projectIdFlag, nodeIdsFlag, payloadFlag, ...governanceExportFlags("xlsx")],
|
|
2906
3637
|
risk: "read",
|
|
2907
|
-
|
|
3638
|
+
asyncArtifact: true,
|
|
3639
|
+
buildInput: (ctx) => assetGovernanceInput(ctx, [...governanceExportFields, "node_ids"])
|
|
2908
3640
|
});
|
|
2909
3641
|
|
|
2910
3642
|
// src/commands/te-analysis/meta/asset/batch-delete.ts
|
|
@@ -2979,9 +3711,10 @@ var analysisMetaAssetOperationRecordExport = createAnalysisGovernanceCapabilityC
|
|
|
2979
3711
|
command: "export",
|
|
2980
3712
|
capabilityId: "governance.operation_record.export",
|
|
2981
3713
|
description: "Export one asset batch operation record result.",
|
|
2982
|
-
flags: [projectIdFlag, recordIdFlag, payloadFlag],
|
|
3714
|
+
flags: [projectIdFlag, recordIdFlag, payloadFlag, ...governanceExportFlags("xlsx")],
|
|
2983
3715
|
risk: "read",
|
|
2984
|
-
|
|
3716
|
+
asyncArtifact: true,
|
|
3717
|
+
buildInput: (ctx) => assetGovernanceInput(ctx, [...governanceExportFields, "record_id"])
|
|
2985
3718
|
});
|
|
2986
3719
|
|
|
2987
3720
|
// src/commands/te-analysis/governance/asset-authentication-shared.ts
|
|
@@ -3359,7 +4092,7 @@ var reportList = createAnalysisCapabilityCommand({
|
|
|
3359
4092
|
resource: "report",
|
|
3360
4093
|
command: "list",
|
|
3361
4094
|
capabilityId: "analysis.report.list",
|
|
3362
|
-
description: "List analysis reports
|
|
4095
|
+
description: "List analysis reports the current user can edit or manage. Read-only reports are excluded; use analysis asset search for readable asset discovery.",
|
|
3363
4096
|
flags: [
|
|
3364
4097
|
projectIdFlag,
|
|
3365
4098
|
queriesFlag,
|
|
@@ -3439,7 +4172,7 @@ var REPORT_WRITE_MODEL_TYPE_VALUES = [
|
|
|
3439
4172
|
];
|
|
3440
4173
|
var REPORT_WRITE_MODEL_DESCRIPTION = `${AI_MODEL_DESCRIPTION} Report create/update also supports tag for saved tag report data; use tag as the AI-facing spelling.`;
|
|
3441
4174
|
var AI_DEFINITION_DESCRIPTION = 'Event metrics: omit optional display_name unless the target command schema explicitly supports it. Funnel step filters use event_property_name (not field) and string-array values, including "true"/"false" for boolean properties. For tag/cluster filters, cluster_date_policy accepts LATEST (default), AUTO (match the computed result for each analysis date), or SPECIFIED (requires specified_cluster_date in yyyy-MM-dd format). AI-facing model definition JSON. Do not pass raw QP, events, event_view, visual_view, or analysis_query. Distribution filters must be attached to the corresponding distribution_metrics[].filters; do not use top-level filters or relation. For path definitions, global filters support user_property, cluster, and tag only; event_property is not supported. session_unit accepts second (1..999), minute (1..999), or hour (1..24). Do not use day; express one day as session_interval=24 and session_unit=hour. For SQL, a simple query is {"sql":"select ..."}; raw variables use ${name}, while typed params use ${Text:name}, ${Selector:name}, or ${PartDate:name}. PartDate expands to a complete predicate, so write WHERE ${PartDate:d}, not a column followed by the placeholder. A part_date parameter may set boolean use_timezone; it defaults to false and controls whether that parameter uses the query effective timezone. Selector value must match one options[].value. Trino identifiers containing #, $, @, spaces, punctuation, or a reserved word must be delimited with double quotes, for example SELECT "#user_id", "$part_event", "end" FROM ...; single quotes are string literals. For multiline SQL JSON, the decoded sql value must contain a real line break; do not submit a literal \\n sequence outside quoted SQL text. Queries against an event table must include a date-partition predicate on the quoted "$part_date" column, for example WHERE "$part_date" BETWEEN \'2026-07-01\' AND \'2026-07-07\'; the backend rejects event-table SQL without it. The CLI preserves SQL text and never auto-quotes identifiers.';
|
|
3442
|
-
var REPORT_WRITE_DEFINITION_DESCRIPTION = `${AI_DEFINITION_DESCRIPTION} For model_type=tag, pass a tag report intent such as {"tag":{"tag_name":"vip_users","time_range":{"mode":"recent","unit":"day","value":7}}}. Tags are supported for report create/update and report data, not ad-hoc analysis.`;
|
|
4175
|
+
var REPORT_WRITE_DEFINITION_DESCRIPTION = `${AI_DEFINITION_DESCRIPTION} Saved-report filters may contain one compound group level only; every item inside that group must be a leaf without another items array. Historical deeper trees remain readable but cannot be written back as a definition. For model_type=tag, pass a tag report intent such as {"tag":{"tag_name":"vip_users","time_range":{"mode":"recent","unit":"day","value":7}}}. Tags are supported for report create/update and report data, not ad-hoc analysis.`;
|
|
3443
4176
|
function aiModelTypeFlag(required) {
|
|
3444
4177
|
return {
|
|
3445
4178
|
name: "model-type",
|
|
@@ -3453,18 +4186,32 @@ function validateFunnelStepFilters(modelType, definition) {
|
|
|
3453
4186
|
const steps = definition.funnel.steps;
|
|
3454
4187
|
if (!Array.isArray(steps)) return;
|
|
3455
4188
|
const errors = [];
|
|
3456
|
-
|
|
3457
|
-
if (!isRecord(
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
4189
|
+
const visit = (filter, location) => {
|
|
4190
|
+
if (!isRecord(filter)) {
|
|
4191
|
+
errors.push(`${location}: use a filter object.`);
|
|
4192
|
+
return;
|
|
4193
|
+
}
|
|
4194
|
+
if ("items" in filter) {
|
|
4195
|
+
if (Object.keys(filter).some((key) => key !== "items" && key !== "relation")) {
|
|
4196
|
+
errors.push(`${location}: compound groups contain only items and relation; put event_property_name and operator on their leaf items.`);
|
|
3463
4197
|
}
|
|
3464
|
-
if (
|
|
3465
|
-
errors.push(`${location}.
|
|
4198
|
+
if (!Array.isArray(filter.items) || filter.items.length === 0) {
|
|
4199
|
+
errors.push(`${location}.items: use a non-empty array of event-property filters or nested groups.`);
|
|
4200
|
+
} else {
|
|
4201
|
+
filter.items.forEach((item, index) => visit(item, `${location}.items[${index}]`));
|
|
3466
4202
|
}
|
|
3467
|
-
|
|
4203
|
+
return;
|
|
4204
|
+
}
|
|
4205
|
+
if ("field" in filter || typeof filter.event_property_name !== "string" || !filter.event_property_name.trim()) {
|
|
4206
|
+
errors.push(`${location}: use a non-empty event_property_name, not a generic field object.`);
|
|
4207
|
+
}
|
|
4208
|
+
if ("values" in filter && (!Array.isArray(filter.values) || filter.values.some((value) => typeof value !== "string"))) {
|
|
4209
|
+
errors.push(`${location}.values: use an array of strings (boolean properties use "true" or "false").`);
|
|
4210
|
+
}
|
|
4211
|
+
};
|
|
4212
|
+
steps.forEach((step, stepIndex) => {
|
|
4213
|
+
if (!isRecord(step) || !Array.isArray(step.filters)) return;
|
|
4214
|
+
step.filters.forEach((filter, filterIndex) => visit(filter, `definition.funnel.steps[${stepIndex}].filters[${filterIndex}]`));
|
|
3468
4215
|
});
|
|
3469
4216
|
if (errors.length) {
|
|
3470
4217
|
throw new CliValidationError(errors.join("\n"), {
|
|
@@ -3554,7 +4301,7 @@ var reportCreate = createAnalysisCapabilityCommand({
|
|
|
3554
4301
|
function validateReportUpdate(ctx) {
|
|
3555
4302
|
const hasDefinition = ctx.str("definition") !== "";
|
|
3556
4303
|
const hasResolutions = ctx.json("resolutions") !== void 0;
|
|
3557
|
-
const hasMetadataUpdate = ctx.str("report-name") !== "" || ctx
|
|
4304
|
+
const hasMetadataUpdate = ctx.str("report-name") !== "" || optionalStringPreserveEmpty(ctx, "report-desc") !== void 0;
|
|
3558
4305
|
if (!hasDefinition && !hasMetadataUpdate) {
|
|
3559
4306
|
throw new Error("At least one of --report-name, --report-desc, or --definition is required.");
|
|
3560
4307
|
}
|
|
@@ -3576,7 +4323,7 @@ var reportUpdate = createAnalysisCapabilityCommand({
|
|
|
3576
4323
|
{ name: "report-id", type: "number", required: true, desc: "Report ID to update." },
|
|
3577
4324
|
{ name: "report-version", type: "number", required: true, desc: "Current report version from report get." },
|
|
3578
4325
|
{ name: "report-name", type: "string", required: false, desc: "New report display name." },
|
|
3579
|
-
{ name: "report-desc", type: "string", required: false, desc: "New report description." },
|
|
4326
|
+
{ name: "report-desc", type: "string", required: false, desc: "New report description. Pass an empty string to clear it; omit to preserve it." },
|
|
3580
4327
|
reportWriteModelTypeFlag(false),
|
|
3581
4328
|
reportWriteDefinitionFlag(false),
|
|
3582
4329
|
modelDefinitionIntentSnapshotFlag,
|
|
@@ -3592,7 +4339,7 @@ var reportUpdate = createAnalysisCapabilityCommand({
|
|
|
3592
4339
|
report_id: ctx.num("report-id"),
|
|
3593
4340
|
version: ctx.num("report-version"),
|
|
3594
4341
|
report_name: optionalString(ctx, "report-name"),
|
|
3595
|
-
report_desc:
|
|
4342
|
+
report_desc: optionalStringPreserveEmpty(ctx, "report-desc"),
|
|
3596
4343
|
model_type: optionalString(ctx, "model-type"),
|
|
3597
4344
|
definition: optionalJson(ctx, "definition"),
|
|
3598
4345
|
resolutions: optionalJson(ctx, "resolutions"),
|
|
@@ -3841,7 +4588,7 @@ var dashboardList = createAnalysisCapabilityCommand({
|
|
|
3841
4588
|
resource: "dashboard",
|
|
3842
4589
|
command: "list",
|
|
3843
4590
|
capabilityId: "analysis.dashboard.list",
|
|
3844
|
-
description: "List dashboards
|
|
4591
|
+
description: "List dashboards the current user can update or manage. Read-only dashboards are excluded; use analysis asset search for readable asset discovery.",
|
|
3845
4592
|
flags: [
|
|
3846
4593
|
projectIdFlag,
|
|
3847
4594
|
queriesFlag,
|
|
@@ -4176,14 +4923,13 @@ var dashboardReportDataExport = createAnalysisCapabilityCommand({
|
|
|
4176
4923
|
clusterQueryScopeFlag,
|
|
4177
4924
|
slaveClusterIdFlag,
|
|
4178
4925
|
{ name: "zone-offset", type: "number", required: false, desc: reportDataZoneOffsetDescription },
|
|
4179
|
-
{ name: "use-cache", type: "boolean", required: false, desc: "Whether to use cache. Default: true." },
|
|
4180
4926
|
{ name: "request-id", type: "string", required: false, desc: "Optional cli_<32 lowercase hex> request ID. Generated when omitted." },
|
|
4181
4927
|
asyncTimeoutSecondsFlag,
|
|
4182
4928
|
{ name: "artifact-format", type: "string", required: false, desc: "Artifact format. Only jsonl is supported." }
|
|
4183
4929
|
],
|
|
4184
4930
|
risk: "read",
|
|
4185
4931
|
validate: validateClusterQueryRouting,
|
|
4186
|
-
buildInput: dashboardReportDataInput
|
|
4932
|
+
buildInput: (ctx) => dashboardReportDataInput(ctx, false)
|
|
4187
4933
|
});
|
|
4188
4934
|
|
|
4189
4935
|
// src/commands/te-analysis/dashboard-report-data/index.ts
|
|
@@ -6592,7 +7338,7 @@ var sqlTableColumns = createAnalysisCapabilityCommand({
|
|
|
6592
7338
|
name: "table-ref",
|
|
6593
7339
|
type: "string",
|
|
6594
7340
|
required: true,
|
|
6595
|
-
desc: "Exact table_ref returned by analysis sql-table list; a unique table-only reference is also accepted."
|
|
7341
|
+
desc: "Exact table_ref or quoted sql_reference returned by analysis sql-table list; a unique table-only reference is also accepted."
|
|
6596
7342
|
},
|
|
6597
7343
|
sqlTableUsageFlag
|
|
6598
7344
|
],
|
|
@@ -6609,7 +7355,7 @@ var sqlTableList = createAnalysisCapabilityCommand({
|
|
|
6609
7355
|
resource: "sql-table",
|
|
6610
7356
|
command: "list",
|
|
6611
7357
|
capabilityId: "analysis.sql_table.list",
|
|
6612
|
-
description: "List server-authoritative SQL table references queryable by the current user in a project.",
|
|
7358
|
+
description: "List server-authoritative SQL table references queryable by the current user in a project, including authorized space tables. Use sql_reference when copying a table into SQL.",
|
|
6613
7359
|
flags: [projectIdFlag, queriesFlag, directoryLimitFlag, directoryOffsetFlag, sqlTableUsageFlag],
|
|
6614
7360
|
risk: "read",
|
|
6615
7361
|
validate: validateQueriesFlag,
|