kenaz 0.3.22 → 0.3.24
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/core/.claude/hooks/_user-scope.js +1 -1
- package/core/.claude/hooks/core-resolve.js +1 -1
- package/core/.claude/hooks/worktree-create.js +11 -29
- package/core/.claude/hooks/worktree-remove.js +12 -38
- package/core/.collaboration/core/reconcile.js +16 -1
- package/core/.collaboration/core/task-2467-lifecycle.test.js +63 -0
- package/core/.collaboration/core/task-api.js +37 -7
- package/core/.formation/bifrost/launch.js +1 -1
- package/core/.formation/tools/dispatch-detail/worktree-subagent-mode.md +6 -1
- package/core/.formation/tools/kenaz-stats.js +1 -1
- package/core/.formation/tools/post-complete/git-merge.js +1 -1
- package/core/.formation/tools/prompt.js +1 -1
- package/core/.formation/tools/utils.js +5 -5
- package/core/.formation/tools/worktree-reclaim.js +73 -2
- package/core/.formation/tools/worktree-reclaim.test.js +113 -0
- package/core/.kenaz/specialist/ansuz_rules.yaml +7 -51
- package/core/.kenaz/specialist/ansuz_session_handoff.schema.json +2 -6
- package/core/.rule/general/project-self-containment.yaml +2 -2
- package/core/.specialist/Amelia/README.md +1 -1
- package/core/.specialist/Amelia/rule.yaml +1 -1
- package/core/.specialist/Ansuz/RULES.md +6 -2
- package/core/.specialist/Ansuz/concepts/commitment_layer.yaml +1 -1
- package/core/.specialist/Ansuz/concepts/evolvable_guardrails.yaml +1 -1
- package/core/.specialist/Ansuz/knowledge.yaml +1 -3
- package/core/.specialist/tools/__tests__/task-2409-lessons.test.js +10 -0
- package/core/.specialist/tools/__tests__/task-2427-harvest.test.js +25 -0
- package/core/.specialist/tools/ansuz-boot-fast.js +1 -1
- package/core/.specialist/tools/failure-detector.js +4 -4
- package/core/.specialist/tools/handoff-doc.js +1 -1
- package/core/.specialist/tools/lessons.js +2 -2
- package/core/CLAUDE.md +5 -5
- package/core/KENAZ_CORE_VERSION +1 -1
- package/core/dashboard/scripts/install-kenaz-cli.js +56 -30
- package/core/dev/scripts/check-file-size.js +1 -1
- package/core/dev/scripts/ci-feedback.js +1 -1
- package/core/dev/scripts/gc-agent-worktrees.js +13 -12
- package/core/dev/scripts/kenaz-session.js +3 -3
- package/core/dev/scripts/peer-identity-e2e.js +6 -4
- package/core/dev/scripts/run-rust-tests.js +2 -2
- package/core/dev/scripts/skill-routing-replay.js +3 -3
- package/core/dev/scripts/task1961/selftest.js +2 -2
- package/core/dev/scripts/windows-hide-guard.test.js +112 -0
- package/core/plugins/kenaz/guidance.md +1 -0
- package/core/plugins/kenaz/hooks/core-resolve.js +1 -1
- package/core/plugins/kenaz/hooks/hooks.json +9 -0
- package/core/plugins/kenaz/hooks/kenaz-hook.js +58 -4
- package/core/plugins/kenaz/hooks/worktree-guard.js +121 -0
- package/core/plugins/kenaz/hooks/worktree-guard.test.js +75 -0
- package/core/plugins/kenaz/scripts/kenaz.test.js +72 -5
- package/core/plugins/kenaz-peer/hooks/register.test.ts +14 -2
- package/core/plugins/kenaz-peer/hooks/register.ts +6 -1
- package/lib/cli.js +9 -5
- package/package.json +6 -6
- package/vendor/install-kenaz-cli.js +56 -30
- package/core/.kenaz/designs/METAPLASTICITY_CONFIDENCE_DESIGN.md +0 -537
- package/core/.kenaz/designs/REFLEX_INITIATOR_DESIGN.md +0 -501
- package/core/.kenaz/designs/TASK_1385_handoff_mcp_design.md +0 -426
- package/core/.kenaz/designs/TASK_932_hippocampus_consolidation.md +0 -103
- package/core/.kenaz/designs/TASK_934_efe_signal_engine.md +0 -97
- package/core/.kenaz/designs/TASK_935_self_evolution_framework.md +0 -154
- package/core/.kenaz/designs/VISION_cognitive_architecture_roadmap.md +0 -159
- package/core/.kenaz/designs/metaplasticity_simulation_results.json +0 -696
- package/core/.kenaz/main-memory/README.md +0 -230
- package/core/.kenaz/main-memory/kenaz/cortex/001_cortex_overview.md +0 -168
- package/core/.kenaz/main-memory/kenaz/cortex/001_rag_engine_overview.md +0 -30
- package/core/.kenaz/main-memory/kenaz/memory-system/001_three_tier_architecture.md +0 -361
- package/core/.kenaz/main-memory/kenaz/pipeline/001_task_execution_flow.md +0 -117
- package/core/.kenaz/main-memory/kenaz/pipeline/001_task_granularity.md +0 -154
- package/core/.kenaz/main-memory/kenaz/pipeline/002_team_priority.md +0 -51
- package/core/.kenaz/main-memory/kenaz/pipeline/003_feature_id_system.md +0 -46
- package/core/.kenaz/main-memory/kenaz/rules/001_gen_007_self_containment.md +0 -108
- package/core/.kenaz/main-memory/kenaz/rules/001_rule_priority_system.md +0 -121
- package/core/.kenaz/main-memory/kenaz/rules/002_agt_006_pre_check.md +0 -0
- package/core/.kenaz/main-memory/kenaz/rules/003_ppl_002_task_archival.md +0 -48
- package/core/.kenaz/main-memory/kenaz/system/001_dual_track_task_system.md +0 -197
- package/core/.kenaz/main-memory/knowledge/patterns/001_json_bom_issue.md +0 -78
- package/core/.kenaz/main-memory/knowledge/patterns/001_leader_worker_pattern.md +0 -0
- package/core/.kenaz/main-memory/knowledge/patterns/002_scope_path_conflict.md +0 -115
- package/core/.kenaz/main-memory/knowledge/patterns/002_task_dependency_resolution.md +0 -223
- package/core/.kenaz/main-memory/knowledge/patterns/003_question_protocol.md +0 -242
- package/core/.kenaz/main-memory/knowledge/patterns/004_user_insight_value.md +0 -111
- package/core/.kenaz/main-memory/knowledge/patterns/005_file_lock_pattern.md +0 -274
- package/core/.kenaz/main-memory/knowledge/references/001_ppl_rules.md +0 -28
- package/core/.kenaz/main-memory/knowledge/solutions/001_json_bom_issue.md +0 -137
- package/core/.kenaz/main-memory/knowledge/solutions/001_team_invocation.md +0 -0
- package/core/.kenaz/main-memory/knowledge/solutions/002_passive_monitoring.md +0 -0
- package/core/.kenaz/main-memory/knowledge/solutions/003_windows_file_race_condition.md +0 -239
- package/core/.kenaz/main-memory/registry.json +0 -326
- package/core/.kenaz/main-memory/version.yaml +0 -58
- package/core/.kenaz/specialist/memory_guard_fired.json +0 -1
- package/core/.kenaz/specialist/memory_guard_trigger_cache.json +0 -1
- package/core/.kenaz/specialist/memory_source_priority.yaml +0 -260
- package/core/.kenaz/specialist/prompt_1775.txt +0 -317
- package/core/.kenaz/specialist/prompt_1776.txt +0 -326
- package/core/.kenaz/specialist/prompt_1791.txt +0 -320
- package/core/.kenaz/specialist/prompt_1792.txt +0 -320
- package/core/.kenaz/specialist/prompt_1795.txt +0 -281
- package/core/.kenaz/specialist/prompt_1813.txt +0 -332
- package/core/.kenaz/specialist/prompt_1814.txt +0 -401
- package/core/.kenaz/specialist/prompt_1815.txt +0 -394
- package/core/.kenaz/specialist/prompt_1816.txt +0 -437
- package/core/.kenaz/specialist/prompt_1818.txt +0 -361
- package/core/.kenaz/specialist/prompt_1819.txt +0 -421
- package/core/.kenaz/specialist/prompt_1821.txt +0 -345
- package/core/.kenaz/specialist/prompt_1822.txt +0 -313
- package/core/.kenaz/specialist/prompt_1824.txt +0 -348
- package/core/.kenaz/specialist/prompt_1826.txt +0 -388
- package/core/.kenaz/specialist/rune_efe_salience_gap.md +0 -21
- package/core/.kenaz/specialist/task1825_update.json +0 -43
- package/core/.kenaz/specialist/taskgen/consolidation_i.json +0 -38
- package/core/.kenaz/specialist/taskgen/csharp_a.json +0 -44
- package/core/.kenaz/specialist/taskgen/csharp_b.json +0 -40
- package/core/.kenaz/specialist/taskgen/embedding_e.json +0 -34
- package/core/.kenaz/specialist/taskgen/hygiene_fg.json +0 -39
- package/core/.kenaz/specialist/taskgen/pathology_h.json +0 -36
- package/core/.kenaz/specialist/taskgen/unity_noise_d.json +0 -38
- package/core/.kenaz/specialist/taskgen/visibility_c.json +0 -38
- package/core/.specialist/Ansuz/decisions/ADR-requirement-graph-layer.md +0 -390
- package/core/.specialist/Ansuz/self_model_seed.backup.json +0 -100
- package/core/.specialist/ansuz_session_handoff.json +0 -96
- package/core/dev/ALAYA_FIELD_FEEDBACK_DESIGN.md +0 -126
- package/core/dev/ANSUZ_SCAFFOLD_DIET_2026-09-20.md +0 -231
- package/core/dev/ANSUZ_STARTUP_INJECTION_REVIEW.md +0 -355
- package/core/dev/ANSUZ_WORKFLOW_MODERNIZATION.md +0 -143
- package/core/dev/CORTEX_META_GRAPH_ASSESSMENT.md +0 -99
- package/core/dev/FREYA_DOWNSTREAM_BUGS_2026-09-19.md +0 -44
- package/core/dev/GLOBAL_MEMORY_IDENTITY_CONSOLIDATION.md +0 -263
- package/core/dev/GUARD_EFFECTIVENESS_DESIGN.md +0 -180
- package/core/dev/HEALTH_GATE_VARIANCE_ASSESSMENT.md +0 -271
- package/core/dev/HOOK_DIET_2026-09-21.md +0 -126
- package/core/dev/JEV_INTEGRATION_PLAN.md +0 -189
- package/core/dev/KENAZ_AGENT_CONNECT_v1_SPEC.md +0 -139
- package/core/dev/MOBILE_DESIGN_SPEC.md +0 -569
- package/core/dev/MULTI_ANSUZ_SPEC.md +0 -136
- package/core/dev/MUNINN_RETIREMENT.md +0 -115
- package/core/dev/PHASE3_ATTRIBUTION_POPULATION_DIAGNOSIS.md +0 -211
- package/core/dev/PHASE3_P3-2B_TASKLEVEL_PROBE.md +0 -83
- package/core/dev/PHASE3_P3-2_POPULATION_DISJOINTNESS.md +0 -83
- package/core/dev/PHASE3_P3-2_REMEASURE_REPORT.md +0 -231
- package/core/dev/PREDICTION_GROUNDING_DESIGN.md +0 -376
- package/core/dev/PRODUCT_SPEC.md +0 -317
- package/core/dev/PROJECT_REGISTRY_DUPLICATE_ASSESSMENT.md +0 -86
- package/core/dev/STARTUP_TIMELINE_TASK_1995.md +0 -181
- package/core/dev/SYNAPSE_WORKER_PER_PROJECT.md +0 -881
- package/core/dev/TASK_1680_P3-3_DISPATCH_SPEC.md +0 -96
- package/core/dev/TASK_1684_CALIBRATION_IMPACT_ANALYSIS.md +0 -170
- package/core/dev/TASK_1684_FORK_A_GOODHART_DESIGN.md +0 -171
- package/core/dev/TASK_1684_P3_2_REMEASURE_VALIDATION.md +0 -262
- package/core/dev/TASK_1903_SIGNAL_AUC_MEASUREMENT.md +0 -207
- package/core/dev/TASK_1904_BRANCH_INTEGRITY_AUDIT.md +0 -146
- package/core/dev/ansuz-eval/README.md +0 -38
- package/core/dev/ansuz-eval/build-fixtures.js +0 -87
- package/core/dev/ansuz-eval/grade.js +0 -96
- package/core/dev/ansuz-eval/grader.test.js +0 -117
- package/core/dev/ansuz-eval/tasks.md +0 -32
- package/core/dev/archive/ansuz/BOOT_FULL.md +0 -141
- package/core/dev/archive/ansuz/agents/ansuz-boot.md +0 -176
- package/core/dev/archive/ansuz/designs/alaya-passive-surfacing.md +0 -84
- package/core/dev/archive/ansuz/designs/cc_memory_indexing.md +0 -307
- package/core/dev/archive/ansuz/designs/check_guard.md +0 -322
- package/core/dev/archive/ansuz/designs/consequence_loop.md +0 -227
- package/core/dev/archive/ansuz/designs/mcp_kuzudb_lock_architecture.md +0 -312
- package/core/dev/archive/ansuz/designs/phase0_git_enrichment.md +0 -278
- package/core/dev/archive/ansuz/designs/refactor_mcp_tools_synapse.md +0 -490
- package/core/dev/archive/ansuz/designs/semantic_markdown_extraction.md +0 -167
- package/core/dev/archive/ansuz/designs/task_1372_prompt_injects_into.md +0 -193
- package/core/dev/archive/ansuz/designs/thought_stack.md +0 -286
- package/core/dev/archive/ansuz/investigations/reachability_unified_api_2026-04-11.md +0 -330
- package/core/dev/archive/ansuz/investigations/synapse_orphans_indexing_bug_2026-04-11.md +0 -352
- package/core/dev/archive/ansuz/investigations/synapse_orphans_reindex_verification_2026-04-11.md +0 -48
- package/core/dev/archive/ansuz/investigations/synapse_orphans_verification_2026-04-11.md +0 -170
- package/core/dev/archive/ansuz/legacy/kernel.yaml +0 -399
- package/core/dev/archive/ansuz/legacy/phases/phase_0.yaml +0 -418
- package/core/dev/archive/ansuz/legacy/phases/phase_1.yaml +0 -376
- package/core/dev/archive/ansuz/legacy/phases/phase_10.yaml +0 -35
- package/core/dev/archive/ansuz/legacy/phases/phase_11.yaml +0 -582
- package/core/dev/archive/ansuz/legacy/phases/phase_2.yaml +0 -94
- package/core/dev/archive/ansuz/legacy/phases/phase_3.yaml +0 -274
- package/core/dev/archive/ansuz/legacy/phases/phase_4.yaml +0 -67
- package/core/dev/archive/ansuz/legacy/phases/phase_5.yaml +0 -32
- package/core/dev/archive/ansuz/legacy/phases/phase_6.yaml +0 -91
- package/core/dev/archive/ansuz/legacy/phases/phase_7.yaml +0 -58
- package/core/dev/archive/ansuz/legacy/phases/phase_8.yaml +0 -146
- package/core/dev/archive/ansuz/legacy/phases/phase_9.yaml +0 -424
- package/core/dev/archive/ansuz/specs/INDEX_bifrost_hook_parity.yaml +0 -92
- package/core/dev/archive/ansuz/specs/active-inference-formation.yaml +0 -453
- package/core/dev/archive/ansuz/specs/brief_TASK_1228_userpromptsubmit.yaml +0 -191
- package/core/dev/archive/ansuz/specs/brief_TASK_1229_pretooluse_posttooluse.yaml +0 -250
- package/core/dev/archive/ansuz/specs/brief_TASK_1230_sessionstart_stop.yaml +0 -301
- package/core/dev/archive/ansuz/specs/brief_TASK_1231_verification.yaml +0 -272
- package/core/dev/archive/skills/feature_agent/SKILL.md +0 -289
- package/core/dev/design/PHASE4_DESIGN.md +0 -559
- package/core/dev/design/dashboard_docs_integration_PLAN.md +0 -388
- package/core/dev/design/matrix_format_ABBREVIATIONS.md +0 -655
- package/core/dev/design/matrix_format_DESIGN_SPEC.md +0 -601
- package/core/dev/design/matrix_format_DISCUSSION_SUMMARY.md +0 -484
- package/core/dev/design/matrix_format_EXAMPLE_memory.matrix +0 -13
- package/core/dev/design/matrix_format_EXAMPLE_project_status.matrix +0 -9
- package/core/dev/design/matrix_format_EXAMPLE_tasks.matrix +0 -14
- package/core/dev/design/matrix_format_SYNTAX_BNF.md +0 -754
- package/core/dev/design/matrix_format_TOKEN_COMPARISON.md +0 -484
- package/core/dev/design/matrix_v2_COGNITIVE_DESIGN.md +0 -503
- package/core/dev/design/matrix_v2_DISCUSSION_SUMMARY.md +0 -414
- package/core/dev/design/matrix_v2_EXAMPLE.matrix +0 -67
- package/core/dev/designs/EXPANDABLE_CARD_DESIGN_SPEC.md +0 -509
- package/core/dev/jev-eval/ACTIVE_CORRECTION.md +0 -52
- package/core/dev/jev-eval/ANNOTATION_GUIDE.md +0 -68
- package/core/dev/jev-eval/BASELINE_COMPARISON.md +0 -45
- package/core/dev/jev-eval/CONTEXT_REVIEW.md +0 -31
- package/core/dev/jev-eval/EVALUATION_STATUS.md +0 -39
- package/core/dev/jev-eval/HISTORICAL_CORPUS.md +0 -33
- package/core/dev/jev-eval/PACKAGING_VERIFICATION.md +0 -42
- package/core/dev/jev-eval/README.md +0 -101
- package/core/dev/jev-eval/THALAMUS_RANKING.md +0 -58
- package/core/dev/jev-eval/VALIDATION_PROGRESS.md +0 -54
- package/core/dev/jev-eval/cli.mjs +0 -50
- package/core/dev/jev-eval/context.mjs +0 -183
- package/core/dev/jev-eval/corpus.mjs +0 -186
- package/core/dev/jev-eval/fixtures/conversation-review.seed.jsonl +0 -6
- package/core/dev/jev-eval/fixtures/synthetic.jsonl +0 -11
- package/core/dev/jev-eval/metrics.mjs +0 -67
- package/core/dev/jev-eval/muninn-baseline.mjs +0 -119
- package/core/dev/jev-eval/providers.mjs +0 -95
- package/core/dev/jev-eval/reports/annotation-pilot-2026-09-20.json +0 -32
- package/core/dev/jev-eval/reports/context-review-2026-09-20.json +0 -48
- package/core/dev/jev-eval/reports/conversation-review.pending.json +0 -151
- package/core/dev/jev-eval/reports/history-corpus-2026-09-20.json +0 -52
- package/core/dev/jev-eval/reports/length-probe-2026-09-20.json +0 -133
- package/core/dev/jev-eval/reports/live-smoke-2026-09-20.json +0 -616
- package/core/dev/jev-eval/reports/muninn-baseline-2026-09-20.json +0 -52
- package/core/dev/jev-eval/reports/resilience-2026-09-20.json +0 -520
- package/core/dev/jev-eval/reports/rules-baseline.json +0 -197
- package/core/dev/jev-eval/reports/synthetic-review.pending.json +0 -357
- package/core/dev/jev-eval/resilience.mjs +0 -71
- package/core/dev/jev-eval/review.mjs +0 -78
- package/core/dev/jev-eval/schema.mjs +0 -87
- package/core/dev/jev-eval/test/context.test.mjs +0 -95
- package/core/dev/jev-eval/test/corpus.test.mjs +0 -102
- package/core/dev/jev-eval/test/eval.test.mjs +0 -146
- package/core/dev/jev-eval/test/muninn-baseline.test.mjs +0 -71
- package/core/dev/jev-eval/test/resilience.test.mjs +0 -72
- package/core/dev/jev-eval/test/review.test.mjs +0 -61
- package/core/dev/pipeline/PHASE3_PLANNING_SUMMARY.md +0 -338
- package/core/dev/pipeline/PROGRESS.md +0 -113
- package/core/dev/pipeline/PROGRESS_template.md +0 -860
- package/core/dev/pipeline/QA_REPORT_F008.md +0 -431
- package/core/dev/pipeline/QA_REPORT_LOCAL_CLAUDE_DIAGNOSIS.md +0 -583
- package/core/dev/pipeline/README.md +0 -210
- package/core/dev/pipeline/WORKFLOW_GUIDE.md +0 -824
- package/core/dev/pipeline/archived/TASK_015_tauri_init.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_016_tauri_commands.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_017_rust_pty.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_018_tauri_bundle.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_019_release_workflow.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_020_update_ui.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_021_update_notification_ui.yaml +0 -55
- package/core/dev/pipeline/archived/TASK_022_remove_node_pty.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_023_api_routes_migration.yaml +0 -86
- package/core/dev/pipeline/archived/TASK_024_feature_id_system.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_025_executable_acceptance.yaml +0 -66
- package/core/dev/pipeline/archived/TASK_026_spec_versioning.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_027_drift_detection.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_028_tauri_pty_manager.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_029_tauri_pty_commands.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_030_frontend_session_adapter.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_031_terminal_tauri_events.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_041_scheduler_data_models.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_042_path_lock_manager.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_043_process_manager.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_044_git_integration.yaml +0 -85
- package/core/dev/pipeline/archived/TASK_045_task_queue_manager.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_046_scheduler_dispatcher.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_047_tauri_scheduler_commands.yaml +0 -55
- package/core/dev/pipeline/archived/TASK_048_realtime_status_push.yaml +0 -92
- package/core/dev/pipeline/archived/TASK_049_frontend_scheduler_integration.yaml +0 -58
- package/core/dev/pipeline/archived/TASK_050_error_recovery.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_051_optimization_proposals_backend.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_052_optimization_proposals_ui.yaml +0 -58
- package/core/dev/pipeline/archived/TASK_053_optimization_proposals_diff_view.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_054_multi_project_scheduler_state.yaml +0 -76
- package/core/dev/pipeline/archived/TASK_055_scheduler_api_project_scope.yaml +0 -64
- package/core/dev/pipeline/archived/TASK_056_frontend_scheduler_project_scope.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_057_scheduler_module_structure.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_058_scheduler_models_extract.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_059_scheduler_core_extract.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_060_scheduler_commands_extract.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_061_scheduler_specialized_commands.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_062_process_manager_module_structure.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_063_process_manager_core_extract.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_064_recovery_module_structure.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_065_recovery_core_extract.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_066_self_enhancement_scheduler_models.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_067_agents_section_quick_actions.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_067_self_enhancement_scheduler_core.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_068_agent_workflow_rule_enhancement.yaml +0 -46
- package/core/dev/pipeline/archived/TASK_068_self_enhancement_tauri_commands.yaml +0 -61
- package/core/dev/pipeline/archived/TASK_069_agent_wizard_responsive.yaml +0 -46
- package/core/dev/pipeline/archived/TASK_069_self_enhancement_ui.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_070_preview_panel_redesign.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_070_self_enhancement_integration.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_071_preview_panel_qa.yaml +0 -98
- package/core/dev/pipeline/archived/TASK_071_single_agent_config.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_072_preview_modal_esc_fix.yaml +0 -71
- package/core/dev/pipeline/archived/TASK_072_product_review_module.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_073_agents_page_component_refactor.yaml +0 -68
- package/core/dev/pipeline/archived/TASK_073_rename_single_agent.yaml +0 -64
- package/core/dev/pipeline/archived/TASK_074_preview_mode_ui_diagnosis.yaml +0 -71
- package/core/dev/pipeline/archived/TASK_074_single_agent_ui_toggle.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_075_agents_page_component_refactor.yaml +0 -69
- package/core/dev/pipeline/archived/TASK_075_single_agent_integration_test.yaml +0 -75
- package/core/dev/pipeline/archived/TASK_076_preview_mode_ui_diagnosis.yaml +0 -70
- package/core/dev/pipeline/archived/TASK_076_single_agent_continuous_mode.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_077_failure_directory_structure.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_077_single_agent_typescript_types.yaml +0 -59
- package/core/dev/pipeline/archived/TASK_078_fail_001_agent_no_output.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_078_single_agent_ui_simplify.yaml +0 -74
- package/core/dev/pipeline/archived/TASK_079_dashboard_rwd_responsive.yaml +0 -63
- package/core/dev/pipeline/archived/TASK_079_fail_002_json_bom.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_080_fail_003_queue_pollution.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_080_http_server_module.yaml +0 -55
- package/core/dev/pipeline/archived/TASK_081_failure_logging_tools.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_081_http_api_routes.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_082_frontend_api_adapter.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_082_integrate_failure_to_workflow.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_083_cleanup_nextjs_api.yaml +0 -48
- package/core/dev/pipeline/archived/TASK_083_task_queue_cleanup.yaml +0 -67
- package/core/dev/pipeline/archived/TASK_084_rust_dead_code_cleanup.yaml +0 -66
- package/core/dev/pipeline/archived/TASK_084_scheduler_sync_logic_fix.yaml +0 -68
- package/core/dev/pipeline/archived/TASK_085_http_api_web_mode_fixes.yaml +0 -46
- package/core/dev/pipeline/archived/TASK_085_memory_consolidation_0204_0205.yaml +0 -98
- package/core/dev/pipeline/archived/TASK_086_collapsible_preview_panel.yaml +0 -161
- package/core/dev/pipeline/archived/TASK_086_web_mode_feature_parity.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_087_manual_memory_archival.yaml +0 -163
- package/core/dev/pipeline/archived/TASK_087_mobile_http_control.yaml +0 -68
- package/core/dev/pipeline/archived/TASK_088_fail_003_to_ppl_002_rule.yaml +0 -63
- package/core/dev/pipeline/archived/TASK_088_mobile_http_qa.yaml +0 -121
- package/core/dev/pipeline/archived/TASK_089_agent_collaboration_topic.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_089_web_mode_monitor_fix.yaml +0 -58
- package/core/dev/pipeline/archived/TASK_090_cli_detection_fix.yaml +0 -61
- package/core/dev/pipeline/archived/TASK_090_ui_ux_lessons_topic.yaml +0 -63
- package/core/dev/pipeline/archived/TASK_091_expandable_card_design.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_091_move_agent_section_components.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_092_expandable_card_component.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_092_refactor_agent_create_wizard.yaml +0 -84
- package/core/dev/pipeline/archived/TASK_093_taskcard_detail_integration.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_093_update_barrel_exports_test.yaml +0 -84
- package/core/dev/pipeline/archived/TASK_094_ai_agent_generation_enhancement.yaml +0 -115
- package/core/dev/pipeline/archived/TASK_094_proposalcard_detail_integration.yaml +0 -55
- package/core/dev/pipeline/archived/TASK_095_preview_fixes.yaml +0 -129
- package/core/dev/pipeline/archived/TASK_095_single_agent_task_selector.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_096_agents_page_ux_improvements.yaml +0 -163
- package/core/dev/pipeline/archived/TASK_096_single_agent_status_sync.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_097_local_claude_error_logging.yaml +0 -59
- package/core/dev/pipeline/archived/TASK_097_single_agent_monitor_events.yaml +0 -59
- package/core/dev/pipeline/archived/TASK_098_product_manager_team_phase2.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_098_single_agent_refactor_test.yaml +0 -58
- package/core/dev/pipeline/archived/TASK_099_backend_team_creation.yaml +0 -258
- package/core/dev/pipeline/archived/TASK_100_frontend_team_creation.yaml +0 -61
- package/core/dev/pipeline/archived/TASK_101_orchestrator_system.yaml +0 -403
- package/core/dev/pipeline/archived/TASK_102_designer_sre_teams.yaml +0 -90
- package/core/dev/pipeline/archived/TASK_103_integration_testing.yaml +0 -86
- package/core/dev/pipeline/archived/TASK_128_integration_testing.yaml +0 -83
- package/core/dev/pipeline/archived/TASK_134_cortex_v2_phase3_file_watcher.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_134_team_http_api.yaml +0 -96
- package/core/dev/pipeline/archived/TASK_135_cortex_v2_phase3_git_monitor.yaml +0 -63
- package/core/dev/pipeline/archived/TASK_136_cortex_v2_phase3_change_analyzer.yaml +0 -69
- package/core/dev/pipeline/archived/TASK_137_cortex_v2_phase3_cache_invalidator.yaml +0 -67
- package/core/dev/pipeline/archived/TASK_137_team_orchestrator_integration.yaml +0 -93
- package/core/dev/pipeline/archived/TASK_138_cortex_v2_phase3_distributed_cache.yaml +0 -68
- package/core/dev/pipeline/archived/TASK_138_matrix_folder_structure.yaml +0 -61
- package/core/dev/pipeline/archived/TASK_139_cortex_v2_phase3_cache_prewarming.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_146_unified_documentation.yaml +0 -141
- package/core/dev/pipeline/archived/TASK_147_pipeline_execution_rules.yaml +0 -76
- package/core/dev/pipeline/archived/TASK_148_update_claude_md.yaml +0 -77
- package/core/dev/pipeline/archived/TASK_149_fix_nextjs_mdx_serialization.yaml +0 -63
- package/core/dev/pipeline/archived/TASK_149_update_team_docs.yaml +0 -77
- package/core/dev/pipeline/archived/TASK_150_pipeline_workflow_guide.yaml +0 -82
- package/core/dev/pipeline/archived/TASK_164_fix_smart_context_switch.yaml +0 -49
- package/core/dev/pipeline/archived/TASK_165_ctags_symbol_index.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_166_symbol_search_mcp_tool.yaml +0 -48
- package/core/dev/pipeline/archived/TASK_167_llm_module_summary.yaml +0 -55
- package/core/dev/pipeline/archived/TASK_168_map_reduce_context.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_169_v2_integration_testing.yaml +0 -52
- package/core/dev/pipeline/backups/archive_2026-02-04T22-07-22/TASK_QUEUE_backup.json +0 -95
- package/core/dev/pipeline/docs/multi-agent-coordination.md +0 -446
- package/core/dev/pipeline/docs/overview.md +0 -406
- package/core/dev/pipeline/docs/task-management.md +0 -412
- package/core/dev/pipeline/docs/workflows.md +0 -32
- package/core/dev/pipeline/orchestrator/schemas/task_queue_schema.json +0 -58
- package/core/dev/pipeline/orchestrator/schemas/task_schema.json +0 -139
- package/core/dev/pipeline/plans/PLAN_task_cli_refactor.md +0 -281
- package/core/dev/pipeline/test_results/TASK_TEST_PARALLEL_002_result.txt +0 -27
- package/core/dev/plans/ANSUZ_SLIM_PLAN.md +0 -68
- package/core/dev/plans/CLI_FIRST_INSTALL_FLOW.md +0 -120
- package/core/dev/plans/FORMATION_RETIREMENT_PLAN.md +0 -313
- package/core/dev/plans/KUZU_REPLACEMENT_PLAN.md +0 -126
- package/core/dev/scripts/CRASH_DIAGNOSIS.md +0 -47
- package/core/dev/scripts/README.md +0 -142
- package/core/dev/scripts/RUN_ONCE.bat +0 -40
- package/core/dev/scripts/START_DEV_AGENT.bat +0 -63
- package/core/dev/scripts/START_MULTI_AGENT.bat +0 -80
- package/core/dev/scripts/dev_agent_scheduler.ps1 +0 -536
- package/core/dev/scripts/init_git.ps1 +0 -396
- package/core/dev/scripts/init_git.sh +0 -337
- package/core/dev/scripts/init_project.ps1 +0 -851
- package/core/dev/scripts/init_project.sh +0 -477
- package/core/dev/scripts/multi_agent_scheduler.ps1 +0 -2021
- package/core/dev/scripts/multi_agent_scheduler.sh +0 -1344
- package/core/dev/scripts/run_once.sh +0 -47
- package/core/dev/scripts/setup_rag.ps1 +0 -304
- package/core/dev/scripts/setup_rag.sh +0 -230
- package/core/dev/scripts/start_dev_agent.sh +0 -137
- package/core/dev/scripts/start_multi_agent.sh +0 -41
- package/core/dev/scripts/sync_task_queue.ps1 +0 -505
- package/core/dev/scripts/sync_task_queue.sh +0 -392
- package/core/dev/specs/agent-connect/PROTOCOL.md +0 -177
- package/core/dev/specs/agent-connect/SDK_GUIDE.md +0 -915
- package/core/dev/specs/agent-connect/examples/minimal-site/README.md +0 -137
- package/core/dev/specs/agent-connect/examples/minimal-site/package.json +0 -12
- package/core/dev/specs/agent-connect/examples/minimal-site/public/index.html +0 -116
- package/core/dev/specs/agent-connect/examples/minimal-site/public/install-redirect.js +0 -73
- package/core/dev/specs/agent-connect/examples/minimal-site/server.js +0 -516
- package/core/dev/specs/agent-connect/examples/minimal-site/test/smoke.test.mjs +0 -263
- package/core/dev/specs/agent-connect/history/DEFECT_REPORT_kenaz-agent-hub_2026-09-09_v0.4-empty-prompt-no-first-turn.md +0 -77
- package/core/dev/specs/agent-connect/history/DEFECT_REPORT_kenaz-agent-hub_2026-09-09_v0.4-prompt-mojibake.md +0 -90
- package/core/dev/specs/agent-connect/history/FEATURE_REQUEST_kenaz-agent-hub_2026-09-07.md +0 -61
- package/core/dev/specs/agent-connect/history/FEATURE_REQUEST_kenaz-agent-hub_2026-09-08_relay-v1-conformance.md +0 -76
- package/core/dev/specs/agent-connect/history/FEATURE_REQUEST_kenaz-agent-hub_2026-09-09_v0.4-session-channel.md +0 -87
- package/core/dev/specs/agent-connect/history/FLOWPIX_REPLY_agent-hub_2026-09-08_relay-v1-answers.md +0 -68
- package/core/dev/specs/agent-connect/history/FLOWPIX_bridge_CONTRACT.md +0 -642
- package/core/dev/specs/agent-connect/history/FLOWPIX_spikes_relay_spike_relay.mjs +0 -244
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-07.md +0 -77
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-08_direction-change-v0.3.md +0 -44
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-08_relay-v1-answers-ack.md +0 -37
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-08_relay-v1-conformance.md +0 -56
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_annotations-install-coldstart.md +0 -44
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_empty-prompt-first-turn.md +0 -56
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_prompt-mojibake-fixed.md +0 -48
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_session-channel.md +0 -57
- package/core/dev/specs/agent-connect/history/PROTOCOL_v0.3_snapshot.md +0 -379
- package/core/dev/specs/agent-connect/history/README.md +0 -47
- package/core/dev/specs/peer/CODEX_INTERACTIVE_PUSH.md +0 -65
- package/core/dev/specs/peer/CODEX_MANAGED_DAEMON.md +0 -54
- package/core/dev/specs/peer/CODEX_PEER_PULL_SPIKE.md +0 -54
- package/core/dev/specs/peer/MODS_SPIKE.md +0 -133
- package/core/dev/specs/peer/PER_PROJECT_ADDRESSING.md +0 -143
- package/core/dev/specs/peer/SWARM_PROTOCOLS.md +0 -256
- package/core/dev/specs/peer/codex-hook-shim-peer.test.js +0 -113
- package/core/dev/specs/peer/codex-push-launcher.test.js +0 -142
- package/core/dev/specs/peer/setup-codex-hooks.test.js +0 -60
- package/core/dev/specs/peer-ansuz/DELIVERY_SPIKE.md +0 -397
- package/core/dev/specs/peer-ansuz/DESIGN.md +0 -109
- package/core/dev/specs/peer-ansuz/spike/claude_poke.js +0 -129
- package/core/dev/specs/peer-ansuz/spike/claude_session_start_hook.js +0 -37
- package/core/dev/specs/peer-ansuz/spike/claude_settings_hook.json +0 -14
- package/core/dev/specs/peer-ansuz/spike/codex_appserver_client.js +0 -105
- package/core/dev/specs/peer-ansuz/spike/codex_appserver_query.js +0 -29
- package/core/dev/specs/peer-ansuz/spike/extract_timeline.js +0 -26
- package/core/dev/specs/synapse/SYMBOL_IDENTITY.md +0 -305
- package/core/dev/spikes/A4-cypher-varlen.md +0 -176
- package/core/dev/spikes/bloat-rounds.sh +0 -25
- package/core/dev/spikes/mods/clean-claude.js +0 -9
- package/core/dev/spikes/mods/drive-probe.js +0 -29
- package/core/dev/spikes/mods/e2e-peer.js +0 -71
- package/core/dev/spikes/mods/evidence/e2e-peer-control.json +0 -17
- package/core/dev/spikes/mods/evidence/e2e-peer-mod.json +0 -17
- package/core/dev/spikes/mods/evidence/probe-006a6e65-d807-4bc1-b648-fd7d1edfe0b4.jsonl +0 -4
- package/core/dev/spikes/mods/evidence/probe-cebdf1f7-f9c4-47a8-83cd-7c0786177404.jsonl +0 -12
- package/core/dev/spikes/mods/evidence/probe-eb21147d-10ce-4c32-93ed-37ca37d88d5a.jsonl +0 -11
- package/core/dev/spikes/mods/evidence/stream-cebdf1f7.jsonl +0 -18
- package/core/dev/spikes/mods/kenaz-mod-probe/.claude-plugin/plugin.json +0 -1
- package/core/dev/spikes/mods/kenaz-mod-probe/hooks/hooks.json +0 -1
- package/core/dev/spikes/mods/kenaz-mod-probe/hooks/register.ts +0 -65
- package/core/dev/spikes/mods/kenaz-mod-probe/tsconfig.json +0 -3
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
// Smoke test for the minimal example site (TASK_1940).
|
|
2
|
-
// Run: node --test dev/specs/agent-connect/examples/minimal-site/test/smoke.test.mjs
|
|
3
|
-
//
|
|
4
|
-
// Proves the MCP endpoint's bearer gate actually works end-to-end (this is
|
|
5
|
-
// the "control group" AC in the task card: "範例網站的 MCP 對錯誤 bearer 回
|
|
6
|
-
// 401") — starts a real HTTP server on an OS-assigned port, makes real
|
|
7
|
-
// requests, and closes the server when done. No mocking of server.js
|
|
8
|
-
// itself: this exercises the exact code path a real browser click would.
|
|
9
|
-
|
|
10
|
-
import { test } from 'node:test';
|
|
11
|
-
import assert from 'node:assert/strict';
|
|
12
|
-
import { createServer } from '../server.js';
|
|
13
|
-
import { resolveInstallRedirect, buildInstallRedirectUrl } from '../public/install-redirect.js';
|
|
14
|
-
|
|
15
|
-
test('POST /api/connect mints a token and returns a well-formed kenaz://connect deep link', async (t) => {
|
|
16
|
-
const demo = createServer({ port: 0 });
|
|
17
|
-
await demo.listen();
|
|
18
|
-
t.after(() => demo.close());
|
|
19
|
-
|
|
20
|
-
const res = await fetch(`${demo.baseUrl}/api/connect`, {
|
|
21
|
-
method: 'POST',
|
|
22
|
-
headers: { 'content-type': 'application/json' },
|
|
23
|
-
body: JSON.stringify({ prompt: 'hello' }),
|
|
24
|
-
});
|
|
25
|
-
assert.equal(res.status, 200);
|
|
26
|
-
const { deepLink, token } = await res.json();
|
|
27
|
-
assert.ok(token, 'expected a token');
|
|
28
|
-
|
|
29
|
-
const parsed = new URL(deepLink);
|
|
30
|
-
assert.equal(parsed.protocol, 'kenaz:');
|
|
31
|
-
assert.equal(parsed.hostname, 'connect');
|
|
32
|
-
assert.equal(parsed.searchParams.get('site'), demo.baseUrl);
|
|
33
|
-
assert.equal(parsed.searchParams.get('mcp'), `${demo.baseUrl}/mcp`);
|
|
34
|
-
assert.equal(parsed.searchParams.get('token'), token);
|
|
35
|
-
assert.equal(parsed.searchParams.get('prompt'), 'hello');
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test('POST /mcp with no bearer, or the wrong bearer, is rejected with 401', async (t) => {
|
|
39
|
-
const demo = createServer({ port: 0 });
|
|
40
|
-
await demo.listen();
|
|
41
|
-
t.after(() => demo.close());
|
|
42
|
-
|
|
43
|
-
const rpc = { jsonrpc: '2.0', id: 1, method: 'tools/call', params: { name: 'kenaz_hello', arguments: {} } };
|
|
44
|
-
|
|
45
|
-
const noAuth = await fetch(`${demo.baseUrl}/mcp`, {
|
|
46
|
-
method: 'POST',
|
|
47
|
-
headers: { 'content-type': 'application/json' },
|
|
48
|
-
body: JSON.stringify(rpc),
|
|
49
|
-
});
|
|
50
|
-
assert.equal(noAuth.status, 401);
|
|
51
|
-
|
|
52
|
-
const wrongAuth = await fetch(`${demo.baseUrl}/mcp`, {
|
|
53
|
-
method: 'POST',
|
|
54
|
-
headers: { 'content-type': 'application/json', authorization: 'Bearer not-a-real-token' },
|
|
55
|
-
body: JSON.stringify(rpc),
|
|
56
|
-
});
|
|
57
|
-
assert.equal(wrongAuth.status, 401);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test('control group: a legitimate token in the same run is still accepted (401 is not a global outage)', async (t) => {
|
|
61
|
-
const demo = createServer({ port: 0 });
|
|
62
|
-
await demo.listen();
|
|
63
|
-
t.after(() => demo.close());
|
|
64
|
-
|
|
65
|
-
const connectRes = await fetch(`${demo.baseUrl}/api/connect`, { method: 'POST' });
|
|
66
|
-
const { token } = await connectRes.json();
|
|
67
|
-
|
|
68
|
-
const res = await fetch(`${demo.baseUrl}/mcp`, {
|
|
69
|
-
method: 'POST',
|
|
70
|
-
headers: { 'content-type': 'application/json', authorization: `Bearer ${token}` },
|
|
71
|
-
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'tools/call', params: { name: 'kenaz_hello', arguments: {} } }),
|
|
72
|
-
});
|
|
73
|
-
assert.equal(res.status, 200);
|
|
74
|
-
const body = await res.json();
|
|
75
|
-
const payload = JSON.parse(body.result.content[0].text);
|
|
76
|
-
assert.deepEqual(payload, { ok: true });
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test('kenaz_hello call is reflected in /api/status/:token', async (t) => {
|
|
80
|
-
const demo = createServer({ port: 0 });
|
|
81
|
-
await demo.listen();
|
|
82
|
-
t.after(() => demo.close());
|
|
83
|
-
|
|
84
|
-
const connectRes = await fetch(`${demo.baseUrl}/api/connect`, { method: 'POST' });
|
|
85
|
-
const { token } = await connectRes.json();
|
|
86
|
-
|
|
87
|
-
const before = await fetch(`${demo.baseUrl}/api/status/${token}`);
|
|
88
|
-
assert.equal((await before.json()).connected, false);
|
|
89
|
-
|
|
90
|
-
await fetch(`${demo.baseUrl}/mcp`, {
|
|
91
|
-
method: 'POST',
|
|
92
|
-
headers: { 'content-type': 'application/json', authorization: `Bearer ${token}` },
|
|
93
|
-
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'tools/call', params: { name: 'kenaz_hello', arguments: {} } }),
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
const after = await fetch(`${demo.baseUrl}/api/status/${token}`);
|
|
97
|
-
const afterBody = await after.json();
|
|
98
|
-
assert.equal(afterBody.connected, true);
|
|
99
|
-
assert.ok(afterBody.calledAt);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
// ── TASK_1948: kenaz_wait_for_message mailbox ──────────────────────────
|
|
103
|
-
|
|
104
|
-
test('POST /message delivers into the mailbox and kenaz_wait_for_message returns it', async (t) => {
|
|
105
|
-
const demo = createServer({ port: 0, waitTimeoutMs: 5_000 });
|
|
106
|
-
await demo.listen();
|
|
107
|
-
t.after(() => demo.close());
|
|
108
|
-
|
|
109
|
-
const connectRes = await fetch(`${demo.baseUrl}/api/connect`, { method: 'POST' });
|
|
110
|
-
const { token } = await connectRes.json();
|
|
111
|
-
|
|
112
|
-
const deliverRes = await fetch(`${demo.baseUrl}/message`, {
|
|
113
|
-
method: 'POST',
|
|
114
|
-
headers: { 'content-type': 'application/json' },
|
|
115
|
-
body: JSON.stringify({ token, message: 'summarize the canvas' }),
|
|
116
|
-
});
|
|
117
|
-
assert.equal(deliverRes.status, 200);
|
|
118
|
-
const { message_id: deliveredId } = await deliverRes.json();
|
|
119
|
-
assert.ok(deliveredId);
|
|
120
|
-
|
|
121
|
-
const waitRes = await fetch(`${demo.baseUrl}/mcp`, {
|
|
122
|
-
method: 'POST',
|
|
123
|
-
headers: { 'content-type': 'application/json', authorization: `Bearer ${token}` },
|
|
124
|
-
body: JSON.stringify({
|
|
125
|
-
jsonrpc: '2.0', id: 2, method: 'tools/call',
|
|
126
|
-
params: { name: 'kenaz_wait_for_message', arguments: {} },
|
|
127
|
-
}),
|
|
128
|
-
});
|
|
129
|
-
assert.equal(waitRes.status, 200);
|
|
130
|
-
const body = await waitRes.json();
|
|
131
|
-
const payload = JSON.parse(body.result.content[0].text);
|
|
132
|
-
assert.equal(payload.message, 'summarize the canvas');
|
|
133
|
-
assert.equal(payload.message_id, deliveredId);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
test('kenaz_wait_for_message returns null message/message_id when nothing was delivered, after the long-poll window', async (t) => {
|
|
137
|
-
const demo = createServer({ port: 0, waitTimeoutMs: 150 });
|
|
138
|
-
await demo.listen();
|
|
139
|
-
t.after(() => demo.close());
|
|
140
|
-
|
|
141
|
-
const connectRes = await fetch(`${demo.baseUrl}/api/connect`, { method: 'POST' });
|
|
142
|
-
const { token } = await connectRes.json();
|
|
143
|
-
|
|
144
|
-
const start = Date.now();
|
|
145
|
-
const waitRes = await fetch(`${demo.baseUrl}/mcp`, {
|
|
146
|
-
method: 'POST',
|
|
147
|
-
headers: { 'content-type': 'application/json', authorization: `Bearer ${token}` },
|
|
148
|
-
body: JSON.stringify({
|
|
149
|
-
jsonrpc: '2.0', id: 2, method: 'tools/call',
|
|
150
|
-
params: { name: 'kenaz_wait_for_message', arguments: {} },
|
|
151
|
-
}),
|
|
152
|
-
});
|
|
153
|
-
const elapsedMs = Date.now() - start;
|
|
154
|
-
const body = await waitRes.json();
|
|
155
|
-
const payload = JSON.parse(body.result.content[0].text);
|
|
156
|
-
assert.equal(payload.message, null);
|
|
157
|
-
assert.equal(payload.message_id, null);
|
|
158
|
-
assert.ok(elapsedMs >= 140, `expected the call to actually block for ~the waitTimeoutMs window, took ${elapsedMs}ms`);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
/// Control group: a token that was never minted (or already expired) must
|
|
162
|
-
/// be rejected the same way an unknown token is rejected for /mcp — proves
|
|
163
|
-
/// /message isn't a free-for-all message drop for any string.
|
|
164
|
-
test('control group: POST /message with an unknown token is rejected with 404', async (t) => {
|
|
165
|
-
const demo = createServer({ port: 0 });
|
|
166
|
-
await demo.listen();
|
|
167
|
-
t.after(() => demo.close());
|
|
168
|
-
|
|
169
|
-
const res = await fetch(`${demo.baseUrl}/message`, {
|
|
170
|
-
method: 'POST',
|
|
171
|
-
headers: { 'content-type': 'application/json' },
|
|
172
|
-
body: JSON.stringify({ token: 'not-a-real-token', message: 'hi' }),
|
|
173
|
-
});
|
|
174
|
-
assert.equal(res.status, 404);
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
// ── TASK_1950: "not installed" redirect (SDK_GUIDE.md §10) ─────────────
|
|
178
|
-
// Uses a short (200ms) timeout rather than the real 8s default so the test
|
|
179
|
-
// runs fast — the logic under test (resolveInstallRedirect /
|
|
180
|
-
// buildInstallRedirectUrl) is pure and timeout-value-agnostic.
|
|
181
|
-
|
|
182
|
-
test('resolveInstallRedirect: no kenaz_hello within the timeout redirects to the install page carrying return=<original deep link>', async () => {
|
|
183
|
-
const deepLink = 'kenaz://connect?site=https%3A%2F%2Fx.example&mcp=https%3A%2F%2Fx.example%2Fmcp&token=abc123';
|
|
184
|
-
const installUrl = 'https://kenaz-install.example/placeholder';
|
|
185
|
-
const timeoutMs = 200;
|
|
186
|
-
const startedAt = Date.now();
|
|
187
|
-
|
|
188
|
-
// Before the timeout elapses: no redirect yet.
|
|
189
|
-
const early = resolveInstallRedirect({ connected: false, startedAt, timeoutMs, installUrl, deepLink });
|
|
190
|
-
assert.equal(early, null, 'must not redirect before the timeout elapses');
|
|
191
|
-
|
|
192
|
-
await new Promise((resolve) => setTimeout(resolve, timeoutMs + 20));
|
|
193
|
-
|
|
194
|
-
const late = resolveInstallRedirect({ connected: false, startedAt, timeoutMs, installUrl, deepLink });
|
|
195
|
-
assert.ok(late, 'expected a redirect URL once the timeout elapses without kenaz_hello');
|
|
196
|
-
const parsed = new URL(late);
|
|
197
|
-
assert.equal(parsed.origin + parsed.pathname, installUrl);
|
|
198
|
-
assert.equal(parsed.searchParams.get('return'), deepLink, 'return= must round-trip the exact original deep link');
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
/// Control group (feedback_probe_needs_control_group): a connected caller
|
|
202
|
-
/// must never be redirected, even long past the timeout — proves the
|
|
203
|
-
/// timeout check isn't the only thing gating the redirect.
|
|
204
|
-
test('control group: resolveInstallRedirect never redirects once connected=true, even past the timeout', () => {
|
|
205
|
-
const deepLink = 'kenaz://connect?site=https%3A%2F%2Fx.example&mcp=https%3A%2F%2Fx.example%2Fmcp&token=abc123';
|
|
206
|
-
const installUrl = 'https://kenaz-install.example/placeholder';
|
|
207
|
-
const startedAt = Date.now() - 10_000; // already well past any short timeout
|
|
208
|
-
|
|
209
|
-
const result = resolveInstallRedirect({ connected: true, startedAt, timeoutMs: 200, installUrl, deepLink });
|
|
210
|
-
assert.equal(result, null);
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
test('buildInstallRedirectUrl encodes the deep link into return= (round-trips through URLSearchParams)', () => {
|
|
214
|
-
const deepLink = 'kenaz://connect?site=https%3A%2F%2Fx.example&token=a+b&prompt=hi%20there';
|
|
215
|
-
const url = buildInstallRedirectUrl('https://kenaz-install.example/placeholder', deepLink);
|
|
216
|
-
const parsed = new URL(url);
|
|
217
|
-
assert.equal(parsed.searchParams.get('return'), deepLink);
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
test('GET / injects the configured install URL + timeout into the connect button data-* attributes', async (t) => {
|
|
221
|
-
const demo = createServer({ port: 0, installUrl: 'https://custom-install.example/x', installTimeoutMs: 4242 });
|
|
222
|
-
await demo.listen();
|
|
223
|
-
t.after(() => demo.close());
|
|
224
|
-
|
|
225
|
-
const res = await fetch(demo.baseUrl);
|
|
226
|
-
const html = await res.text();
|
|
227
|
-
assert.ok(html.includes('data-install-url="https://custom-install.example/x"'));
|
|
228
|
-
assert.ok(html.includes('data-not-installed-timeout-ms="4242"'));
|
|
229
|
-
assert.ok(!html.includes('__KENAZ_INSTALL_URL__'), 'placeholder must be fully substituted');
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
test('GET /install-redirect.js serves the shared pure-function module as JS', async (t) => {
|
|
233
|
-
const demo = createServer({ port: 0 });
|
|
234
|
-
await demo.listen();
|
|
235
|
-
t.after(() => demo.close());
|
|
236
|
-
|
|
237
|
-
const res = await fetch(`${demo.baseUrl}/install-redirect.js`);
|
|
238
|
-
assert.equal(res.status, 200);
|
|
239
|
-
assert.match(res.headers.get('content-type'), /javascript/);
|
|
240
|
-
const body = await res.text();
|
|
241
|
-
assert.ok(body.includes('export function resolveInstallRedirect'));
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
test('the echo demo tool round-trips its argument (proves tools other than kenaz_hello also work)', async (t) => {
|
|
245
|
-
const demo = createServer({ port: 0 });
|
|
246
|
-
await demo.listen();
|
|
247
|
-
t.after(() => demo.close());
|
|
248
|
-
|
|
249
|
-
const connectRes = await fetch(`${demo.baseUrl}/api/connect`, { method: 'POST' });
|
|
250
|
-
const { token } = await connectRes.json();
|
|
251
|
-
|
|
252
|
-
const res = await fetch(`${demo.baseUrl}/mcp`, {
|
|
253
|
-
method: 'POST',
|
|
254
|
-
headers: { 'content-type': 'application/json', authorization: `Bearer ${token}` },
|
|
255
|
-
body: JSON.stringify({
|
|
256
|
-
jsonrpc: '2.0', id: 2, method: 'tools/call',
|
|
257
|
-
params: { name: 'echo', arguments: { text: 'canvas state' } },
|
|
258
|
-
}),
|
|
259
|
-
});
|
|
260
|
-
const body = await res.json();
|
|
261
|
-
const payload = JSON.parse(body.result.content[0].text);
|
|
262
|
-
assert.deepEqual(payload, { echo: 'canvas state' });
|
|
263
|
-
});
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
# Defect Report: 0.2.231 深連結沒帶 `prompt=` 時,claude 分支以空字串 `''` 當第一則訊息啟動 → 互動式 Claude Code 沒有第一個 turn,`kenaz_hello` / `kenaz_wait_for_message` 迴圈永遠不會開始
|
|
2
|
-
|
|
3
|
-
日期:2026-09-09
|
|
4
|
-
來源:FlowPix / GameAsset_auto(Ansuz session,TASK_112 R8「對齊上游 0.2.231」的真實 Kenaz 驗收)
|
|
5
|
-
對應回覆:`KENAZ_RESPONSE_agent-hub_2026-09-09_session-channel.md`(S2 段落:「處理完 `prompt`(沒有 prompt 就直接)→ 反覆呼叫 `kenaz_wait_for_message`」)、`PROTOCOL.md` §2 第 5 點(「`prompt` 為空則直接進入」)
|
|
6
|
-
Kenaz 版本觀察:kenaz-dashboard.exe **0.2.231**(`D:\Users\Wei\AppData\Local\BLOCK ACTION\kenaz-dashboard.exe`,2026-09-09 06:45 啟動);agent=claude,Claude Code v2.1.259。
|
|
7
|
-
|
|
8
|
-
## 一句話
|
|
9
|
-
|
|
10
|
-
S1 header、S5 `--allowedTools`、`.ps1` BOM 修正在 0.2.231 都驗證有效(見「先講好消息」)。但 S2 的前提「網站可以省略 `prompt=`,人格會直接進入迴圈」在 claude 分支**不成立**:沒有 `prompt=` 時,Kenaz 產生的啟動腳本把空字串 `''` 當位置參數傳給 `claude`,Claude Code 以互動模式開啟、停在空的輸入框等使用者打字,**沒有任何一個 turn 發生**,system prompt 裡的「先呼叫 `kenaz_hello`、再反覆呼叫 `kenaz_wait_for_message`」也就永遠不會被執行。FlowPix 端可以自救(送一句固定 ASCII 開場 prompt 當 turn 觸發器,見第 3 節),但這與 S2「網站不需要 prompt 工程」的設計意圖相違,請 Kenaz 側在 `prompt` 為空時自行補一個開場訊息。
|
|
11
|
-
|
|
12
|
-
## 先講好消息:0.2.231 的其他部分都通了
|
|
13
|
-
|
|
14
|
-
同一次啟動(2026-09-09 07:59 本機時間,`[AgentHub] Launched for http://localhost:5173 — agent=claude session=0e76bd42-…`)觀察到:
|
|
15
|
-
|
|
16
|
-
- **亂碼修正**:`%USERPROFILE%\.kenaz\agent_hub\mcp\<id>-<uuid>.ps1` 前三個位元組是 `EF BB BF`(BOM)。前一版留下的舊 `.ps1` 是 `24 45 72`(無 BOM)。與 `KENAZ_RESPONSE_…_prompt-mojibake-fixed.md` 的 D1 一致。
|
|
17
|
-
- **S1**:預配的 MCP JSON `headers` 是 `{"Authorization": "Bearer …", "X-Kenaz-Session": "137c11f5-eef5-4f56-b204-6ae4a3af8fa7"}`;`GET /api/agent-hub/status` 的 origin 底下有 `sessions: [{session_id: "137c11f5-…", pty_session_id: "0e76bd42-…", agent: "claude", model: "claude-sonnet-5", cwd: "D:\\Projects\\Ashfall", started_at, alive: true}]`。與 PROTOCOL §2 第 1b 點及 fixture `mcp.config_with_session_header` 一致。FlowPix bridge 已改成把這個 header 記到 token 上(`GET /kenaz/connect/{token}/status` 多回 `kenaz_session_id`)。
|
|
18
|
-
- **S5**:啟動命令列含 `--allowedTools 'mcp__127__*'`。
|
|
19
|
-
- **人格**:`-persona.txt` 第 133–135 行有 `kenaz_hello` 與 `kenaz_wait_for_message` 的迴圈約定,措辭與 PROTOCOL §2 第 5 點一致。
|
|
20
|
-
|
|
21
|
-
所以 0.2.231 的 S1/S2 人格文字/S5/BOM 四項都到位。以下只有一個問題。
|
|
22
|
-
|
|
23
|
-
## 問題:`prompt` 為空 → `claude … ''` → 沒有第一個 turn
|
|
24
|
-
|
|
25
|
-
### 量到的(逐字)
|
|
26
|
-
|
|
27
|
-
FlowPix 依 S2 的建議把深連結改成**不帶** `prompt=`(`kenaz://connect?site=…&mcp=…&token=…&agent=claude`,142 bytes)。Kenaz 產生的 `.ps1`(token 已遮蔽):
|
|
28
|
-
|
|
29
|
-
```
|
|
30
|
-
claude --mcp-config 'D:\…\kenaz-core\.mcp.json' 'C:\Users\Wei\.kenaz\agent_hub\mcp\<id>.json' --allowedTools 'mcp__127__*' --append-system-prompt-file 'C:\Users\Wei\.kenaz\agent_hub\mcp\<id>-<uuid>-persona.txt' ''
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
最後那個 `''` 就是空的 `prompt`。對照前一版(TASK_110 AC8 那次,有 prompt)的同一行結尾:
|
|
34
|
-
|
|
35
|
-
```
|
|
36
|
-
… -persona.txt' '先呼叫 list_canvases,然後在「生成角色裝備圖」畫布加一個 text_prompt 節點,內容寫 TASK_110 AC8'
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### 使用者看到的
|
|
40
|
-
|
|
41
|
-
- Kenaz 終端分頁:Claude Code v2.1.259 的歡迎畫面(`Opus 5 (1M context) · Claude Max`、`D:\Projects\Ashfall`)與一個空的輸入框,`manual mode on`,靜止不動。
|
|
42
|
-
- FlowPix 面板:「連接中… 等待 Kenaz 連線…」直到 60 秒逾時。
|
|
43
|
-
- FlowPix bridge(`http://127.0.0.1:8790`)存取紀錄:10 筆 `POST /mcp`(MCP initialize / tools/list 握手,`claude` 啟動時做的),**沒有** `kenaz_hello`、沒有 `kenaz_wait_for_message`;`GET /kenaz/connect/{token}/status` 一直是 `connected: false`。
|
|
44
|
-
|
|
45
|
-
### 為什麼
|
|
46
|
-
|
|
47
|
-
`claude` CLI 的位置參數是「第一則使用者訊息」。給空字串等於沒給——CLI 以互動模式起來等使用者輸入,不會自己開始一個 turn。system prompt(`--append-system-prompt-file`)只在有 turn 時才被模型讀到。因此「人格承諾在沒有 prompt 時直接進入迴圈」在機制上做不到:**沒有第一則訊息就沒有第一個 turn**。這不是人格文字的問題,是啟動方式的問題。codex 分支我們沒測;`codex` 的位置參數同樣是第一則訊息,估計行為相同。
|
|
48
|
-
|
|
49
|
-
### 相關但不同層的觀察(順帶)
|
|
50
|
-
|
|
51
|
-
`GET /api/agent-hub/status` 的 `sessions[0].model` 是 `claude-sonnet-5`,但終端分頁的 Claude Code 歡迎畫面顯示 `Opus 5 (1M context)`。可能是 status 回報的是 Kenaz 設定裡的 dispatch model、實際啟動沒有帶 `--model`(命令列裡確實沒有),Claude Code 用了自己的預設。不影響本報告的主題,但 `sessions[].model` 目前不能當作「這個 session 實際跑的模型」來看。
|
|
52
|
-
|
|
53
|
-
## 3. FlowPix 端的自救(已做,2026-09-09)
|
|
54
|
-
|
|
55
|
-
深連結重新帶一句固定的 ASCII `prompt=`,唯一目的是**觸發第一個 turn**,內容只是把人格已經承諾的事再說一次(不含任何 FlowPix 自己的迴圈邏輯):
|
|
56
|
-
|
|
57
|
-
```
|
|
58
|
-
You are connected to FlowPix. Call kenaz_hello now, then keep calling kenaz_wait_for_message and act on each message with the FlowPix canvas tools; after each one, call reply with a short summary.
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
使用者的中文訊息一律走信箱(`POST /kenaz/connect/{token}/messages` → `kenaz_wait_for_message`),與 S2 的設計一致。這樣 FlowPix 不依賴本報告的修正就能運作;但每個接入的網站都得知道「一定要帶 prompt,否則 claude 不會動」,這正是 S2 想避免的 prompt 工程。
|
|
62
|
-
|
|
63
|
-
## 4. 建議(給 Kenaz 側)
|
|
64
|
-
|
|
65
|
-
**D1(必要)**:`launch.rs::build_interactive_script` 在 `prompt` 為空時,**不要**傳 `''`,改傳一句 Kenaz 自己的開場訊息(例如 `Session started by <site origin>. Follow the Kenaz session instructions.`),讓第一個 turn 一定發生。人格裡的「call `kenaz_hello` once before doing anything else with the prompt below」就會照常觸發,S2 的「網站可省略 prompt」才真正成立。codex 分支同理。
|
|
66
|
-
|
|
67
|
-
**D2(建議)**:PROTOCOL §2 第 5 點與 SDK_GUIDE §9 的「`prompt` 省略時就直接進入」旁加註:這由 Kenaz 保證(Kenaz 會補開場訊息),網站不必自己補。
|
|
68
|
-
|
|
69
|
-
**D3(建議)**:`launch.rs` 加一個測試:`prompt = None` 時產出的腳本**不**以 `''` 結尾、而是含 Kenaz 的預設開場訊息。現有的 `build_interactive_script_{claude,codex}_writes_utf8_bom_and_preserves_cjk_prompt` 只覆蓋「有 prompt」的路徑。
|
|
70
|
-
|
|
71
|
-
**D4(順帶)**:`sessions[].model` 若無法保證與實際啟動一致,請回報實際命令列用的模型,或在啟動時真的帶上 `--model`。
|
|
72
|
-
|
|
73
|
-
## 5. 修正後怎麼確認
|
|
74
|
-
|
|
75
|
-
1. 從 FlowPix(或 `examples/minimal-site`)送一條**不帶** `prompt=` 的深連結。
|
|
76
|
-
2. 審批允許後,終端分頁的 Claude Code 應自己開始第一個 turn,並呼叫 `mcp__<name>__kenaz_hello`;網站 MCP 若提供 `kenaz_wait_for_message`,接著應看到它被反覆呼叫(FlowPix bridge 的存取紀錄會出現對應的 `POST /mcp`,`GET /kenaz/connect/{token}/status` 變成 `connected: true`)。
|
|
77
|
-
3. 若 Kenaz 側修好後 FlowPix 就會把第 3 節的開場 prompt 拿掉。
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
# Defect Report: Agent Connect v0.4 深連結的 `prompt=` 進到終端分頁後中文變亂碼(Windows / Big5 環境)
|
|
2
|
-
|
|
3
|
-
日期:2026-09-09
|
|
4
|
-
來源:FlowPix / GameAsset_auto(Ansuz session,TASK_110「FlowPix 接上 Kenaz Agent Connect v0.4」)
|
|
5
|
-
接續:`FEATURE_REQUEST_kenaz-agent-hub_2026-09-08_relay-v1-conformance.md`、`KENAZ_RESPONSE_agent-hub_2026-09-08_...`(v0.4 定稿通知)
|
|
6
|
-
Kenaz 版本觀察:kenaz-dashboard.exe **0.2.230**(`D:\Users\Wei\AppData\Local\BLOCK ACTION\kenaz-dashboard.exe`,2026-09-09 01:56 啟動,使用者環境變數 `KENAZ_AGENT_HUB_DEV=1`)。
|
|
7
|
-
|
|
8
|
-
## 一句話
|
|
9
|
-
|
|
10
|
-
v0.4 的深連結 → 審批卡 → 終端分頁 → `kenaz_hello` 這一整條,FlowPix 用真實 Kenaz 0.2.230 端到端驗通了(見下方「先講好消息」)。唯一的缺陷:深連結 `prompt=` 帶的中文,到了 Kenaz 開的終端分頁裡變成 Big5 解讀 UTF-8 的亂碼;ASCII 部分完整。FlowPix 端送出的深連結已逐字驗證是標準 percent-encoded UTF-8,問題在 Kenaz 把 prompt 交給 CLI 的那一步。**請 Kenaz 側在注入 prompt 時處理 Windows 主控台 codepage。**
|
|
11
|
-
|
|
12
|
-
## 先講好消息:v0.4 在 FlowPix 端到端通了
|
|
13
|
-
|
|
14
|
-
FlowPix 依 `dev/specs/agent-connect/SDK_GUIDE.md` §0/§1/§3 與 `PROTOCOL.md` v0.4 實作(bridge 簽一次性 token、組深連結、`/mcp` 驗 bearer、`kenaz_hello` 回 `{"ok":true}`,面板輪詢 60 秒逾時)。2026-09-09 03:50(本機時間)從 `http://localhost:5173` 按「連接 Kenaz」:
|
|
15
|
-
|
|
16
|
-
- Kenaz 出審批卡,用戶按「允許」→ `GET http://127.0.0.1:18080/api/agent-hub/status` 變成 `{"origins":[{"origin":"http://localhost:5173","state":"once",...}]}`。
|
|
17
|
-
- `backend.stderr.log`:`[AgentHub] Launched for http://localhost:5173 — agent=claude session=12b19338-...`。
|
|
18
|
-
- Dashboard 開了終端分頁,agent 呼叫了 `mcp__127__kenaz_hello`(server 名由 `mcp=http://127.0.0.1:8790/mcp` 的 hostname 衍生成 `127`,與 SDK_GUIDE §3.3 描述一致),FlowPix 面板在幾秒內切成「Kenaz 已連線」。
|
|
19
|
-
- 沒有任何 `[AgentHub] Rejected` 行;dev 模式對 `http://localhost` / `http://127.0.0.1` 的放寬如 §5 所述生效。
|
|
20
|
-
|
|
21
|
-
所以深連結格式、審批卡、MCP 預配、`kenaz_hello` 慣例都符合文件。以下只有一個問題。
|
|
22
|
-
|
|
23
|
-
## 問題:`prompt=` 的中文在終端分頁裡是亂碼
|
|
24
|
-
|
|
25
|
-
### 用戶看到的(Kenaz 終端分頁的第一則訊息,截圖逐字)
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
?��??list_canvases曝��敺��?�??�??脰??�??��撣�?鉾??text_prompt 蜓暉�??批捆撤?TASK_110 AC8
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
FlowPix 送出的原文:
|
|
32
|
-
|
|
33
|
-
```
|
|
34
|
-
先呼叫 list_canvases,然後在「生成角色裝備圖」畫布加一個 text_prompt 節點,內容寫 TASK_110 AC8
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
ASCII 片段(`list_canvases`、`text_prompt`、`TASK_110 AC8`)完整無缺,只有 CJK 壞掉;壞法是「每個三位元組的 UTF-8 字元變成一個 Big5 雙位元組字加一個 `?`/`�`」——這是 UTF-8 位元組被當成 CP950 解讀的典型樣子,不是 URL 解碼錯(URL 解碼錯會出現 `Ã¥` 那種 Latin-1 樣式)。
|
|
38
|
-
|
|
39
|
-
### FlowPix 端已排除(可重現)
|
|
40
|
-
|
|
41
|
-
深連結由 FlowPix bridge 的 `urllib.parse.urlencode`(`quote_plus`)組出,在瀏覽器裡攔下實際送出的 URL 檢查:
|
|
42
|
-
|
|
43
|
-
- `new URL(deeplink).searchParams.get('prompt') === 原文` → `true`(UTF-8 percent-encoding 正確往返)。
|
|
44
|
-
- `prompt=` 的前三個位元組是 `%E5%85%88`(=「先」的 UTF-8)。
|
|
45
|
-
- 整條深連結 420 bytes,`scheme=kenaz:`、`host=connect`、無 `v=`、無 `agent=`(用「依 Kenaz 預設」)。
|
|
46
|
-
|
|
47
|
-
這就是 SDK_GUIDE §2「URL 編碼規則:每個參數值都要 encodeURIComponent」的做法;FlowPix 沒有別的方式可以送中文。
|
|
48
|
-
|
|
49
|
-
### 本機環境(Kenaz 重現時要對齊的變數)
|
|
50
|
-
|
|
51
|
-
| 項目 | 值 |
|
|
52
|
-
|---|---|
|
|
53
|
-
| OS | Windows 11 Pro 10.0.26200 |
|
|
54
|
-
| 系統 ANSI / OEM codepage | `ACP=950`、`OEMCP=950`(繁中 Big5) |
|
|
55
|
-
| PowerShell `[Console]::InputEncoding` / `OutputEncoding` | `big5` / `big5` |
|
|
56
|
-
| Culture / UICulture | `en-US` / `zh-TW` |
|
|
57
|
-
| `claude` 解析到的執行檔 | `C:\Users\Wei\AppData\Roaming\npm\claude.ps1`(npm 的 PowerShell shim),`claude --version` = `2.1.259` |
|
|
58
|
-
| 使用的 agent | `agent=` 省略 → Kenaz 預設,實際啟動 claude |
|
|
59
|
-
|
|
60
|
-
### 推測的出錯點(Rust 原始碼不在這台機器,請以原始碼核對)
|
|
61
|
-
|
|
62
|
-
深連結在 `deep_link.rs` 用 `Url` 解析,`prompt` 進到 Rust 時應已是正確的 UTF-8 `String`(否則 ASCII 也不會完整)。壞掉發生在「把 prompt 交給 CLI」這一步,兩種可能:
|
|
63
|
-
|
|
64
|
-
1. **prompt 以 argv 傳給 `claude`**:`claude` 在這台機器解析到 `claude.ps1`,經 `powershell.exe` 轉手時參數以 ANSI codepage(950)重新編碼,或是 spawn 用了 ANSI 版 API。
|
|
65
|
-
2. **prompt 以按鍵/stdin 方式寫進終端分頁(PTY)**:Kenaz 寫入的是 UTF-8 位元組,但該主控台的輸入 codepage 是 950(Windows 預設跟著 OEMCP),shell/CLI 以 Big5 解讀。
|
|
66
|
-
|
|
67
|
-
### 需求
|
|
68
|
-
|
|
69
|
-
**D1(必要)**:在 Windows 上讓 `prompt=` 的非 ASCII 內容原樣到達 agent。可行做法擇一:
|
|
70
|
-
- 注入前先把該終端分頁的 codepage 設成 UTF-8(等同 `chcp 65001`,或 `SetConsoleCP/SetConsoleOutputCP(65001)`),再寫入 UTF-8 位元組;
|
|
71
|
-
- 或依目前主控台的輸入 codepage 轉碼後再寫入;
|
|
72
|
-
- 或不經 argv/PTY 文字,改把 prompt 寫進 UTF-8 暫存檔、以 `claude -p`/`codex exec` 的檔案或 stdin 方式餵入(`codex exec` 本來就支援 stdin prompt);
|
|
73
|
-
- 若走 argv,直接 spawn `node <claude cli.js>` 或 `claude.cmd`,避開 `claude.ps1` 這層 PowerShell shim,並用寬字元 CreateProcessW。
|
|
74
|
-
|
|
75
|
-
**D2(建議)**:SDK_GUIDE §2「長度限制」旁補一句「`prompt` 支援任意 UTF-8,Windows 上由 Kenaz 負責 codepage」,讓網站開發者不用自己猜要不要先轉成 ASCII。
|
|
76
|
-
|
|
77
|
-
**D3(建議)**:conformance suite(`dashboard/scripts/agent-connect-conformance/run.mjs`)加一個含 CJK 的 `deep_link.*` fixture,並在 Windows CI 上驗「agent 收到的第一則訊息 == fixture 的 prompt」。
|
|
78
|
-
|
|
79
|
-
### 影響
|
|
80
|
-
|
|
81
|
-
FlowPix 的產品設計(用戶決定,2026-09-09)是「生圖改成 prompt 裡描述,agent 用 FlowPix 的 MCP 工具產出並寫回畫布」,用戶是中文使用者,`prompt=` 幾乎一定含中文。目前 workaround 只有把 prompt 限制成英文,或改成「深連結只帶一句英文、真正的指示放進 FlowPix MCP 的工具讓 agent 自己拿」——後者 SDK_GUIDE §2 本來就建議用於長內容,FlowPix 可以做,但短中文 prompt 壞掉仍是 Kenaz 端該修的。
|
|
82
|
-
|
|
83
|
-
## 怎麼重現(Kenaz 側)
|
|
84
|
-
|
|
85
|
-
1. Windows、系統語言繁中(ACP 950),`KENAZ_AGENT_HUB_DEV=1` 完整重啟 Kenaz 0.2.230。
|
|
86
|
-
2. `cd D:\Projects\GameAsset_auto && .\dev.ps1`(或只起 bridge `python -m uvicorn bridge.main:app --port 8790` + `cd editor && npx vite --port 5173`)。
|
|
87
|
-
3. 瀏覽器開 `http://localhost:5173`,工具列右下「連接 Kenaz」→ 在「要 agent 做什麼」輸入任何中文 → 按「連接 Kenaz」→ 審批卡按允許。
|
|
88
|
-
4. 看終端分頁的第一則訊息;同時 FlowPix 面板應顯示「Kenaz 已連線」(證明其餘流程正常)。
|
|
89
|
-
|
|
90
|
-
沒有 Kenaz 也能看到 FlowPix 送了什麼:`curl -X POST http://127.0.0.1:8790/kenaz/connect -H 'content-type: application/json' -d '{"site":"http://localhost:5173","prompt":"測試"}'`,回應的 `deeplink` 裡 `prompt=%E6%B8%AC%E8%A9%A6`。
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
# Feature Request: Kenaz 作為網站可喚起的本機 Agent(Agent Hub)
|
|
2
|
-
|
|
3
|
-
日期:2026-09-07
|
|
4
|
-
來源:FlowPix / GameAsset_auto(Ansuz session)
|
|
5
|
-
Kenaz 版本觀察:kenaz-dashboard.exe 0.2.228,本機 MCP 於 `http://localhost:18080/api/mcp`,**尚未註冊任何 URL 協定**(HKCU/HKLM `Software\Classes` 皆無 `kenaz`)。
|
|
6
|
-
|
|
7
|
-
## 目標(一句話)
|
|
8
|
-
|
|
9
|
-
雲端網站(第一個是 FlowPix)按「連接 Kenaz」就能喚起用戶電腦上的 Kenaz,之後網站的 AI 生成請求由 Kenaz 用**用戶自己的 Codex(ChatGPT 訂閱)**執行,用戶在 Kenaz 的彈窗裡審批。網站與伺服器永遠碰不到用戶的憑證,也不付 AI 的錢。體驗對齊 Web3「連接錢包」:連接一次、每次操作審批、可設「此網站永遠允許」。
|
|
10
|
-
|
|
11
|
-
## 美術人員看到的流程(驗收基準)
|
|
12
|
-
|
|
13
|
-
1. 網站按「連接 Kenaz」→ 若未安裝,導到下載頁;一鍵安裝。
|
|
14
|
-
2. 瀏覽器詢問「要開啟 Kenaz 嗎?」→ 確定 → 網站顯示「已連線」。
|
|
15
|
-
3. 第一次生成 → Kenaz 開啟 ChatGPT 登入頁(內部是 `codex login`)→ 登入完成。
|
|
16
|
-
4. 之後每次生成 → 右下角彈窗「flowpix.app 要用你的 Codex 生成 1 張圖:允許/此網站永遠允許/拒絕」。
|
|
17
|
-
|
|
18
|
-
沒有終端、沒有 token、沒有 Node、沒有 git。
|
|
19
|
-
|
|
20
|
-
## Kenaz 側要新增的能力
|
|
21
|
-
|
|
22
|
-
| # | 能力 | 說明 | 現況 |
|
|
23
|
-
|---|---|---|---|
|
|
24
|
-
| K1 | `kenaz://` URL 協定 | 安裝程式註冊(Windows:`HKCU\Software\Classes\kenaz`,`URL Protocol` + `shell\open\command`;macOS:`CFBundleURLTypes`)。Tauri 2 有 `tauri-plugin-deep-link`,含單一實例轉發(已在跑的 Kenaz 收到 URL 而不是再開一個)。 | 缺 |
|
|
25
|
-
| K2 | 配對與對外連線 | 處理 `kenaz://connect?site=<origin>&token=<一次性>&relay=<wss url>`:以 token 向 relay 換取 session 憑證,之後**主動**維持一條 WSS 到 relay(用戶端只做對外連線;防火牆友善)。斷線退避重連。 | 缺 |
|
|
26
|
-
| K3 | 站點權限與審批 UI | 每個 origin 一筆授權紀錄(未授權/單次/永遠允許/封鎖)。收到需要審批的請求時彈原生視窗或 toast,含請求摘要(哪個網站、做什麼、預估數量)。審批結果與狀態要回報給網站(見協定 `approval/*`)。 | 缺 |
|
|
27
|
-
| K4 | Codex 驅動(app-server) | 由 Kenaz 啟動並持有 `codex app-server --listen ws://127.0.0.1:<port>`,以 JSON-RPC 走 `initialize` → `thread/start {ephemeral:true, sandbox:"read-only", approvalPolicy:"never"}` → `turn/start`;`item/completed` 的 `imageGeneration` item 帶 `result`(base64 PNG)與 `savedPath`;`account/rateLimits/updated` 回報訂閱用量。已在 FlowPix 實測:一輪約 35 秒;**app-server 對任何帶 Origin 的握手回 403,所以只能由 Kenaz 這種本機程序連,網頁不可能直連**。參考:GameAsset_auto 的 rune `rune_545535f080244e4084d1573309bfc4e3`、`rune_f352dc3d2dce4dc2969fa6a769da371b`。 | Kenaz 已能派工給 Codex(formation adapter),但不是這條長連線協定 |
|
|
28
|
-
| K5 | Codex 執行檔與登入 | 隨附 Codex 執行檔(`@openai/codex` 為 Apache-2.0,npm 套件內含各平台二進位),不要求用戶裝 Node;首次使用由 Kenaz 觸發 `codex login`(開瀏覽器),並偵測 `codex login status` 是否「Logged in」。 | 缺 |
|
|
29
|
-
| K6 | 極簡 bundle | 同一 Tauri 程式碼庫用 feature flag 切出「FlowPix Agent」bundle:只有 tray、深連結、K2–K5,沒有 Dashboard 介面。完整版 Kenaz Dashboard 內含同一模組。 | 缺 |
|
|
30
|
-
| K7 | tray、開機自啟、自動更新 | `tauri-plugin-autostart`、`tauri-plugin-updater`;更新來源可放靜態空間(Cloudflare Pages)。 | 未核實(原始碼不在本機) |
|
|
31
|
-
| K8 | 依用戶選擇啟動 CLI Agent(**用戶 2026-09-07 追加,核心需求**) | 深連結多帶 `agent=claude\|codex`(可再帶 `task=<id>` 或初始 prompt)。Kenaz 喚起後啟動用戶選的 CLI:`claude`(Claude Code)或 `codex`,並**預先接好 FlowPix 的 MCP 端點與這次配對的憑證**(Claude:`claude mcp add --transport http flowpix <url> --header "Authorization: Bearer <session>"` 的等價設定;Codex:`mcp_servers.flowpix.url` + bearer env),讓 Agent 一啟動就能用 FlowPix 的畫布工具集(list_canvases…focus_canvas)與生成。兩種模式:`interactive`(開一個終端視窗,用戶看得到、能對話)與 `headless`(Kenaz 代跑 `claude -p` / `codex exec`,結果回網站)。Kenaz 既有的 Claude/Codex dispatch adapter 可重用。生圖仍走 K4 的 Codex;選 Claude Code 時 Claude 負責畫布協作、生圖節點由 Kenaz 交給 Codex。若所選 CLI 未安裝或未登入,回報 `agent_unavailable` 並在 Kenaz 內引導安裝/登入。 | Kenaz 已能派工給兩者,但沒有「從深連結參數啟動並預配 MCP」 |
|
|
32
|
-
|
|
33
|
-
## 協定契約(Relay v1,Kenaz 與網站雙方都照這份實作)
|
|
34
|
-
|
|
35
|
-
> **定稿位置(2026-09-07 更新)**:FlowPix repo `D:/Projects/GameAsset_auto/bridge/CONTRACT.md` 的「Relay v1」章節,已由 spike TASK_105 用真實 Codex 端到端驗通(relay 訊息 17 則、最大 300 bytes,圖片走 blobstore URL;token 一次性/60 秒/綁 origin 三種拒絕都有測試;Claude Code 與 Codex 兩種 CLI 都能由 agent.launch 啟動並用預配的 MCP 在畫布加節點)。K1–K8 對照表在 `spikes/relay_spike/NOTES.md`。假 Kenaz 的參考實作:`bridge/agent_relay_client.py`(Python,Kenaz 以 Rust 重寫時逐訊息對照)。下面的骨架以那份為準。
|
|
36
|
-
|
|
37
|
-
由 FlowPix 側先用現有的 Python bridge 當「假 Kenaz」驗通,再由 Kenaz 以 Rust 實作。定稿版本會放在 FlowPix repo `bridge/CONTRACT.md` 的「Relay v1」章節,這裡先列骨架:
|
|
38
|
-
|
|
39
|
-
- 傳輸:WSS,JSON 訊息,每則含 `type`、`request_id`(呼叫/回應配對),大於 1 MB 的圖片以物件儲存(R2/GCS)presigned URL 傳遞而非內嵌。
|
|
40
|
-
- 配對:`pair.begin {token}` → `pair.ok {session_credential, site_origin}`;token 一次性、60 秒 TTL、綁定 origin。
|
|
41
|
-
- 狀態:`agent.status {codex_logged_in, rate_limits?, approval_mode}` 主動推送。
|
|
42
|
-
- 請求(relay → Kenaz):`generate_image {prompt, size, quality, reference_images:[url]}`、`generate_text {...}`;FlowPix 的畫布工具集(`list_canvases`…`focus_canvas`,見 Agent hub v1)保留給本機 CLI Agent 路徑,不經 relay。
|
|
43
|
-
- 審批:Kenaz 在執行前推 `approval.pending {request_id, summary}`,用戶決定後推 `approval.resolved {request_id, decision}`,網站據此顯示「等待你在 Kenaz 允許」。
|
|
44
|
-
- 結果:`result {request_id, ok, payload | error:{code,message}}`;錯誤碼含 `not_logged_in`、`usage_limit_exceeded`(附 resetsAt)、`denied`、`timeout`。
|
|
45
|
-
- 安全:Kenaz 只做對外連線;憑證不離開本機;session 憑證可由用戶在 Kenaz 內撤銷;每個 origin 獨立授權。
|
|
46
|
-
|
|
47
|
-
## 已知限制(先講清楚)
|
|
48
|
-
|
|
49
|
-
- Codex 內建 `image_gen` 對**正方形**尺寸一律回 1254x1254(非正方形照做);網站端要能接受實際尺寸。
|
|
50
|
-
- Codex 的 `remote-control` 是 OpenAI 自家客戶端的中繼,對第三方不開放;若未來開放,K2 的 relay 可換成它。
|
|
51
|
-
- 一台機器同時開多個網站分頁時,審批要能標明是哪個 origin 的哪個請求。
|
|
52
|
-
|
|
53
|
-
## FlowPix 側對應工作(不需 Kenaz 動手)
|
|
54
|
-
|
|
55
|
-
- 雲端 backend:引擎跑到 AI 節點時暫停、把請求經 relay 送到該用戶的 Kenaz、收到結果續跑(Ansuz 建為 spike 卡)。
|
|
56
|
-
- 網站:「連接 Kenaz」按鈕(喚起 `kenaz://connect?...`)、連線與審批狀態顯示、未安裝時的下載導引。
|
|
57
|
-
- relay 服務:先用本機 Node ws 原型,通了再放雲端。
|
|
58
|
-
|
|
59
|
-
## 聯絡點
|
|
60
|
-
|
|
61
|
-
FlowPix 側的既有實作可直接參考:`bridge/`(provider 插槽、Agent hub、Codex 呼叫)、`spikes/ai_bridge/`、`spikes/agent_hub/`。
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# Defect / Change Request: Agent Hub 與 Relay v1 合約不一致,且本機開發環境無法配對
|
|
2
|
-
|
|
3
|
-
日期:2026-09-08
|
|
4
|
-
來源:FlowPix / GameAsset_auto(Ansuz session)
|
|
5
|
-
接續:`FEATURE_REQUEST_kenaz-agent-hub_2026-09-07.md`(K1–K8)
|
|
6
|
-
Kenaz 版本觀察:kenaz-dashboard.exe **0.2.229**(`D:\Users\Wei\AppData\Local\BLOCK ACTION\kenaz-dashboard.exe`,2026-09-08 06:05 建置),`GET /api/health` 回 `"version":"0.2.229"`。
|
|
7
|
-
|
|
8
|
-
## 一句話
|
|
9
|
-
|
|
10
|
-
K1 已通(`kenaz://` 到得了正在跑的 Kenaz),但 Agent Hub 在撥 relay 之前就用三道 scheme 閘門把本機開發環境擋掉;而且 exe 內的訊息型別與 FlowPix 的定稿合約 `D:/Projects/GameAsset_auto/bridge/CONTRACT.md`「Relay v1」章節有多處欄位漂移。**請 Kenaz 側對齊合約**(合約是 2026-09-07 用真實 Codex 端到端驗通的版本,FlowPix 的 backend / relay / 假 Kenaz 三方都以它為準,`test_relay_contract.py` 鎖住),並提供 loopback 開發模式。
|
|
11
|
-
|
|
12
|
-
## 怎麼測的(可重現)
|
|
13
|
-
|
|
14
|
-
1. 起 FlowPix 的 relay 原型:`node spikes/relay_spike/relay.mjs --port 8791 --log <path>`(relay 會把每一則 frame 的方向 / type / bytes 記成 JSONL)。
|
|
15
|
-
2. 以「site」角色連上 relay:`site.hello {origin}` → `token.mint {agent:null}` → 拿到一次性 token,組出深連結。
|
|
16
|
-
3. 開深連結(兩種方式都試過):`os.startfile("kenaz://connect?...")`(走 OS 協定處理器),以及直接 `kenaz-dashboard.exe "kenaz://connect?..."`。
|
|
17
|
-
4. 觀察三處:relay 的 frame log、`GET http://localhost:18080/api/agent-hub/status`、`C:\Users\Wei\AppData\Local\Kenaz Dashboard\backend.stderr.log`。
|
|
18
|
-
|
|
19
|
-
三次結果:relay **從未**收到任何來自 Kenaz 的連線(frame log 只有 site 自己的 4 則);`/api/agent-hub/status` 始終 `{"origins":[],"relay":{"status":"disconnected"}}`;stderr log 出現:
|
|
20
|
-
|
|
21
|
-
```
|
|
22
|
-
[AgentHub] Rejected deep link (site scheme not allowed: http): kenaz://connect/?site=http%3A%2F%2F127.0.0.1%3A5173&token=...&relay=ws%3A%2F%2F127.0.0.1%3A8791%2Fws
|
|
23
|
-
[AgentHub] Rejected deep link (site scheme not allowed: http): kenaz://connect?site=http%3A%2F%2F127.0.0.1%3A5173&token=...&relay=ws%3A%2F%2F127.0.0.1%3A8791%2Fws
|
|
24
|
-
[AgentHub] Rejected deep link (relay scheme not allowed: ws): kenaz://connect?site=https%3A%2F%2F127.0.0.1%3A5173&token=...&relay=ws%3A%2F%2F127.0.0.1%3A8791%2Fws
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
(第一行的 `connect/?` 是 OS 協定處理器正規化加的斜線,Kenaz 兩種寫法都有正確解析,這點沒問題。)
|
|
28
|
-
|
|
29
|
-
## 問題 1:三道 scheme 閘門讓本機開發完全無法配對(阻斷)
|
|
30
|
-
|
|
31
|
-
exe 內有三個拒絕訊息:`site scheme not allowed: `、`relay scheme not allowed: `、`mcp scheme not allowed: `。FlowPix 開發環境是 editor `http://localhost:5173`、relay `ws://127.0.0.1:8791/ws`、bridge MCP `http://127.0.0.1:8790/mcp`,三個都會被擋。
|
|
32
|
-
|
|
33
|
-
**需求 D1**:提供開發模式豁免,只對 loopback 生效(`127.0.0.1` / `localhost` / `[::1]`),允許 `http` / `ws`。建議形式:環境變數(例如 `KENAZ_AGENT_HUB_ALLOW_INSECURE_LOOPBACK=1`)或 Dashboard 設定開關,預設關閉。正式環境維持 https / wss 強制,這點我們同意。
|
|
34
|
-
**需求 D2**:拒絕深連結時,除了寫 stderr,也要把原因顯示給用戶(toast 或 Dashboard 內通知)。現在網站端只看到「已開啟 Kenaz」但永遠不會變成「已連線」,用戶無從得知是哪裡被擋。
|
|
35
|
-
|
|
36
|
-
## 問題 2:訊息型別與 Relay v1 合約漂移
|
|
37
|
-
|
|
38
|
-
以下「Kenaz 實作」欄位是從 0.2.229 exe 的 serde 字串表還原(`internally tagged enum AgentHubMessage`,欄位名與 `struct variant ... with N elements` 的 N),因為 Rust 原始碼不在這台機器上;請以原始碼核對,但欄位名本身是實際存在於二進位裡的。
|
|
39
|
-
|
|
40
|
-
| 訊息 | Relay v1 合約(CONTRACT.md §) | Kenaz 0.2.229 實作 | 需求 |
|
|
41
|
-
|---|---|---|---|
|
|
42
|
-
| 配對拒絕 | `pair.denied {request_id, error:{code,message}}`(§3),code ∈ token_invalid / token_expired / token_already_used / origin_mismatch / relay_unavailable | `pair.error {request_id, code, message}`(3 elements) | **D3** 改回 `pair.denied`,error 包在 `error` 物件內。相關字串 `timeout waiting for pair.ok/pair.error` 一併改。 |
|
|
43
|
-
| 狀態推送 | `agent.status {request_id:null, codex_logged_in, rate_limits, approval_mode}`(§4) | `agent.status {agents, dispatch, approval_mode, ...}`(4 elements) | **D4** 至少保留 `codex_logged_in`(bool)與 `rate_limits`(nullable);`agents` / `dispatch` 可以額外附加,FlowPix 會忽略未知欄位。 |
|
|
44
|
-
| 生圖請求 | `generate_image {request_id, prompt, size, quality, reference_images:[url]}`(§5) | `generate_image {request_id, prompt, input_url}`(3 elements) | **D5** 接受合約的 `size` / `quality` / `reference_images[]`(多張參考圖是 FlowPix 既有節點的真實需求)。`input_url` 單張欄位若要保留可當 alias。 |
|
|
45
|
-
| 生文請求 | `generate_text {request_id, prompt, system, model, max_output_tokens, reasoning_effort, reference_images:[url]}`(§5) | `generate_text {request_id, prompt}`(2 elements) | **D6** 接受合約欄位(至少 `system`、`max_output_tokens`、`reference_images`)。若 serde 用 `deny_unknown_fields`,現在合約訊息會直接被拒。 |
|
|
46
|
-
| 生成結果 | `result {request_id, ok, payload}`;image payload `{url, width, height, provider, elapsed_ms, meta}`、text payload `{text, provider, elapsed_ms, meta}`(§7) | `result {request_id, ok, ...}`(4 elements);另有 hub prompt 要求 agent 寫 `{ok, text, artifacts:[{url,kind}]}` | **D7** `generate_*` 的 result 請照 §7 的 payload 形狀;`{ok,text,artifacts}` 只用於 `agent.launch` 的回覆即可。**圖片一律走 URL**(relay 有 256 KiB 單則上限,§Transport)。 |
|
|
47
|
-
| 錯誤碼 | not_logged_in / usage_limit_exceeded(+resetsAt) / denied / timeout / relay_unavailable / payload_too_large(§7) | denied / agent_unavailable / mcp_config_failed / launch_failed / timeout | **D8** 補 `not_logged_in` 與 `usage_limit_exceeded {resetsAt}`(網站要據此顯示「請先登入 ChatGPT」/「用量已達上限,xx 時重置」)。新增的三個碼我們會接受。 |
|
|
48
|
-
| Agent 啟動 | Kenaz → 網站的**公告**:`agent.launch {agent, mode, prompt}` → `agent.launched {agent, pid}` \| `agent_unavailable {agent, reason}`(§8);由深連結的 `agent=` 觸發 | 網站 → Kenaz 的**請求**:`agent.launch {request_id, agent, model?, prompt, mcp, cwd}`(6 elements),以 `result` 回覆 | **D9** 兩種語意都可以,但要二選一並寫進合約。若 Kenaz 堅持「網站請求」語意,請告知確切欄位與 `result` 形狀,FlowPix 會改 backend;深連結的 `agent=` 參數仍要能在配對成功後自動啟動一次(美術人員按一次「連接」就該看到 CLI 起來,這是 K8 的核心體驗)。 |
|
|
49
|
-
| 配對成功 | `pair.ok {request_id, session_credential, site_origin}`(§3) | `pair.ok`(3 elements,含 `session_credential`) | 看起來一致,請確認。 |
|
|
50
|
-
| 審批 | `approval.pending {request_id, summary}` / `approval.resolved {request_id, decision}`(§6) | 同名同欄位數 | 一致。 |
|
|
51
|
-
|
|
52
|
-
## 問題 3:深連結多了 `mcp` 參數,合約沒有
|
|
53
|
-
|
|
54
|
-
Kenaz 的 `agent_hub/sites.json` 每筆有 `origin, session_credential, relay_url, paired_at, last_used_at, mcp_url, last_agent` 與權限 `unauthorized | once | always`(K3 的持久化權限表,很好)。`mcp_url` 顯然來自深連結的 `mcp=` 參數,合約的深連結只有 `site / token / relay / agent`(§2)。
|
|
55
|
-
|
|
56
|
-
**需求 D10**:請確認 `mcp=` 是否必填、以及 `mcp` 缺席時是否仍能完成配對與 `generate_*`(生圖不需要 MCP)。FlowPix 願意加 `mcp=<bridge /mcp url>`,但它必須是**選填**,且受問題 1 的 loopback 豁免(開發時是 `http://127.0.0.1:8790/mcp`)。合約會在你們確認後更新 §2。
|
|
57
|
-
|
|
58
|
-
## 有做對的(不用改)
|
|
59
|
-
|
|
60
|
-
- K1:`tauri-plugin-deep-link` + single-instance 轉發正常,兩種喚起方式都到達正在跑的實例。
|
|
61
|
-
- K3:`sites.json` 的 per-origin 權限模型(`unauthorized | once | always`)符合需求。
|
|
62
|
-
- K8:core 腳本端 `hub` formation(`.formation/unit/hub.yaml`)+ `headless.js --mcp-config-extra / --allowed-tools` + `relay.js buildCodexMcpOverrides`(bearer 走環境變數,不進 `-c` 字面值)——設計正確,測試也在。
|
|
63
|
-
- TLS:native-tls / schannel,正式環境的 wss 憑證鏈不會有問題。
|
|
64
|
-
|
|
65
|
-
## 驗收方式(Kenaz 修完後 FlowPix 這邊會跑)
|
|
66
|
-
|
|
67
|
-
1. `KENAZ_AGENT_HUB_ALLOW_INSECURE_LOOPBACK=1` 下,用上面的重現步驟,relay frame log 要出現 Kenaz 的 `pair.begin` → relay 回 `pair.ok` → Kenaz 推 `agent.status`,`/api/agent-hub/status` 的 `origins` 出現 `https?://127.0.0.1:5173`。
|
|
68
|
-
2. 送一則合約形狀的 `generate_text`,Kenaz 要先推 `approval.pending`(在做任何事之前),用戶允許後推 `approval.resolved`,最後 `result.ok=true` 且 `payload.text` 有值。
|
|
69
|
-
3. 送一則帶兩張 `reference_images` URL 的 `generate_image`,`result.payload.url` 可下載、`width/height` 為實際尺寸。
|
|
70
|
-
4. 錯誤 token 重放:relay 回 `pair.denied {error.code:"token_already_used"}`,Kenaz 要正確解析並顯示,而不是 `timeout waiting for pair.ok/pair.error`。
|
|
71
|
-
|
|
72
|
-
## 聯絡點
|
|
73
|
-
|
|
74
|
-
- 合約:`D:/Projects/GameAsset_auto/bridge/CONTRACT.md`「Relay v1」章節(欄位名逐一對照;`spikes/relay_spike/test_contract_consistency.py` 鎖三方一致)。
|
|
75
|
-
- 參考實作:`bridge/agent_relay_client.py`(假 Kenaz,逐訊息對照)、`spikes/relay_spike/relay.mjs`(token 一次性 / 60 秒 / 綁 origin 的參考行為)。
|
|
76
|
-
- 本次探針腳本與 relay frame log:Ansuz session scratchpad `site_probe.py`、`relay_frames.jsonl`、`probe1..3.log`(需要可再提供)。
|