@thinkingai/ae-cli 6.1.20 → 6.1.21
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 +2 -1
- package/README.zh.md +2 -1
- package/dist/{auth-FUM37MHF.js → auth-XZNXFRJS.js} +5 -5
- package/dist/{capability-AXFQW5WM.js → capability-FYTU3X6L.js} +42 -12
- package/dist/{chunk-LNZBEQXW.js → chunk-4NRCTUZJ.js} +27041 -474
- package/dist/{chunk-VXNMYUXU.js → chunk-57RRFUEZ.js} +23 -7
- package/dist/{chunk-WZ6YVQSF.js → chunk-7FTTULED.js} +1 -1
- package/dist/{chunk-ATSM5XAW.js → chunk-7XGFSUOM.js} +2 -2
- package/dist/chunk-CCS66K4K.js +155 -0
- package/dist/{chunk-I4WQAEYB.js → chunk-DVMLWQD4.js} +8 -186
- package/dist/{chunk-CZU3V3DQ.js → chunk-DX5CDO34.js} +27 -6
- package/dist/chunk-EQ255HKO.js +38248 -0
- package/dist/{chunk-BBEFP4SB.js → chunk-HBGADCKA.js} +3 -3
- package/dist/{chunk-QJQZH5GQ.js → chunk-HFGZGYCG.js} +10 -6
- package/dist/{chunk-ECBLHAZO.js → chunk-JOCDD4ON.js} +1 -1
- package/dist/{chunk-TKHSULJT.js → chunk-KPQY44JQ.js} +6 -0
- package/dist/{chunk-4P355ZWB.js → chunk-MAPZ7VB6.js} +21 -1
- package/dist/chunk-V2NUHPXF.js +196 -0
- package/dist/{chunk-RSG4ONOI.js → chunk-VYXXOKYS.js} +5 -5
- package/dist/{community-report-client-XXWGSBSD.js → community-report-client-CU22W53K.js} +1 -1
- package/dist/{config-EXUGQN5T.js → config-XO3LI3SA.js} +4 -4
- package/dist/context-IFJI3LIT.js +46 -0
- package/dist/{data-integration-4NZ53OMT.js → data-integration-HNGUKFIC.js} +44 -35
- package/dist/index.js +101 -64
- package/dist/{local-data-upload-client-KYOKVYZV.js → local-data-upload-client-GTRIT64F.js} +3 -2
- package/dist/{memory-ATNKZNW5.js → memory-QGPSNCQS.js} +4 -4
- package/dist/{metadata-VZVC7YMH.js → metadata-DI5BMYFU.js} +8 -8
- package/dist/{model-E4JMQ4V2.js → model-RNPQXIBI.js} +4 -4
- package/dist/{personal-semantic-preference-7S2SQ3UV.js → personal-semantic-preference-5C3WUXFI.js} +11 -8
- package/dist/{project-semantic-2SZP2OPO.js → project-semantic-3LF6Q6JZ.js} +27 -21
- package/dist/{sync-YV3E66IF.js → sync-O45NXEQY.js} +7 -6
- package/dist/{te-agent-JB5T3PO7.js → te-agent-K5MSPNHJ.js} +5 -5
- package/dist/{te-analysis-3YJAAT2D.js → te-analysis-AISWCOOZ.js} +1086 -354
- package/dist/{te-community-UDBI672N.js → te-community-4OYU3BDA.js} +4 -4
- package/dist/{te-dataops-ZLYOCXZ4.js → te-dataops-NFIPB6FX.js} +5 -5
- package/dist/{te-engage-4XG6OJML.js → te-engage-BAM3GBFX.js} +7 -7
- package/dist/{te-experiment-VXUWPINJ.js → te-experiment-GUTZXZ5Z.js} +132 -14
- package/dist/{te-kb-WYQWHFSC.js → te-kb-3TS73NO6.js} +454 -194
- package/dist/{te-system-7G6F2LJA.js → te-system-STMHLS5J.js} +12 -7
- package/dist/{te-team-E7FBBXMQ.js → te-team-3I5AOX3N.js} +6 -6
- package/dist/{update-D47BUG25.js → update-RZXLPCRH.js} +4 -4
- package/package.json +21 -14
- package/skills/ae-analysis/SKILL.md +91 -78
- package/skills/ae-analysis/references/adhoc_export.md +11 -18
- package/skills/ae-analysis/references/adhoc_run.md +15 -7
- package/skills/ae-analysis/references/agent_review_detail.md +11 -0
- package/skills/ae-analysis/references/agent_review_evidence.md +46 -0
- package/skills/ae-analysis/references/agent_review_list.md +9 -0
- package/skills/ae-analysis/references/agent_review_preflight.md +96 -0
- package/skills/ae-analysis/references/agent_review_priorities_comparisons.md +76 -0
- package/skills/ae-analysis/references/agent_review_records.md +9 -0
- package/skills/ae-analysis/references/agent_review_retry.md +12 -0
- package/skills/ae-analysis/references/agent_review_review.md +16 -0
- package/skills/ae-analysis/references/agent_review_submit_to_page.md +184 -0
- package/skills/ae-analysis/references/ai_models/attribution.md +29 -0
- package/skills/ae-analysis/references/ai_models/distribution.md +40 -0
- package/skills/ae-analysis/references/ai_models/event.md +108 -0
- package/skills/ae-analysis/references/ai_models/funnel.md +46 -0
- package/skills/ae-analysis/references/ai_models/heat_map.md +26 -0
- package/skills/ae-analysis/references/ai_models/interval.md +20 -0
- package/skills/ae-analysis/references/ai_models/path.md +38 -0
- package/skills/ae-analysis/references/ai_models/prop_analysis.md +39 -0
- package/skills/ae-analysis/references/ai_models/rank_list.md +25 -0
- package/skills/ae-analysis/references/ai_models/retention.md +70 -0
- package/skills/ae-analysis/references/ai_models/revenue.md +28 -0
- package/skills/ae-analysis/references/ai_models/sql.md +74 -0
- package/skills/ae-analysis/references/ai_models/tag.md +19 -0
- package/skills/ae-analysis/references/ai_models.md +32 -473
- package/skills/ae-analysis/references/alert_create.md +7 -7
- package/skills/ae-analysis/references/alert_delete.md +4 -6
- package/skills/ae-analysis/references/alert_detail_list.md +7 -9
- package/skills/ae-analysis/references/alert_get.md +5 -7
- package/skills/ae-analysis/references/alert_job_list.md +4 -6
- package/skills/ae-analysis/references/alert_list.md +6 -8
- package/skills/ae-analysis/references/alert_notice_config_list.md +4 -6
- package/skills/ae-analysis/references/alert_start.md +5 -7
- package/skills/ae-analysis/references/alert_stop.md +5 -7
- package/skills/ae-analysis/references/alert_update.md +8 -8
- package/skills/ae-analysis/references/analysis_data_export.md +72 -0
- package/skills/ae-analysis/references/analysis_data_retrieval.md +32 -196
- package/skills/ae-analysis/references/analysis_gateway_assets.md +23 -180
- package/skills/ae-analysis/references/analysis_interpretation.md +37 -17
- package/skills/ae-analysis/references/asset_abnormal_get.md +0 -1
- package/skills/ae-analysis/references/asset_abnormal_list.md +0 -1
- package/skills/ae-analysis/references/asset_authentication_export.md +4 -0
- package/skills/ae-analysis/references/asset_authentication_list.md +7 -1
- package/skills/ae-analysis/references/asset_authentication_update.md +5 -1
- package/skills/ae-analysis/references/asset_batch_dashboard_schedule_freeze.md +8 -6
- package/skills/ae-analysis/references/asset_batch_delete.md +6 -6
- package/skills/ae-analysis/references/asset_batch_disable_auto_backup.md +4 -5
- package/skills/ae-analysis/references/asset_batch_disable_auto_update.md +5 -6
- package/skills/ae-analysis/references/asset_batch_handover.md +4 -5
- package/skills/ae-analysis/references/asset_batch_info_export.md +4 -5
- package/skills/ae-analysis/references/asset_batch_sql_export.md +5 -6
- package/skills/ae-analysis/references/asset_dependency_list.md +4 -5
- package/skills/ae-analysis/references/asset_export.md +4 -5
- package/skills/ae-analysis/references/asset_impact_list.md +5 -9
- package/skills/ae-analysis/references/asset_lineage_get.md +5 -6
- package/skills/ae-analysis/references/asset_list.md +4 -5
- package/skills/ae-analysis/references/asset_query_history_list.md +4 -8
- package/skills/ae-analysis/references/asset_recent_list.md +0 -1
- package/skills/ae-analysis/references/asset_search.md +12 -9
- package/skills/ae-analysis/references/asset_url_get.md +3 -4
- package/skills/ae-analysis/references/bi_panel_copy.md +2 -2
- package/skills/ae-analysis/references/bi_panel_page_data_export.md +4 -12
- package/skills/ae-analysis/references/bi_panel_page_data_run.md +2 -0
- package/skills/ae-analysis/references/catalog_export.md +4 -17
- package/skills/ae-analysis/references/catalog_list.md +4 -4
- package/skills/ae-analysis/references/check_delete.md +5 -7
- package/skills/ae-analysis/references/check_export.md +11 -11
- package/skills/ae-analysis/references/check_get.md +8 -10
- package/skills/ae-analysis/references/check_list.md +4 -6
- package/skills/ae-analysis/references/check_retry.md +8 -10
- package/skills/ae-analysis/references/check_run.md +2 -4
- package/skills/ae-analysis/references/command_index.md +44 -26
- package/skills/ae-analysis/references/dashboard_report_data_export.md +5 -13
- package/skills/ae-analysis/references/dashboard_report_data_run.md +1 -1
- package/skills/ae-analysis/references/dashboard_update.md +14 -3
- package/skills/ae-analysis/references/datatable_columns_get.md +0 -1
- package/skills/ae-analysis/references/datatable_influence_list.md +0 -1
- package/skills/ae-analysis/references/datatable_version_get.md +0 -1
- package/skills/ae-analysis/references/datatable_version_list.md +0 -1
- package/skills/ae-analysis/references/debug_device_add.md +1 -2
- package/skills/ae-analysis/references/drilldown_entities_export.md +3 -3
- package/skills/ae-analysis/references/drilldown_events_export.md +3 -2
- package/skills/ae-analysis/references/drilldown_user_events_export.md +2 -2
- package/skills/ae-analysis/references/entity_detail_export.md +3 -2
- package/skills/ae-analysis/references/entity_detail_run.md +1 -0
- package/skills/ae-analysis/references/event_blacklist_add.md +5 -7
- package/skills/ae-analysis/references/event_blacklist_list.md +4 -6
- package/skills/ae-analysis/references/event_blacklist_update.md +6 -8
- package/skills/ae-analysis/references/event_changelog_list.md +0 -1
- package/skills/ae-analysis/references/event_create.md +0 -1
- package/skills/ae-analysis/references/event_detail_export.md +3 -2
- package/skills/ae-analysis/references/event_detail_run.md +1 -0
- package/skills/ae-analysis/references/event_export.md +0 -1
- package/skills/ae-analysis/references/event_get.md +0 -1
- package/skills/ae-analysis/references/event_hide_update.md +0 -1
- package/skills/ae-analysis/references/event_influence_list.md +0 -1
- package/skills/ae-analysis/references/event_list.md +0 -1
- package/skills/ae-analysis/references/event_property_bundle_export.md +5 -14
- package/skills/ae-analysis/references/event_property_bundle_import.md +2 -6
- package/skills/ae-analysis/references/event_relation_update.md +0 -1
- package/skills/ae-analysis/references/event_update.md +0 -1
- package/skills/ae-analysis/references/exchange_config_update.md +0 -1
- package/skills/ae-analysis/references/exchange_rate_refresh.md +0 -1
- package/skills/ae-analysis/references/exchange_rule_list.md +0 -1
- package/skills/ae-analysis/references/exchange_rule_update.md +0 -1
- package/skills/ae-analysis/references/exchange_rule_validate.md +0 -1
- package/skills/ae-analysis/references/governance_recommendation_decisions.md +23 -0
- package/skills/ae-analysis/references/governance_recommendation_export.md +108 -0
- package/skills/ae-analysis/references/governance_recommendation_submit.md +41 -0
- package/skills/ae-analysis/references/history_tag_data_drilldown_export.md +4 -4
- package/skills/ae-analysis/references/history_tag_data_export.md +3 -3
- package/skills/ae-analysis/references/ingest_error_list.md +7 -9
- package/skills/ae-analysis/references/ingest_summary.md +6 -8
- package/skills/ae-analysis/references/live_data_export.md +10 -10
- package/skills/ae-analysis/references/live_data_list.md +7 -9
- package/skills/ae-analysis/references/metadata_resolution.md +78 -0
- package/skills/ae-analysis/references/metric_export.md +0 -1
- package/skills/ae-analysis/references/metric_get.md +0 -1
- package/skills/ae-analysis/references/metric_list.md +4 -5
- package/skills/ae-analysis/references/metric_update.md +0 -1
- package/skills/ae-analysis/references/operation_record_export.md +4 -5
- package/skills/ae-analysis/references/operation_record_list.md +4 -5
- package/skills/ae-analysis/references/personal_semantic_preference_list.md +18 -1
- package/skills/ae-analysis/references/plan_change_log_export.md +10 -10
- package/skills/ae-analysis/references/plan_change_log_list.md +4 -6
- package/skills/ae-analysis/references/plan_delete_items.md +2 -4
- package/skills/ae-analysis/references/plan_export.md +9 -9
- package/skills/ae-analysis/references/plan_generate.md +2 -4
- package/skills/ae-analysis/references/plan_get.md +4 -6
- package/skills/ae-analysis/references/plan_import_excel.md +6 -8
- package/skills/ae-analysis/references/plan_save_items.md +2 -4
- package/skills/ae-analysis/references/plan_sync_from_meta.md +4 -6
- package/skills/ae-analysis/references/project_access_detail_get.md +0 -1
- package/skills/ae-analysis/references/project_data_power_get.md +0 -1
- package/skills/ae-analysis/references/project_data_power_list.md +0 -1
- package/skills/ae-analysis/references/project_data_power_upsert.md +0 -1
- package/skills/ae-analysis/references/project_entity_create.md +0 -1
- package/skills/ae-analysis/references/project_entity_event_list.md +0 -1
- package/skills/ae-analysis/references/project_entity_get.md +0 -1
- package/skills/ae-analysis/references/project_entity_list.md +0 -1
- package/skills/ae-analysis/references/project_entity_update.md +0 -1
- package/skills/ae-analysis/references/project_function_list.md +0 -1
- package/skills/ae-analysis/references/project_info_get.md +0 -1
- package/skills/ae-analysis/references/project_info_list.md +0 -1
- package/skills/ae-analysis/references/project_info_update.md +0 -1
- package/skills/ae-analysis/references/project_mark_time_create.md +0 -1
- package/skills/ae-analysis/references/project_mark_time_list.md +0 -1
- package/skills/ae-analysis/references/project_mark_time_update.md +0 -1
- package/skills/ae-analysis/references/project_member_add.md +6 -5
- package/skills/ae-analysis/references/project_member_batch_update.md +0 -1
- package/skills/ae-analysis/references/project_member_candidate_list.md +4 -3
- package/skills/ae-analysis/references/project_member_handover_run.md +2 -3
- package/skills/ae-analysis/references/project_member_list.md +0 -1
- package/skills/ae-analysis/references/project_member_receiver_list.md +0 -1
- package/skills/ae-analysis/references/project_member_update.md +0 -1
- package/skills/ae-analysis/references/project_owner_update.md +0 -1
- package/skills/ae-analysis/references/project_permission_binding_list.md +0 -1
- package/skills/ae-analysis/references/project_role_function_list.md +0 -1
- package/skills/ae-analysis/references/project_role_get.md +0 -1
- package/skills/ae-analysis/references/project_role_list.md +0 -1
- package/skills/ae-analysis/references/project_role_upsert.md +32 -2
- package/skills/ae-analysis/references/project_role_user_list.md +0 -1
- package/skills/ae-analysis/references/project_semantic_knowledge_wiki.md +214 -0
- package/skills/ae-analysis/references/project_semantic_knowledge_wiki_plan_schema.md +93 -0
- package/skills/ae-analysis/references/project_timezone_get.md +0 -1
- package/skills/ae-analysis/references/project_timezone_overview.md +0 -1
- package/skills/ae-analysis/references/project_timezone_update.md +0 -1
- package/skills/ae-analysis/references/project_user_id_items_update.md +0 -1
- package/skills/ae-analysis/references/property_changelog_list.md +0 -1
- package/skills/ae-analysis/references/property_create.md +0 -1
- package/skills/ae-analysis/references/property_export.md +0 -1
- package/skills/ae-analysis/references/property_get.md +0 -1
- package/skills/ae-analysis/references/property_hide_update.md +0 -1
- package/skills/ae-analysis/references/property_influence_list.md +0 -1
- package/skills/ae-analysis/references/property_list.md +3 -4
- package/skills/ae-analysis/references/property_related_events.md +0 -1
- package/skills/ae-analysis/references/property_relation_update.md +0 -1
- package/skills/ae-analysis/references/property_update.md +0 -1
- package/skills/ae-analysis/references/report_create.md +4 -2
- package/skills/ae-analysis/references/report_data_export.md +11 -9
- package/skills/ae-analysis/references/report_data_run.md +14 -7
- package/skills/ae-analysis/references/report_get.md +5 -3
- package/skills/ae-analysis/references/report_list.md +2 -0
- package/skills/ae-analysis/references/report_update.md +5 -3
- package/skills/ae-analysis/references/rule_create.md +5 -6
- package/skills/ae-analysis/references/rule_delete.md +5 -5
- package/skills/ae-analysis/references/rule_list.md +3 -4
- package/skills/ae-analysis/references/rule_schema.md +3 -4
- package/skills/ae-analysis/references/rule_update.md +5 -6
- package/skills/ae-analysis/references/sdk_sample_generate.md +2 -4
- package/skills/ae-analysis/references/sql_table_columns.md +1 -1
- package/skills/ae-analysis/references/super_metadata_batch_create.md +1 -1
- package/skills/ae-analysis/references/super_metadata_batch_edit.md +1 -1
- package/skills/ae-analysis/references/system_member_add.md +1 -2
- package/skills/ae-analysis/references/system_member_status_update.md +1 -1
- package/skills/ae-analysis/references/system_ops_alert_contact_list.md +1 -1
- package/skills/ae-analysis/references/system_ops_alert_contact_test.md +0 -1
- package/skills/ae-analysis/references/system_query_monitor_overview.md +3 -3
- package/skills/ae-analysis/references/system_query_task_export.md +4 -14
- package/skills/ae-analysis/references/system_query_task_get.md +1 -1
- package/skills/ae-analysis/references/system_query_task_list.md +5 -6
- package/skills/ae-analysis/references/system_receiver_address_upsert.md +3 -3
- package/skills/ae-analysis/references/system_receiver_detection_get.md +1 -1
- package/skills/ae-analysis/references/system_third_party_login_disable.md +1 -1
- package/skills/ae-analysis/references/system_usage_trend_export.md +3 -12
- package/skills/ae-analysis/references/user_cluster_list.md +1 -1
- package/skills/ae-analysis/references/user_cluster_member_export.md +4 -4
- package/skills/ae-analysis/references/user_tag_list.md +1 -1
- package/skills/ae-analysis/references/user_tag_member_export.md +4 -4
- package/skills/ae-analysis/references/virtual_event_create.md +10 -5
- package/skills/ae-analysis/references/virtual_event_get.md +0 -1
- package/skills/ae-analysis/references/virtual_property_create.md +0 -1
- package/skills/ae-analysis/references/virtual_property_sql_rule_update.md +0 -1
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/build-project-semantic-wiki.mjs +1054 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/company-kb.mjs +112 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/default-compile-rules.md +30 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/generate-build-ir.mjs +2735 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/package-wiki-source-zip.mjs +376 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/plan-kb-source-sync.mjs +264 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/precompiled-source.mjs +49 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/upload-kb-sources-concurrently.mjs +200 -0
- package/skills/ae-analysis/scripts/read_results.py +197 -0
- package/skills/ae-analysis-global/SKILL.md +1 -1
- package/skills/ae-capability/SKILL.md +1 -1
- package/skills/ae-community/SKILL.md +1 -1
- package/skills/ae-current-context/SKILL.md +53 -0
- package/skills/ae-data-integration/SKILL.md +5 -4
- package/skills/ae-data-integration/references/lark-bitable-source.md +288 -0
- package/skills/ae-data-integration/references/lark-sheet-source.md +130 -0
- package/skills/ae-data-integration/references/manual-export-source.md +83 -0
- package/skills/ae-data-integration/references/reuse.md +2 -0
- package/skills/ae-data-integration/references/sink-upload.md +32 -0
- package/skills/ae-data-integration/references/tracking-plan.md +4 -1
- package/skills/ae-data-integration/references/ue-mapping.md +2 -2
- package/skills/ae-data-integration-helper/SKILL.md +5 -5
- package/skills/ae-data-integration-helper/references/android_sdk_faq.md +3 -3
- package/skills/ae-data-integration-helper/references/c_sdk_faq.md +3 -3
- package/skills/ae-data-integration-helper/references/cocoscreator_sdk_faq.md +1 -1
- package/skills/ae-data-integration-helper/references/cpp_server_sdk_faq.md +3 -3
- package/skills/ae-data-integration-helper/references/ios_sdk_faq.md +1 -1
- package/skills/ae-data-integration-helper/references/java_sdk_faq.md +3 -3
- package/skills/ae-data-integration-helper/references/javascript_sdk_faq.md +1 -1
- package/skills/ae-data-integration-helper/references/logbus2_guide.md +1 -1
- package/skills/ae-data-integration-helper/references/logbus2_parser_plugin.md +2 -2
- package/skills/ae-data-integration-helper/references/minigame_sdk_faq.md +2 -2
- package/skills/ae-data-integration-helper/references/miniprogram_sdk_faq.md +1 -1
- package/skills/ae-data-integration-helper/references/python_sdk_faq.md +2 -2
- package/skills/ae-data-integration-helper/references/restful_api_notes.md +2 -2
- package/skills/ae-data-integration-helper/references/sdk_log_guide.md +3 -3
- package/skills/ae-data-integration-helper/references/sdk_usage_notes.md +11 -11
- package/skills/ae-data-integration-helper/references/unity_sdk_faq.md +1 -1
- package/skills/ae-dataops/SKILL.md +1 -1
- package/skills/ae-engage/SKILL.md +4 -3
- package/skills/ae-engage/references/build-task-save-guide.md +3 -0
- package/skills/ae-engage/references/flow-metric-update.md +115 -1
- package/skills/ae-engage/references/save-flow.md +3 -0
- package/skills/ae-engage/references/save-task.md +21 -0
- package/skills/ae-engage/references/task-metric-update.md +151 -0
- package/skills/ae-experiment/SKILL.md +14 -7
- package/skills/ae-experiment/references/save_submit_external_experiment.md +52 -0
- package/skills/ae-experiment-design/SKILL.md +3 -3
- package/skills/ae-experiment-design/references/platform-operations.md +1 -1
- package/skills/ae-experiment-insight/SKILL.md +2 -2
- package/skills/ae-experiment-insight/references/platform-operations.md +1 -1
- package/skills/ae-generate-tracking-code/SKILL.md +2 -1
- package/skills/ae-generate-tracking-code/references/client-sdk-insert.md +1 -1
- package/skills/ae-generate-tracking-code/references/datax-config.md +1 -1
- package/skills/ae-generate-tracking-code/references/logbus-config.md +1 -1
- package/skills/ae-generate-tracking-code/references/modes.md +1 -1
- package/skills/ae-generate-tracking-code/references/server-sdk-insert.md +5 -5
- package/skills/ae-generate-tracking-code/references/snippet-delivery.md +3 -3
- package/skills/ae-generate-tracking-plan/SKILL.md +2 -2
- package/skills/ae-generate-tracking-plan/references/te-api.md +1 -0
- package/skills/ae-generate-tracking-plan/references/xlsx-schema.md +3 -2
- package/skills/ae-kb/SKILL.md +41 -2
- package/skills/ae-kb/references/analysis-workflow.md +292 -0
- package/skills/ae-kb/references/source-mutations.md +95 -0
- package/skills/ae-kb-discovery/SKILL.md +5 -1
- package/skills/ae-metadata/SKILL.md +1 -1
- package/skills/ae-migrate-tracking-code/SKILL.md +195 -0
- package/skills/ae-migrate-tracking-code/references/ae-preset-properties.md +76 -0
- package/skills/ae-migrate-tracking-code/references/ir.md +167 -0
- package/skills/ae-migrate-tracking-code/references/mapping-framework.md +112 -0
- package/skills/ae-migrate-tracking-code/references/providers/README.md +58 -0
- package/skills/ae-migrate-tracking-code/references/providers/amplitude.md +208 -0
- package/skills/ae-migrate-tracking-code/references/providers/firebase.md +160 -0
- package/skills/ae-migrate-tracking-code/references/providers/ga4.md +92 -0
- package/skills/ae-migrate-tracking-code/references/providers/mixpanel.md +150 -0
- package/skills/ae-migrate-tracking-code/references/providers/sensors-data.md +146 -0
- package/skills/ae-project-semantic/SKILL.md +1 -1
- package/skills/ae-system/SKILL.md +4 -4
- package/skills/ae-team/SKILL.md +2 -2
- package/skills/ae-use-agent/references/local-agent.md +1 -1
- package/dist/chunk-TAL6CZH6.js +0 -72
- package/skills/ae-analysis/metadata_resolution.md +0 -184
package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/package-wiki-source-zip.mjs
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { normalizeSourceForHash } from './precompiled-source.mjs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { createRequire } from 'node:module';
|
|
6
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
7
|
+
|
|
8
|
+
const args = parseArgs(process.argv.slice(2));
|
|
9
|
+
const sourceDir = path.resolve(required('source-dir'));
|
|
10
|
+
const sourceRoot = fs.realpathSync(sourceDir);
|
|
11
|
+
const treeOutput = path.resolve(args['tree-output'] || `${sourceDir}-source-tree`);
|
|
12
|
+
const outputArchive = args.output ? path.resolve(args.output) : '';
|
|
13
|
+
const previousManifestPath = args['previous-manifest'] ? path.resolve(args['previous-manifest']) : '';
|
|
14
|
+
const manifestOutput = path.resolve(args['manifest-output'] || path.join(treeOutput, 'kb-source-tree-manifest.json'));
|
|
15
|
+
const force = Boolean(args.force);
|
|
16
|
+
const rootPath = normalizeRootPath(args['root-path'] || 'sources');
|
|
17
|
+
|
|
18
|
+
if (!outputArchive && !previousManifestPath) throw new Error('--output or --previous-manifest is required.');
|
|
19
|
+
assertOutputPath(treeOutput, sourceRoot, 'Tree output');
|
|
20
|
+
if (outputArchive) assertOutputPath(outputArchive, sourceRoot, 'Archive');
|
|
21
|
+
if (manifestOutput.startsWith(`${sourceRoot}${path.sep}`)) throw new Error('Manifest output must not be nested inside the flat source directory.');
|
|
22
|
+
|
|
23
|
+
const flatManifest = readManifest(path.join(sourceRoot, 'kb-upload-manifest.json'), { allowFlat: true });
|
|
24
|
+
const next = buildSourceTreeManifest(flatManifest, { requireLocalContent: true });
|
|
25
|
+
const entries = buildSourceTreeEntries(next);
|
|
26
|
+
|
|
27
|
+
materializeTree(treeOutput, force, (staging) => {
|
|
28
|
+
for (const entry of entries) writeText(path.join(staging, entry.path), entry.content);
|
|
29
|
+
});
|
|
30
|
+
writeJson(manifestOutput, next, force);
|
|
31
|
+
|
|
32
|
+
const result = {
|
|
33
|
+
manifest_kind: next.manifest_kind,
|
|
34
|
+
namespace: next.namespace,
|
|
35
|
+
root_path: next.root_path,
|
|
36
|
+
source_count: next.source_count,
|
|
37
|
+
tree_output: treeOutput,
|
|
38
|
+
manifest: manifestOutput,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
if (previousManifestPath) {
|
|
42
|
+
const previous = buildSourceTreeManifest(readManifest(previousManifestPath, { allowFlat: true, allowTree: true }), { requireLocalContent: false });
|
|
43
|
+
if (previous.namespace !== next.namespace || previous.semantic_project_id !== next.semantic_project_id) {
|
|
44
|
+
throw new Error('Wiki namespace/project changed; stop.');
|
|
45
|
+
}
|
|
46
|
+
const before = new Map(previous.sources.map((source) => [source.file, source]));
|
|
47
|
+
const after = new Map(next.sources.map((source) => [source.file, source]));
|
|
48
|
+
const actions = [];
|
|
49
|
+
const unchanged = [];
|
|
50
|
+
for (const source of next.sources) {
|
|
51
|
+
const old = before.get(source.file);
|
|
52
|
+
if (old?.content_hash === source.content_hash) unchanged.push(source.file);
|
|
53
|
+
else actions.push({
|
|
54
|
+
action: old ? 'replace' : 'add',
|
|
55
|
+
path: source.file,
|
|
56
|
+
file: path.join(treeOutput, source.file),
|
|
57
|
+
source_kind: source.source_kind,
|
|
58
|
+
asset_type: source.asset_type,
|
|
59
|
+
asset_key: source.asset_key,
|
|
60
|
+
content_hash: source.content_hash,
|
|
61
|
+
previous_content_hash: old?.content_hash ?? null,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
for (const source of previous.sources) {
|
|
65
|
+
if (!after.has(source.file)) actions.push({
|
|
66
|
+
action: 'remove',
|
|
67
|
+
path: source.file,
|
|
68
|
+
source_kind: source.source_kind,
|
|
69
|
+
asset_type: source.asset_type,
|
|
70
|
+
asset_key: source.asset_key,
|
|
71
|
+
previous_content_hash: source.content_hash,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
Object.assign(result, { actions, unchanged, compile_mode: actions.length ? 'incremental' : 'skip' });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (outputArchive) {
|
|
78
|
+
if (fs.existsSync(outputArchive) && !force) throw new Error('Archive already exists. Pass --force to replace it.');
|
|
79
|
+
const archiveEntries = next.sources.map((source) => ({
|
|
80
|
+
name: source.file,
|
|
81
|
+
content: fs.readFileSync(path.join(treeOutput, source.file)),
|
|
82
|
+
})).sort((a, b) => a.name.localeCompare(b.name, 'en'));
|
|
83
|
+
await writeZip(outputArchive, archiveEntries);
|
|
84
|
+
Object.assign(result, { archive: outputArchive, archive_bytes: fs.statSync(outputArchive).size });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log(JSON.stringify(result, null, 2));
|
|
88
|
+
|
|
89
|
+
function buildSourceTreeManifest(manifest, options) {
|
|
90
|
+
if (manifest.manifest_kind === 'ae_project_semantic_kb_source_tree') return validateTreeManifest(manifest);
|
|
91
|
+
|
|
92
|
+
const flatSources = manifest.sources.map((source) => normalizeFlatSource(manifest, source, options.requireLocalContent));
|
|
93
|
+
const flatToTree = new Map(flatSources.map((source) => [source.display_name, sourceTreePath(source)]));
|
|
94
|
+
const generated = flatSources.map((source) => {
|
|
95
|
+
const content = options.requireLocalContent
|
|
96
|
+
? rewriteLinksForTree(readText(path.join(sourceRoot, source.file)), source.display_name, flatToTree)
|
|
97
|
+
: null;
|
|
98
|
+
return {
|
|
99
|
+
display_name: source.display_name,
|
|
100
|
+
file: flatToTree.get(source.display_name),
|
|
101
|
+
namespace: manifest.namespace,
|
|
102
|
+
snapshot_date: manifest.snapshot_date ?? null,
|
|
103
|
+
snapshot_hash: manifest.snapshot_hash,
|
|
104
|
+
source_kind: source.source_kind,
|
|
105
|
+
asset_type: source.asset_type,
|
|
106
|
+
asset_key: source.asset_key,
|
|
107
|
+
title: source.title,
|
|
108
|
+
content_hash: content == null ? source.content_hash : sha256(normalizeContentForHash(content)),
|
|
109
|
+
source_path: source.source_path,
|
|
110
|
+
managed_by: 'project-semantic-kb-source-tree',
|
|
111
|
+
};
|
|
112
|
+
});
|
|
113
|
+
const readmes = sourceDirectoryReadmes(manifest).map((entry) => ({
|
|
114
|
+
display_name: entry.path,
|
|
115
|
+
file: entry.path,
|
|
116
|
+
namespace: manifest.namespace,
|
|
117
|
+
snapshot_date: manifest.snapshot_date ?? null,
|
|
118
|
+
snapshot_hash: manifest.snapshot_hash,
|
|
119
|
+
source_kind: 'filing-guide',
|
|
120
|
+
asset_type: null,
|
|
121
|
+
asset_key: null,
|
|
122
|
+
content_hash: sha256(normalizeContentForHash(entry.content)),
|
|
123
|
+
source_path: entry.path,
|
|
124
|
+
managed_by: 'project-semantic-kb-source-tree',
|
|
125
|
+
}));
|
|
126
|
+
const sources = [...readmes, ...generated].sort((a, b) => a.file.localeCompare(b.file, 'en'));
|
|
127
|
+
assertUnique(sources.map((source) => source.file), 'source tree path');
|
|
128
|
+
return {
|
|
129
|
+
schema_version: '1.1',
|
|
130
|
+
manifest_kind: 'ae_project_semantic_kb_source_tree',
|
|
131
|
+
namespace: manifest.namespace,
|
|
132
|
+
semantic_project_id: manifest.semantic_project_id,
|
|
133
|
+
project_name: manifest.project_name ?? null,
|
|
134
|
+
root_path: rootPath,
|
|
135
|
+
snapshot_date: manifest.snapshot_date ?? null,
|
|
136
|
+
snapshot_hash: manifest.snapshot_hash ?? null,
|
|
137
|
+
source_count: sources.length,
|
|
138
|
+
generated_source_count: generated.length,
|
|
139
|
+
filing_guide_count: readmes.length,
|
|
140
|
+
sources,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function buildSourceTreeEntries(manifest) {
|
|
145
|
+
const flatToTree = new Map(manifest.sources
|
|
146
|
+
.filter((item) => item.source_kind !== 'filing-guide')
|
|
147
|
+
.map((item) => [item.display_name, item.file]));
|
|
148
|
+
const guides = new Map(sourceDirectoryReadmes(manifest).map((entry) => [entry.path, entry.content]));
|
|
149
|
+
return manifest.sources.map((source) => {
|
|
150
|
+
if (source.source_kind === 'filing-guide') {
|
|
151
|
+
const content = guides.get(source.file);
|
|
152
|
+
if (!content) throw new Error(`Missing filing guide content for ${source.file}.`);
|
|
153
|
+
return { path: source.file, content };
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
path: source.file,
|
|
157
|
+
content: rewriteLinksForTree(readText(path.join(sourceRoot, source.display_name)), source.display_name, flatToTree),
|
|
158
|
+
};
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function sourceDirectoryReadmes(manifest) {
|
|
163
|
+
const project = clean(manifest.project_name) || `Project ${manifest.semantic_project_id}`;
|
|
164
|
+
const lines = [
|
|
165
|
+
[`${rootPath}/README.md`, `# Source Directory\n\nThis directory is the writable source space for ${project} project knowledge. README files are filing guides only; they are not business evidence.\n\nPut source material by nature. CLI-managed asset facts live under assets/. Human context such as project background, meetings, decisions, corrections, and references must not be removed by an asset refresh.\n\nThe expected compiled Wiki should be organized for consumption: index.md, wiki/project/, wiki/domains/, wiki/semantics/, wiki/assets/, wiki/decisions/, and wiki/review/.\n`],
|
|
166
|
+
[`${rootPath}/project/README.md`, '# Project Sources\n\nBackground, goals, business scope, terminology, and ownership notes. This guide is not evidence.\n'],
|
|
167
|
+
[`${rootPath}/assets/README.md`, '# Asset Sources\n\nCLI-managed structured asset facts. Refresh may change files owned by the project semantic asset package only.\n'],
|
|
168
|
+
[`${rootPath}/assets/dashboards/README.md`, '# Dashboard Asset Sources\n\nDashboard facts exported by CLI.\n'],
|
|
169
|
+
[`${rootPath}/assets/reports/README.md`, '# Report Asset Sources\n\nReport facts exported by CLI, including calculation, filters, parameters, SQL, provenance, and authority status when available.\n'],
|
|
170
|
+
[`${rootPath}/assets/metrics/README.md`, '# Metric Asset Sources\n\nReusable metric facts exported by CLI.\n'],
|
|
171
|
+
[`${rootPath}/assets/metadata/README.md`, '# Metadata Asset Sources\n\nEvents, properties, tags, cohorts, and other selectable metadata facts exported by CLI.\n'],
|
|
172
|
+
[`${rootPath}/business/README.md`, '# Business Sources\n\nBusiness rules, metric definitions, domain context, process notes, and user-facing question patterns.\n'],
|
|
173
|
+
[`${rootPath}/meetings/README.md`, '# Meeting Sources\n\nMeeting notes and discussion records. They can provide context, but do not override confirmed decisions by recency alone.\n'],
|
|
174
|
+
[`${rootPath}/decisions/README.md`, '# Decision Sources\n\nConfirmed decisions must state confirmer, status, date, and applicable scope.\n'],
|
|
175
|
+
[`${rootPath}/corrections/README.md`, '# Correction Sources\n\nCorrections must identify the target material, corrected content, reason, date, and applicable scope.\n'],
|
|
176
|
+
[`${rootPath}/references/README.md`, '# Reference Sources\n\nSupporting documents, external explanations, source containers, appendices, and audit material.\n'],
|
|
177
|
+
];
|
|
178
|
+
return lines.map(([pathValue, content]) => ({ path: pathValue, content }));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function sourceTreePath(source) {
|
|
182
|
+
const base = sourceTreeBaseName(source);
|
|
183
|
+
const kind = source.source_kind;
|
|
184
|
+
const assetType = source.asset_type;
|
|
185
|
+
if (assetType === 'dashboard') return `${rootPath}/assets/dashboards/${base}`;
|
|
186
|
+
if (assetType === 'report') return `${rootPath}/assets/reports/${base}`;
|
|
187
|
+
if (assetType === 'metric') return `${rootPath}/assets/metrics/${base}`;
|
|
188
|
+
if (assetType === 'metadata' || kind === 'metadata') return `${rootPath}/assets/metadata/${base}`;
|
|
189
|
+
if (kind === 'domain' || kind === 'recall-card') return `${rootPath}/business/${base}`;
|
|
190
|
+
if (kind === 'index' || kind === 'manifest') return `${rootPath}/project/${base}`;
|
|
191
|
+
if (kind === 'governance') return `${rootPath}/references/governance/${base}`;
|
|
192
|
+
if (kind === 'appendix' || kind === 'source-container') return `${rootPath}/references/${base}`;
|
|
193
|
+
return `${rootPath}/references/${base}`;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function sourceTreeBaseName(source) {
|
|
197
|
+
const original = path.posix.basename(source.file);
|
|
198
|
+
if (!source.asset_key) return original;
|
|
199
|
+
const titlePart = slug(clean(source.title));
|
|
200
|
+
const keyPart = slug(clean(source.asset_key));
|
|
201
|
+
const prefix = `${clean(source.namespace)}-${clean(source.asset_type || source.source_kind)}`;
|
|
202
|
+
const stem = [prefix, titlePart, keyPart].filter(Boolean).join('-');
|
|
203
|
+
if (!titlePart || original.includes(`-${titlePart}-`)) return original;
|
|
204
|
+
return `${stem.length <= 150 ? stem : `${stem.slice(0, 125)}-${sha256(stem).slice(0, 16)}`}.md`;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function slug(value) {
|
|
208
|
+
return clean(value).normalize('NFKC').toLowerCase().replace(/[^\p{L}\p{N}._-]+/gu, '-').replace(/^-+|-+$/g, '').slice(0, 120);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function rewriteLinksForTree(content, currentFlatName, flatToTree) {
|
|
212
|
+
const currentTreePath = flatToTree.get(currentFlatName);
|
|
213
|
+
if (!currentTreePath) return content;
|
|
214
|
+
return content.replace(/\[([^\]]*)\]\(([^)]+)\)/g, (match, label, target) => {
|
|
215
|
+
const [targetPath, fragment = ''] = String(target).split('#');
|
|
216
|
+
if (!targetPath || /^(https?:|mailto:)/.test(targetPath)) return match;
|
|
217
|
+
const treeTarget = flatToTree.get(decodeURIComponent(targetPath));
|
|
218
|
+
if (!treeTarget) return match;
|
|
219
|
+
const relative = path.posix.relative(path.posix.dirname(currentTreePath), treeTarget) || path.posix.basename(treeTarget);
|
|
220
|
+
return `[${label}](${relative}${fragment ? `#${fragment}` : ''})`;
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function readManifest(file, options) {
|
|
225
|
+
const manifest = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
226
|
+
const kind = manifest.manifest_kind;
|
|
227
|
+
if (kind === 'ae_project_semantic_kb_upload_sources' && options.allowFlat) return validateFlatManifest(manifest);
|
|
228
|
+
if (kind === 'ae_project_semantic_kb_source_tree' && options.allowTree) return validateTreeManifest(manifest);
|
|
229
|
+
throw new Error(`Unsupported manifest kind: ${kind || '<missing>'}.`);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function validateFlatManifest(manifest) {
|
|
233
|
+
if (!manifest.namespace || !Array.isArray(manifest.sources)) throw new Error('Invalid Wiki upload manifest.');
|
|
234
|
+
const seen = new Set();
|
|
235
|
+
for (const source of manifest.sources) {
|
|
236
|
+
normalizeFlatSource(manifest, source, false);
|
|
237
|
+
if (seen.has(source.file)) throw new Error('Duplicate flat source file.');
|
|
238
|
+
seen.add(source.file);
|
|
239
|
+
}
|
|
240
|
+
if (!seen.size) throw new Error('No Wiki sources.');
|
|
241
|
+
return manifest;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function normalizeFlatSource(manifest, source, requireLocalFile) {
|
|
245
|
+
const name = source.file;
|
|
246
|
+
if (typeof name !== 'string' || name !== source.display_name || !name.startsWith(`${manifest.namespace}-`)
|
|
247
|
+
|| !name.endsWith('.md') || /[\\/\x00-\x1f]/.test(name) || !/^[a-f0-9]{64}$/i.test(source.content_hash)) {
|
|
248
|
+
throw new Error('Invalid Wiki source identity/hash.');
|
|
249
|
+
}
|
|
250
|
+
if (requireLocalFile) {
|
|
251
|
+
const file = fs.realpathSync(path.join(sourceRoot, name));
|
|
252
|
+
if (!file.startsWith(`${sourceRoot}${path.sep}`)) throw new Error('Source escapes the Wiki directory.');
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
...source,
|
|
256
|
+
namespace: clean(source.namespace) || manifest.namespace,
|
|
257
|
+
source_kind: clean(source.source_kind) || 'wiki-page',
|
|
258
|
+
asset_type: clean(source.asset_type) || null,
|
|
259
|
+
asset_key: clean(source.asset_key) || null,
|
|
260
|
+
title: clean(source.title) || clean(source.display_name).replace(/\.md$/i, ''),
|
|
261
|
+
source_path: clean(source.source_path),
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function validateTreeManifest(manifest) {
|
|
266
|
+
if (!manifest.namespace || !Array.isArray(manifest.sources) || clean(manifest.root_path) !== rootPath) {
|
|
267
|
+
throw new Error('Invalid source tree manifest.');
|
|
268
|
+
}
|
|
269
|
+
const seen = new Set();
|
|
270
|
+
for (const source of manifest.sources) {
|
|
271
|
+
if (typeof source.file !== 'string' || !source.file.startsWith(`${rootPath}/`) || !source.file.endsWith('.md')
|
|
272
|
+
|| source.file.includes('\\') || source.file.split('/').some((part) => !part || part === '.' || part === '..')
|
|
273
|
+
|| !/^[a-f0-9]{64}$/i.test(source.content_hash) || seen.has(source.file)) {
|
|
274
|
+
throw new Error('Invalid or duplicate source tree path/hash.');
|
|
275
|
+
}
|
|
276
|
+
seen.add(source.file);
|
|
277
|
+
}
|
|
278
|
+
return manifest;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function normalizeContentForHash(content) { return normalizeSourceForHash(String(content).replace(/\r\n/g, '\n')); }
|
|
282
|
+
|
|
283
|
+
function parseArgs(tokens) {
|
|
284
|
+
const parsed = {};
|
|
285
|
+
for (let i = 0; i < tokens.length; i += 1) {
|
|
286
|
+
const key = tokens[i];
|
|
287
|
+
if (!key.startsWith('--')) throw new Error(`Invalid argument: ${key}`);
|
|
288
|
+
const name = key.slice(2);
|
|
289
|
+
if (name === 'force') {
|
|
290
|
+
parsed[name] = true;
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
const value = tokens[++i];
|
|
294
|
+
if (!value || value.startsWith('--')) throw new Error(`Missing value for ${key}.`);
|
|
295
|
+
parsed[name] = value;
|
|
296
|
+
}
|
|
297
|
+
return parsed;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function required(name) {
|
|
301
|
+
const value = args[name];
|
|
302
|
+
if (!value) throw new Error(`--${name} is required.`);
|
|
303
|
+
return value;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function normalizeRootPath(value) {
|
|
307
|
+
const normalized = clean(value).replace(/^\/+|\/+$/g, '');
|
|
308
|
+
if (!normalized || normalized.includes('\\') || normalized.split('/').some((part) => !part || part === '.' || part === '..')) {
|
|
309
|
+
throw new Error('--root-path must be a normalized relative path.');
|
|
310
|
+
}
|
|
311
|
+
return normalized;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function assertOutputPath(target, source, label) {
|
|
315
|
+
if (target === source || target.startsWith(`${source}${path.sep}`)) throw new Error(`${label} must not be nested inside the flat source directory.`);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function assertUnique(values, label) {
|
|
319
|
+
const seen = new Set();
|
|
320
|
+
for (const value of values) {
|
|
321
|
+
if (seen.has(value)) throw new Error(`Duplicate ${label}: ${value}`);
|
|
322
|
+
seen.add(value);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function materializeTree(output, replace, writer) {
|
|
327
|
+
if (fs.existsSync(output) && !replace) throw new Error(`Tree output already exists: ${output}. Pass --force to replace it.`);
|
|
328
|
+
const parent = path.dirname(output);
|
|
329
|
+
fs.mkdirSync(parent, { recursive: true });
|
|
330
|
+
const staging = path.join(parent, `.${path.basename(output)}.staging-${process.pid}-${randomBytes(4).toString('hex')}`);
|
|
331
|
+
const backup = path.join(parent, `.${path.basename(output)}.backup-${process.pid}-${randomBytes(4).toString('hex')}`);
|
|
332
|
+
fs.mkdirSync(staging, { recursive: true });
|
|
333
|
+
try {
|
|
334
|
+
writer(staging);
|
|
335
|
+
if (fs.existsSync(output)) fs.renameSync(output, backup);
|
|
336
|
+
fs.renameSync(staging, output);
|
|
337
|
+
fs.rmSync(backup, { recursive: true, force: true });
|
|
338
|
+
} catch (error) {
|
|
339
|
+
fs.rmSync(staging, { recursive: true, force: true });
|
|
340
|
+
if (!fs.existsSync(output) && fs.existsSync(backup)) fs.renameSync(backup, output);
|
|
341
|
+
throw error;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
async function writeZip(output, files) {
|
|
346
|
+
const parent = path.dirname(output);
|
|
347
|
+
fs.mkdirSync(parent, { recursive: true });
|
|
348
|
+
const temporary = path.join(parent, `.${path.basename(output)}.tmp-${process.pid}-${randomBytes(4).toString('hex')}`);
|
|
349
|
+
const archiver = createRequire(import.meta.url)('archiver');
|
|
350
|
+
await new Promise((resolve, reject) => {
|
|
351
|
+
const stream = fs.createWriteStream(temporary, { flags: 'wx' });
|
|
352
|
+
const zip = typeof archiver === 'function' ? archiver('zip', { zlib: { level: 9 } }) : new archiver.ZipArchive({ zlib: { level: 9 } });
|
|
353
|
+
stream.on('close', resolve);
|
|
354
|
+
stream.on('error', reject);
|
|
355
|
+
zip.on('error', reject);
|
|
356
|
+
zip.pipe(stream);
|
|
357
|
+
for (const file of files) zip.append(file.content, { name: file.name, date: new Date('1980-01-01T00:00:00Z'), mode: 0o600 });
|
|
358
|
+
void zip.finalize();
|
|
359
|
+
});
|
|
360
|
+
if (fs.existsSync(output)) fs.rmSync(output, { force: true });
|
|
361
|
+
fs.renameSync(temporary, output);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function writeText(file, value) {
|
|
365
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
366
|
+
fs.writeFileSync(file, value.endsWith('\n') ? value : `${value}\n`, 'utf8');
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function writeJson(file, value, replace) {
|
|
370
|
+
if (fs.existsSync(file) && !replace) throw new Error(`Manifest output already exists: ${file}. Pass --force to replace it.`);
|
|
371
|
+
writeText(file, JSON.stringify(value, null, 2));
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function readText(file) { return fs.readFileSync(file, 'utf8'); }
|
|
375
|
+
function clean(value) { return value == null ? '' : String(value).trim(); }
|
|
376
|
+
function sha256(value) { return createHash('sha256').update(value).digest('hex'); }
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
|
|
6
|
+
const args = parseArgs(process.argv.slice(2));
|
|
7
|
+
const nextManifestPath = path.resolve(required(args, 'next-manifest'));
|
|
8
|
+
const previousManifestPath = clean(args['previous-manifest']) ? path.resolve(args['previous-manifest']) : null;
|
|
9
|
+
const remoteSourcesPath = clean(args['remote-sources']) ? path.resolve(args['remote-sources']) : null;
|
|
10
|
+
|
|
11
|
+
const nextManifest = readJson(nextManifestPath);
|
|
12
|
+
const previousManifest = previousManifestPath ? readJson(previousManifestPath) : null;
|
|
13
|
+
const remoteSources = remoteSourcesPath ? readJson(remoteSourcesPath) : null;
|
|
14
|
+
const namespace = clean(args.namespace || nextManifest.namespace);
|
|
15
|
+
const fullThreshold = parseRatio(args['full-threshold'], 0.2);
|
|
16
|
+
const maxIncrementalActions = parsePositiveInteger(args['max-incremental-actions'], 50);
|
|
17
|
+
|
|
18
|
+
if (!namespace) fail('A namespace is required. Pass --namespace or use a next manifest with namespace.');
|
|
19
|
+
if (clean(nextManifest.namespace) !== namespace) fail(`Next manifest namespace ${clean(nextManifest.namespace) || '<empty>'} does not match ${namespace}.`);
|
|
20
|
+
if (previousManifest && clean(previousManifest.namespace) !== namespace) {
|
|
21
|
+
fail(`Previous manifest namespace ${clean(previousManifest.namespace) || '<empty>'} does not match ${namespace}.`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const nextSources = sourceMap(nextManifest);
|
|
25
|
+
const previousSources = previousManifest ? sourceMap(previousManifest) : new Map();
|
|
26
|
+
const remoteSourceMap = remoteSources ? listRemoteSources(remoteSources, namespace) : new Map();
|
|
27
|
+
const baselineSources = buildBaselineSources(previousSources, remoteSourceMap, Boolean(previousManifest));
|
|
28
|
+
|
|
29
|
+
const added = [];
|
|
30
|
+
const updated = [];
|
|
31
|
+
const removed = [];
|
|
32
|
+
const unchanged = [];
|
|
33
|
+
|
|
34
|
+
for (const [displayName, source] of nextSources) {
|
|
35
|
+
const previous = baselineSources.get(displayName);
|
|
36
|
+
if (!previous) {
|
|
37
|
+
added.push(addAction(source));
|
|
38
|
+
} else if (previous.content_hash && previous.content_hash === source.content_hash) {
|
|
39
|
+
unchanged.push(unchangedAction(source, previous));
|
|
40
|
+
} else if (previous.content_hash) {
|
|
41
|
+
updated.push(updateAction(source, previous));
|
|
42
|
+
} else if (previousManifest) {
|
|
43
|
+
updated.push(updateAction(source, previous));
|
|
44
|
+
} else {
|
|
45
|
+
added.push(addAction(source));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
for (const [displayName, source] of baselineSources) {
|
|
50
|
+
if (!nextSources.has(displayName)) removed.push(removeAction(source));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const actions = [
|
|
54
|
+
...removed.map((source) => ({ action: 'remove', ...source })),
|
|
55
|
+
...updated.map((source) => ({ action: 'replace', ...source })),
|
|
56
|
+
...added.map((source) => ({ action: 'add', ...source })),
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
const compileDecision = decideCompileMode({
|
|
60
|
+
actionCount: actions.length,
|
|
61
|
+
baselineCount: baselineSources.size,
|
|
62
|
+
nextCount: nextSources.size,
|
|
63
|
+
fullThreshold,
|
|
64
|
+
maxIncrementalActions,
|
|
65
|
+
args,
|
|
66
|
+
});
|
|
67
|
+
process.stdout.write(`${JSON.stringify({
|
|
68
|
+
schema_version: '1.0',
|
|
69
|
+
plan_kind: 'ae_project_semantic_kb_source_sync_plan',
|
|
70
|
+
namespace,
|
|
71
|
+
previous_snapshot_hash: previousManifest?.snapshot_hash ?? null,
|
|
72
|
+
next_snapshot_hash: nextManifest.snapshot_hash ?? null,
|
|
73
|
+
remote_source_count: remoteSourceMap.size,
|
|
74
|
+
counts: {
|
|
75
|
+
added: added.length,
|
|
76
|
+
updated: updated.length,
|
|
77
|
+
removed: removed.length,
|
|
78
|
+
unchanged: unchanged.length,
|
|
79
|
+
},
|
|
80
|
+
change_ratio: compileDecision.changeRatio,
|
|
81
|
+
full_threshold: fullThreshold,
|
|
82
|
+
max_incremental_actions: maxIncrementalActions,
|
|
83
|
+
compile_mode: compileDecision.mode,
|
|
84
|
+
compile_mode_reason: compileDecision.reason,
|
|
85
|
+
requires_schema_force: compileDecision.requiresSchemaForce,
|
|
86
|
+
schema_force_reasons: compileDecision.schemaForceReasons,
|
|
87
|
+
added,
|
|
88
|
+
updated,
|
|
89
|
+
removed,
|
|
90
|
+
unchanged,
|
|
91
|
+
actions,
|
|
92
|
+
}, null, 2)}\n`);
|
|
93
|
+
|
|
94
|
+
function sourceMap(manifest) {
|
|
95
|
+
const values = asArray(manifest.sources);
|
|
96
|
+
const result = new Map();
|
|
97
|
+
for (const value of values) {
|
|
98
|
+
const source = normalizeSource(value);
|
|
99
|
+
if (!source.display_name.startsWith(`${namespace}-`)) fail(`Source ${source.display_name} is outside namespace ${namespace}.`);
|
|
100
|
+
if (result.has(source.display_name)) fail(`Duplicate source display_name: ${source.display_name}.`);
|
|
101
|
+
result.set(source.display_name, source);
|
|
102
|
+
}
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function listRemoteSources(value, sourceNamespace) {
|
|
107
|
+
const rows = Array.isArray(value) ? value : asArray(value.sources || value.data?.sources || value.data?.items || value.items);
|
|
108
|
+
const result = new Map();
|
|
109
|
+
for (const row of rows) {
|
|
110
|
+
const displayName = clean(row.display_name || row.displayName || row.name || row.filename);
|
|
111
|
+
if (!displayName || !displayName.startsWith(`${sourceNamespace}-`)) continue;
|
|
112
|
+
result.set(displayName, {
|
|
113
|
+
display_name: displayName,
|
|
114
|
+
source_id: clean(row.id || row.source_id || row.sourceId) || null,
|
|
115
|
+
content_hash: clean(row.content_hash || row.contentHash) || null,
|
|
116
|
+
source_path: clean(row.source_path || row.sourcePath) || null,
|
|
117
|
+
raw: row,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function buildBaselineSources(previousSources, remoteSources, hasPreviousManifest) {
|
|
124
|
+
if (!hasPreviousManifest) return remoteSources;
|
|
125
|
+
const result = new Map(previousSources);
|
|
126
|
+
for (const [displayName, remote] of remoteSources) {
|
|
127
|
+
const previous = result.get(displayName);
|
|
128
|
+
if (previous) result.set(displayName, { ...previous, source_id: remote.source_id ?? previous.source_id ?? null, remote });
|
|
129
|
+
else result.set(displayName, remote);
|
|
130
|
+
}
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function addAction(source) {
|
|
135
|
+
return {
|
|
136
|
+
display_name: source.display_name,
|
|
137
|
+
file: source.file,
|
|
138
|
+
content_hash: source.content_hash,
|
|
139
|
+
source_path: source.source_path,
|
|
140
|
+
source_kind: source.source_kind,
|
|
141
|
+
asset_type: source.asset_type,
|
|
142
|
+
asset_key: source.asset_key,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function updateAction(source, previous) {
|
|
147
|
+
return {
|
|
148
|
+
...addAction(source),
|
|
149
|
+
previous_content_hash: previous.content_hash ?? null,
|
|
150
|
+
source_id: previous.source_id ?? null,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function removeAction(source) {
|
|
155
|
+
return {
|
|
156
|
+
display_name: source.display_name,
|
|
157
|
+
source_id: source.source_id ?? null,
|
|
158
|
+
previous_content_hash: source.content_hash ?? null,
|
|
159
|
+
source_path: source.source_path ?? null,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function unchangedAction(source, previous) {
|
|
164
|
+
return {
|
|
165
|
+
display_name: source.display_name,
|
|
166
|
+
content_hash: source.content_hash,
|
|
167
|
+
source_id: previous.source_id ?? null,
|
|
168
|
+
source_path: source.source_path,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function normalizeSource(value) {
|
|
173
|
+
const source = asObject(value);
|
|
174
|
+
const displayName = clean(source.display_name || source.displayName);
|
|
175
|
+
if (!displayName) fail('Every manifest source requires display_name.');
|
|
176
|
+
return {
|
|
177
|
+
display_name: displayName,
|
|
178
|
+
file: clean(source.file || source.local_path || source.localPath || displayName),
|
|
179
|
+
content_hash: clean(source.content_hash || source.contentHash),
|
|
180
|
+
source_path: clean(source.source_path || source.sourcePath),
|
|
181
|
+
source_kind: clean(source.source_kind || source.sourceKind),
|
|
182
|
+
asset_type: clean(source.asset_type || source.assetType) || null,
|
|
183
|
+
asset_key: clean(source.asset_key || source.assetKey) || null,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function decideCompileMode({ actionCount, baselineCount, nextCount, fullThreshold, maxIncrementalActions, args: parsedArgs }) {
|
|
188
|
+
const denominator = Math.max(baselineCount, nextCount, 1);
|
|
189
|
+
const changeRatio = Number((actionCount / denominator).toFixed(6));
|
|
190
|
+
if (actionCount === 0) {
|
|
191
|
+
return {
|
|
192
|
+
mode: 'skip',
|
|
193
|
+
reason: 'no_source_changes',
|
|
194
|
+
changeRatio,
|
|
195
|
+
requiresSchemaForce: false,
|
|
196
|
+
schemaForceReasons: [],
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const forceReasons = [];
|
|
201
|
+
if (boolArg(parsedArgs['force-full'])) forceReasons.push('force_full');
|
|
202
|
+
if (boolArg(parsedArgs['semantic-plan-changed'])) forceReasons.push('semantic_plan_changed');
|
|
203
|
+
if (boolArg(parsedArgs['schema-changed'])) forceReasons.push('schema_changed');
|
|
204
|
+
if (boolArg(parsedArgs['compile-guidance-changed'])) forceReasons.push('compile_guidance_changed');
|
|
205
|
+
if (boolArg(parsedArgs['recall-card-contract-changed'])) forceReasons.push('recall_card_contract_changed');
|
|
206
|
+
if (boolArg(parsedArgs['page-taxonomy-changed'])) forceReasons.push('page_taxonomy_changed');
|
|
207
|
+
if (changeRatio > fullThreshold) forceReasons.push('change_ratio_exceeded');
|
|
208
|
+
if (actionCount > maxIncrementalActions) forceReasons.push('max_incremental_actions_exceeded');
|
|
209
|
+
|
|
210
|
+
if (forceReasons.length) {
|
|
211
|
+
return {
|
|
212
|
+
mode: 'full',
|
|
213
|
+
reason: forceReasons[0],
|
|
214
|
+
changeRatio,
|
|
215
|
+
requiresSchemaForce: true,
|
|
216
|
+
schemaForceReasons: forceReasons,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return {
|
|
221
|
+
mode: 'incremental',
|
|
222
|
+
reason: 'small_source_delta',
|
|
223
|
+
changeRatio,
|
|
224
|
+
requiresSchemaForce: false,
|
|
225
|
+
schemaForceReasons: [],
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function parseArgs(values) {
|
|
230
|
+
const out = {};
|
|
231
|
+
for (let i = 0; i < values.length; i += 1) {
|
|
232
|
+
const value = values[i];
|
|
233
|
+
if (!value.startsWith('--')) fail(`Unexpected argument: ${value}`);
|
|
234
|
+
const next = values[i + 1];
|
|
235
|
+
if (next == null || next.startsWith('--')) out[value.slice(2)] = true;
|
|
236
|
+
else out[value.slice(2)] = values[++i];
|
|
237
|
+
}
|
|
238
|
+
return out;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function required(values, key) {
|
|
242
|
+
const value = clean(values[key]);
|
|
243
|
+
if (!value) fail(`--${key} is required.`);
|
|
244
|
+
return value;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function readJson(file) { return JSON.parse(fs.readFileSync(file, 'utf8')); }
|
|
248
|
+
function clean(value) { return value == null ? '' : String(value).trim(); }
|
|
249
|
+
function boolArg(value) { return value === true || clean(value).toLowerCase() === 'true'; }
|
|
250
|
+
function parseRatio(value, defaultValue) {
|
|
251
|
+
if (!clean(value)) return defaultValue;
|
|
252
|
+
const parsed = Number(value);
|
|
253
|
+
if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) fail('--full-threshold must be a number between 0 and 1.');
|
|
254
|
+
return parsed;
|
|
255
|
+
}
|
|
256
|
+
function parsePositiveInteger(value, defaultValue) {
|
|
257
|
+
if (!clean(value)) return defaultValue;
|
|
258
|
+
const parsed = Number(value);
|
|
259
|
+
if (!Number.isInteger(parsed) || parsed < 1) fail('--max-incremental-actions must be a positive integer.');
|
|
260
|
+
return parsed;
|
|
261
|
+
}
|
|
262
|
+
function asArray(value) { return Array.isArray(value) ? value : []; }
|
|
263
|
+
function asObject(value) { return value && typeof value === 'object' && !Array.isArray(value) ? value : {}; }
|
|
264
|
+
function fail(message) { process.stderr.write(`${message}\n`); process.exit(1); }
|