#!/usr/bin/env node const assert = require("assert"); const fs = require("fs"); const path = require("path"); const repo = path.resolve(__dirname, ".."); function read(relativePath) { const fullPath = path.join(repo, relativePath); if (!fs.existsSync(fullPath)) { if (fs.existsSync(path.join(repo, "DISASMER_PUBLIC_TREE.json"))) { console.log( `CLI-first contract smoke skipped: ${relativePath} is filtered from this public tree` ); process.exit(0); } throw new Error(`${relativePath} is missing`); } return fs.readFileSync(fullPath, "utf8"); } function criterionLines(source) { return source .split(/\r?\n/) .filter((line) => /^- \[[ x]\] \*\*/.test(line)); } function expect(source, name, pattern) { assert.match(source, pattern, `missing CLI-first contract evidence: ${name}`); } const criteria = read("cli_acceptance_criteria.md"); const cli = read("crates/disasmer-cli/src/main.rs"); const coordinator = read("crates/disasmer-coordinator/src/service.rs"); const cliFirstAcceptance = read("scripts/acceptance-cli-first.sh"); const outputModeSmoke = read("scripts/cli-output-mode-smoke.js"); const errorExitSmoke = read("scripts/cli-error-exit-smoke.js"); const browserLoginFlowSmoke = read("scripts/cli-browser-login-flow-smoke.js"); expect(criteria, "header", /^# Disasmer CLI-First MVP Acceptance Criteria/m); expect( criteria, "addendum status", /\*\*Status:\*\* CLI-first addendum to `acceptance_criteria\.md` and `acceptance_criteria_phase2\.md`/ ); expect( criteria, "website exception", /hosted account creation as the only intentional private website exception/ ); expect( criteria, "no duplicate work note", /does not automatically mean new product code, a new feature, or even actual implementation work is required/ ); expect( criteria, "future hosted business non-goal", /billing, paid-plan checkout, team\/org management, provider setup wizards, secret-manager UI, full support tooling, broad moderation consoles, and durable account\/business-process management are intentionally outside this CLI-first MVP slice/ ); const lines = criterionLines(criteria); assert(lines.length > 0, "CLI-first criteria must contain criteria lines"); for (const line of lines) { assert.match( line, /^- \[[ x]\] \*\*(Passed|Partial|Open|Postponed)(?: \([^)]+\))?:\*\*/, `CLI-first criterion lacks an explicit status prefix: ${line}` ); } const openCriteria = lines.filter((line) => /\*\*Open(?::| \()/.test(line)); assert.deepStrictEqual( openCriteria, [], "CLI-first criteria should not leave Open items once the non-e2e gate exists; remaining unfinished facts stay Partial" ); expect( criteria, "CLI-first non-e2e gate wording", /scripts\/acceptance-cli-first\.sh[\s\S]*final public-release e2e remains intentionally excluded/ ); expect( criteria, "artifact export explicit local byte write", /artifact export --to ` writes bytes[\s\S]*explicit bounded download stream[\s\S]*complete staged content is available/ ); expect( criteria, "locality failure safe guidance", /If direct transfer or locality assumptions fail[\s\S]*connectivity-category safe failures[\s\S]*coordinator bulk relay was not used/ ); expect( criteria, "mutating commands require confirmation", /Mutating or dangerous commands support `--yes`[\s\S]*confirmation-required safe failure[\s\S]*do not send coordinator requests/ ); expect( criteria, "log redaction criteria", /Logs are capped, truncated honestly[\s\S]*preserve byte counts and truncation flags[\s\S]*Secret-like values are redacted[\s\S]*common token\/password\/bearer patterns/ ); expect( criteria, "doctor node readiness criteria", /`disasmer doctor` reports missing local dependencies[\s\S]*explicit node readiness summary[\s\S]*missing local dependencies[\s\S]*node next actions/ ); expect( criteria, "admin bootstrap self-hosted sequence criteria", /admin bootstrap now reports a CLI-only self-hosted sequence[\s\S]*node enrollment\/attach[\s\S]*quota status[\s\S]*node revoke/ ); expect( criteria, "quota resource-category criteria", /Hitting a quota produces a clear error[\s\S]*resource category[\s\S]*private abuse heuristics[\s\S]*quota machine errors now extract the resource category/ ); expect( cliFirstAcceptance, "CLI-first acceptance report", /node scripts\/acceptance-report\.js cli-first/ ); expect( cliFirstAcceptance, "CLI-first acceptance refuses final e2e", /DISASMER_PUBLIC_RELEASE_DRYRUN_E2E[\s\S]*does not run final public-release e2e/ ); expect( cliFirstAcceptance, "CLI-first acceptance refuses final evidence", /DISASMER_PUBLIC_RELEASE_DRYRUN_FINAL[\s\S]*does not run final public-release evidence/ ); expect( cliFirstAcceptance, "CLI-first acceptance composes public API contracts", /node scripts\/cli-output-mode-smoke\.js[\s\S]*node scripts\/cli-login-smoke\.js[\s\S]*node scripts\/cli-error-exit-smoke\.js[\s\S]*node scripts\/cli-browser-login-flow-smoke\.js/ ); expect( cliFirstAcceptance, "CLI-first acceptance composes service boundary checks", /node scripts\/local-services-smoke\.js[\s\S]*node scripts\/cli-local-run-smoke\.js/ ); expect( cliFirstAcceptance, "CLI-first acceptance composes self-hosted checks", /node scripts\/self-hosted-coordinator-smoke\.js/ ); expect( cliFirstAcceptance, "CLI-first acceptance composes debug and artifact checks", /node scripts\/vscode-f5-smoke\.js[\s\S]*node scripts\/artifact-download-smoke\.js[\s\S]*node scripts\/artifact-export-smoke\.js/ ); expect( cliFirstAcceptance, "CLI-first acceptance composes DAP checks", /node scripts\/dap-smoke\.js/ ); expect( cliFirstAcceptance, "CLI-first acceptance can include private hosted gate", /DISASMER_CLI_FIRST_INCLUDE_PRIVATE[\s\S]*scripts\/acceptance-private\.sh/ ); assert.doesNotMatch( cliFirstAcceptance, /node scripts\/public-release-dryrun-e2e\.js|node scripts\/public-release-dryrun-final-evidence\.js/, "CLI-first non-e2e gate must not invoke final public release e2e or final evidence verifier" ); for (const [name, pattern] of [ ["top-level version metadata", /#\[command\([\s\S]*name = "disasmer"[\s\S]*version[\s\S]*arg_required_else_help = true[\s\S]*\)\]/], ["top-level primary workflow help", /after_help = "Primary workflow:[\s\S]*disasmer login --browser[\s\S]*disasmer node attach --worker[\s\S]*Disasmer: Launch Virtual Process[\s\S]*Hosted account creation happens in the browser login flow\."/], ["top-level logout command", /enum Commands[\s\S]*Logout\(AuthLogoutArgs\)[\s\S]*Auth \{/], ["login non-interactive flag", /struct LoginArgs[\s\S]*non_interactive: bool/], ["run non-interactive flag", /struct RunArgs[\s\S]*non_interactive: bool/], ["stored CLI session model", /struct StoredCliSession[\s\S]*cli_session_credential_kind[\s\S]*provider_tokens_exposed_to_cli[\s\S]*provider_tokens_sent_to_nodes/], ["read CLI session helper", /fn read_cli_session\(project: &Path\) -> Result>/], ["write CLI session helper", /fn write_cli_session\(project: &Path, session: &StoredCliSession\) -> Result/], ["session source fallback", /fn session_from_sources\(project: &Path\) -> Result[\s\S]*read_cli_session\(project\)\?\.is_some\(\)/], ["browser login writes local CLI session", /local_cli_session_file_written[\s\S]*write_cli_session\(&cwd, &stored_session\)\?/], ["browser login does not persist provider tokens", /provider_tokens_persisted_locally:\s*false/], ["non-interactive auth report", /fn non_interactive_auth_machine_error[\s\S]*browser_opened[\s\S]*false/], ["human report renderer", /fn human_report\(value: &Value\) -> String/], ["shared report emitter", /fn emit_report\(report: &T, json_output: bool\) -> Result<\(\)>/], ["doctor command", /Doctor\(DoctorArgs\)/], ["doctor node readiness summary", /fn node_readiness_summary[\s\S]*ready_to_attach[\s\S]*explicit_attach_required[\s\S]*missing_local_dependencies[\s\S]*next_actions/], ["auth status command", /enum AuthCommands[\s\S]*Status\(AuthStatusArgs\)/], ["auth logout command", /enum AuthCommands[\s\S]*Logout\(AuthLogoutArgs\)/], ["key lifecycle commands", /enum KeyCommands[\s\S]*Add\(KeyAddArgs\)[\s\S]*List\(KeyListArgs\)[\s\S]*Revoke\(KeyRevokeArgs\)/], ["project commands", /enum ProjectCommands[\s\S]*Init\(ProjectInitArgs\)[\s\S]*Status\(ProjectStatusArgs\)[\s\S]*List\(ProjectListArgs\)[\s\S]*Select\(ProjectSelectArgs\)/], ["inspect command", /Inspect\(BundleInspectArgs\)/], ["build command", /Build\(BuildArgs\)/], ["node lifecycle commands", /enum NodeCommands[\s\S]*Attach\(AttachArgs\)[\s\S]*Enroll\(NodeEnrollArgs\)[\s\S]*List\(NodeListArgs\)[\s\S]*Status\(NodeStatusArgs\)[\s\S]*Revoke\(NodeRevokeArgs\)/], ["process commands", /enum ProcessCommands[\s\S]*Status\(ProcessStatusArgs\)[\s\S]*Restart\(ProcessRestartArgs\)[\s\S]*Cancel\(ProcessCancelArgs\)/], ["task lifecycle commands", /enum TaskCommands[\s\S]*List\(TaskListArgs\)[\s\S]*Restart\(TaskRestartArgs\)/], ["logs command", /Logs\(LogsArgs\)/], ["artifact commands", /enum ArtifactCommands[\s\S]*List\(ArtifactListArgs\)[\s\S]*Download\(ArtifactDownloadArgs\)[\s\S]*Export\(ArtifactExportArgs\)/], ["DAP command", /Dap\(DapArgs\)/], ["debug attach command", /enum DebugCommands[\s\S]*Attach\(DebugAttachArgs\)/], ["quota command", /enum QuotaCommands[\s\S]*Status\(QuotaStatusArgs\)/], ["admin commands", /enum AdminCommands[\s\S]*Status\(AdminStatusArgs\)[\s\S]*Bootstrap\(AdminBootstrapArgs\)[\s\S]*RevokeNode\(NodeRevokeArgs\)[\s\S]*StopProcess\(ProcessCancelArgs\)[\s\S]*SuspendTenant\(AdminSuspendTenantArgs\)/], ]) { expect(cli, name, pattern); } for (const [name, pattern] of [ ["CLI parse coverage", /fn cli_first_mvp_command_surface_parses\(\)/], ["CLI primary workflow help coverage", /fn top_level_help_exposes_primary_workflow_without_auth\(\)/], ["CLI non-interactive run auth coverage", /fn non_interactive_run_without_session_requires_explicit_auth_or_local\(\)/], ["CLI non-interactive browser login coverage", /fn browser_login_non_interactive_fails_before_opening_browser\(\)/], ["CLI stored browser session coverage", /fn stored_browser_login_session_omits_provider_token_values\(\)/], ["CLI auth status session-file coverage", /fn auth_status_reads_stored_cli_session_without_provider_tokens\(\)/], ["CLI version coverage", /fn top_level_version_is_available\(\)/], ["CLI JSON parse coverage", /fn cli_first_json_mode_parses_for_primary_commands\(\)/], ["CLI human output coverage", /fn human_report_is_text_not_json\(\)/], ["CLI key lifecycle coverage", /fn key_lifecycle_reports_project_scoped_agent_credentials\(\)/], ["CLI agent workflow actor coverage", /fn run_with_agent_public_key_sends_attributable_workflow_actor\(\)/], ["CLI node revoke coverage", /fn node_revoke_reports_scoped_credential_revocation\(\)/], ["CLI admin public API coverage", /fn admin_status_and_suspend_use_public_coordinator_api\(\)/], ["CLI admin bootstrap coverage", /fn admin_bootstrap_reports_self_hosted_cli_only_path\(\)/], ["CLI debug attach coverage", /fn debug_attach_reports_public_authorization\(\)/], ["doctor unchecked reachability coverage", /fn doctor_reports_unchecked_coordinator_reachability_without_config\(\)/], ["doctor ping reachability coverage", /fn doctor_pings_configured_coordinator\(\)/], ["project local config coverage", /fn project_init_select_and_status_use_local_project_config\(\)/], ["project public API list/select coverage", /fn project_list_and_select_use_public_api_without_website\(\)/], ["project coordinator status coverage", /fn project_status_queries_public_coordinator_state\(\)/], ["run coordinator active-process coverage", /fn run_contacts_configured_coordinator_and_reports_active_process_conflicts\(\)/], ["CLI error classifier coverage", /fn cli_error_classifier_distinguishes_mvp_failure_categories\(\)/], ["CLI command exit-code coverage", /fn command_report_exit_code_marks_command_failures_only\(\)/], ["CLI top-level logout alias coverage", /fn top_level_logout_alias_removes_only_cli_session_state\(\)/], ["CLI confirmation gate helper", /fn confirmation_required_report[\s\S]*coordinator_request_sent[\s\S]*confirmation_required/], ["CLI mutating confirmation coverage", /fn mutating_commands_require_yes_before_side_effects\(\)/], ["CLI run rejection category coverage", /fn run_rejection_reports_machine_readable_error_category\(\)/], ["CLI locality failure classifier", /fn classify_cli_error_message\(message: &str\)[\s\S]*message_mentions_locality_failure\(&message\)[\s\S]*return "connectivity"/], ["CLI locality failure report helper", /fn task_locality_failure_from_reason\(reason: &Value\) -> Value[\s\S]*coordinator_bulk_relay_used[\s\S]*safe_next_actions/], ["CLI locality failure human output", /fn push_task_locality_failures\(lines: &mut Vec, tasks: &\[Value\]\)[\s\S]*locality \{task_name\}/], ["node attach grant disclosure coverage", /fn node_attach_discloses_dangerous_capability_grants\(\)/], ["node enroll public API grant coverage", /fn node_enroll_reports_short_lived_public_api_grant\(\)/], ["quota local status coverage", /fn quota_status_uses_project_config_and_generic_public_limits\(\)/], ["quota coordinator usage coverage", /fn quota_status_queries_public_coordinator_usage\(\)/], ["task event summary coverage", /fn process_task_log_and_artifact_reports_summarize_task_events\(\)/], ["task locality failure summary coverage", /fn process_task_log_and_artifact_reports_summarize_task_events\(\)[\s\S]*source snapshot unavailable and direct connectivity unavailable[\s\S]*locality_failure/], ["log secret redaction coverage", /fn log_and_task_reports_redact_secret_like_values\(\)/], ["artifact download/export report coverage", /fn artifact_download_and_export_reports_expose_safe_session_boundaries\(\)/], ["process control report coverage", /fn process_restart_and_cancel_reports_expose_control_boundaries\(\)/], ["task restart report coverage", /fn task_restart_reports_clean_boundary_requirements\(\)/], ["build no full repo upload coverage", /fn build_command_reuses_bundle_inspection_without_full_repo_upload\(\)/], ["bundle rebuild restart compatibility coverage", /fn bundle_rebuild_after_source_edit_keeps_restart_compatibility_contract\(\)/], ["inspect missing environment coverage", /fn bundle_inspect_reports_missing_environment_references_before_schedule\(\)/], ["inspect source provider override coverage", /fn bundle_inspect_reports_source_provider_overrides_before_schedule\(\)/], ["build missing environment gate coverage", /fn build_blocks_before_schedule_on_missing_environment_reference\(\)/], ["safe coordinator-required plans", /fn node_enroll_and_process_commands_have_safe_plan_without_coordinator\(\)/], ]) { expect(cli, name, pattern); } expect( browserLoginFlowSmoke, "browser login smoke checks session file", /provider_tokens_persisted_locally[\s\S]*path\.join\(project, "\.disasmer", "session\.json"\)[\s\S]*\["auth", "status", "--json"\]/ ); expect( browserLoginFlowSmoke, "browser login smoke rejects provider token persistence", /assert\.doesNotMatch\([\s\S]*access_token\|refresh_token\|id_token/ ); expect( coordinator, "coordinator whole-process cancellation coverage", /fn service_cancels_whole_process_and_blocks_new_task_launches\(\)/ ); expect( coordinator, "coordinator single active process coverage", /fn service_rejects_second_active_process_unless_restarting_same_process\(\)/ ); expect( coordinator, "coordinator agent key lifecycle coverage", /fn service_manages_project_scoped_agent_public_keys\(\)/ ); expect( coordinator, "coordinator agent workflow dispatch coverage", /fn service_runs_agent_workflows_with_scoped_key_attribution\(\)/ ); expect( coordinator, "coordinator agent workflow authorization", /authorize_agent_project_run\([\s\S]*project:run/ ); expect( coordinator, "coordinator agent workflow actor fields", /pub struct WorkflowActor[\s\S]*agent: Option[\s\S]*public_key_fingerprint: Option[\s\S]*authenticated_without_browser/ ); expect( coordinator, "coordinator node revoke coverage", /fn service_revokes_node_credentials_and_live_descriptors\(\)/ ); expect( coordinator, "coordinator public admin suspension coverage", /fn service_reports_and_enforces_public_admin_tenant_suspension\(\)/ ); expect( coordinator, "coordinator debug attach coverage", /fn service_authorizes_debug_attach_through_public_api\(\)/ ); expect( coordinator, "coordinator task restart boundary coverage", /fn service_reports_task_restart_boundary_through_public_api\(\)/ ); expect( coordinator, "coordinator task events retain placement reasons", /pub struct TaskCompletionEvent[\s\S]*placement: Option[\s\S]*task_placements[\s\S]*event\.placement = self\.task_placements\.remove/ ); expect( coordinator, "public debug operation audit event", /pub struct DebugAuditEvent[\s\S]*charged_debug_read_bytes[\s\S]*used_debug_read_bytes/ ); expect( coordinator, "public debug operation metering", /record_debug_audit_event\([\s\S]*LimitKind::DebugReadBytes[\s\S]*DEBUG_CONTROL_READ_BYTES/ ); expect( cli, "CLI surfaces debug audit and quota fields", /debug_reads_quota_limited[\s\S]*charged_debug_read_bytes[\s\S]*used_debug_read_bytes/ ); expect( cli, "CLI sends agent workflow actor fields", /fn add_workflow_actor_fields[\s\S]*actor_agent[\s\S]*agent_public_key_fingerprint/ ); expect( cli, "CLI exposes node attach grant disclosures", /struct CapabilityGrantDisclosure[\s\S]*coordinator_policy_limited[\s\S]*fn capability_grant_disclosures/ ); expect( cli, "CLI exposes normalized node enrollment grants", /fn node_enroll_report[\s\S]*create_node_enrollment_grant[\s\S]*enrollment_grant[\s\S]*private_website_required[\s\S]*fn node_enrollment_grant_summary[\s\S]*short_lived[\s\S]*node_credentials_separate_from_user_session/ ); expect( cli, "CLI exposes task placement reasons", /fn task_summaries[\s\S]*node_placement[\s\S]*reasons[\s\S]*explanation_available/ ); expect( cli, "CLI project list/select report public API boundary", /fn project_list_report[\s\S]*public_coordinator_api[\s\S]*private_website_required[\s\S]*fn project_select_report[\s\S]*project_config_written[\s\S]*private_website_required/ ); expect( cli, "CLI project select writes config after coordinator response", /let coordinator_response = if let Some\(coordinator\)[\s\S]*session\.request\(json!\(\{[\s\S]*"type": "select_project"[\s\S]*\}\)\)\?[\s\S]*write_project_config\(&cwd, &config\)\?/ ); expect( cli, "CLI renders task placement reasons", /fn push_task_placement_reasons[\s\S]*placement \{task_name\}: \{node\}/ ); expect( cli, "CLI redacts secret-like log values", /fn log_entries[\s\S]*redact_secret_like_text[\s\S]*secret_like_values_redacted[\s\S]*redacted_fields[\s\S]*fn redact_secret_like_text[\s\S]*access_token=[\s\S]*password=[\s\S]*bearer / ); expect( cli, "CLI classifies machine-readable error categories", /fn classify_cli_error_message[\s\S]*"authentication"[\s\S]*"authorization"[\s\S]*"quota"[\s\S]*"policy"[\s\S]*"capability"[\s\S]*"connectivity"[\s\S]*"environment"[\s\S]*"program"/ ); expect( cli, "CLI exposes quota machine-error posture", /fn cli_error_summary_for_category[\s\S]*resource_category[\s\S]*quota_error_resource_category[\s\S]*community_tier_language[\s\S]*private_abuse_heuristics_exposed[\s\S]*fn quota_error_resource_category[\s\S]*resource limit exceeded for / ); expect( cli, "CLI reports stable error-code contract", /fn cli_error_exit_code[\s\S]*"authentication" => 20[\s\S]*"authorization" => 21[\s\S]*"quota" => 22[\s\S]*"policy" => 23[\s\S]*"capability" => 24[\s\S]*"connectivity" => 25[\s\S]*"environment" => 26[\s\S]*"program" => 27/ ); expect( cli, "CLI attaches machine errors to run and task reports", /run_start_summary[\s\S]*"machine_error": machine_error/ ); expect( cli, "CLI attaches machine errors to task failures", /task_failure_machine_error[\s\S]*cli_error_summary_with_default/ ); expect( cli, "CLI applies process exit code after printing command failure report", /fn emit_report[\s\S]*apply_command_report_exit_code[\s\S]*std::process::exit\(exit_code\)/ ); expect( cli, "CLI wraps fallible main with classified exit", /fn main\(\)[\s\S]*cli_error_summary\(&message\)[\s\S]*std::process::exit\(exit_code\)/ ); expect( cli, "CLI parses dangerous capability overrides", /"host-filesystem"[\s\S]*Capability::HostFilesystem[\s\S]*"network"[\s\S]*Capability::Network[\s\S]*"secrets"[\s\S]*Capability::Secrets/ ); expect( cli, "CLI exposes source provider diagnostics", /source_provider_statuses[\s\S]*source_provider_selection[\s\S]*source_provider_unsupported/ ); expect( cli, "CLI exposes environment pre-schedule diagnostics", /environment_diagnostics_for_inputs[\s\S]*diagnose_environment_references[\s\S]*missing_environment/ ); expect( cli, "CLI bundle metadata exposes MVP build facets", /BundleIdentityInputs[\s\S]*entrypoints[\s\S]*default_entrypoint[\s\S]*source_transfer_policy[\s\S]*wasm_source_proxy_digest[\s\S]*task_abi_digest/ ); expect( cli, "CLI bundle coverage verifies Dockerfile and debug metadata", /fn bundle_inspect_discovers_environments_selected_inputs_and_source_providers\(\)[\s\S]*envs\/docker\/Dockerfile[\s\S]*task_metadata[\s\S]*source_metadata[\s\S]*debug_metadata/ ); expect( cli, "CLI build coverage verifies inspectable metadata", /fn build_command_reuses_bundle_inspection_without_full_repo_upload\(\)[\s\S]*wasm_code[\s\S]*task_metadata[\s\S]*source_metadata[\s\S]*debug_metadata/ ); expect( cli, "CLI build coverage verifies large input handle posture", /large_input_policy[\s\S]*selected_inputs_are_content_digests[\s\S]*selected_input_bytes_included[\s\S]*silent_task_argument_serialization[\s\S]*supported_handle_types/ ); expect( cli, "CLI bundle coverage verifies restart compatibility metadata", /restart_compatibility[\s\S]*source_edits_can_restart_from_clean_task_boundary[\s\S]*requires_clean_checkpoint_boundary[\s\S]*compares_task_abi[\s\S]*incompatible_changes_require_whole_process_restart/ ); expect( cli, "CLI blocks build before scheduling unsafe inputs", /blocked_before_schedule[\s\S]*scheduled_work[\s\S]*false/ ); expect( cli, "CLI artifact export writes explicit local bytes from stream content", /fn artifact_export_local_write_followup[\s\S]*open_artifact_download_stream[\s\S]*content_base64[\s\S]*std::fs::write/ ); expect( cli, "CLI artifact export keeps content out of reports", /fn artifact_stream_summary[\s\S]*content_material_returned_in_report[\s\S]*false/ ); expect( cli, "CLI exposes admin bootstrap self-hosted path", /fn admin_bootstrap_report[\s\S]*self_hosted_cli_only[\s\S]*bootstrap_sequence[\s\S]*create_node_enrollment_grant[\s\S]*attach_worker_node[\s\S]*inspect_status_logs_artifacts[\s\S]*revoke_access/ ); expect( coordinator, "coordinator exposes conservative artifact stream content", /fn download_stream_content_base64[\s\S]*stdout_truncated[\s\S]*artifact_size_bytes[\s\S]*BASE64_STANDARD\.encode/ ); for (const [name, pattern] of [ ["agent --json flag", /struct AgentEnrollArgs[\s\S]*#\[arg\(long\)\]\s*json: bool/], ["bundle inspect --json flag", /struct BundleInspectArgs[\s\S]*#\[arg\(long\)\]\s*json: bool/], ["build --json flag", /struct BuildArgs[\s\S]*#\[arg\(long\)\]\s*json: bool/], ["run --json flag", /struct RunArgs[\s\S]*#\[arg\(long\)\]\s*json: bool/], ["node attach --json flag", /struct AttachArgs[\s\S]*#\[arg\(long\)\]\s*json: bool/], ["DAP plan --json flag", /struct DapArgs[\s\S]*#\[arg\(long\)\]\s*json: bool/], ["shared scope --json flag", /struct CliScopeArgs[\s\S]*#\[arg\(long\)\]\s*json: bool/], ]) { expect(cli, name, pattern); } for (const [name, pattern] of [ ["human default assertion", /default output should be human-readable text, not JSON/], ["login JSON mode", /\["login", "--coordinator", "https:\/\/coord\.example\.test", "--json"\]/], ["doctor human mode", /\["doctor"\]/], ["doctor reachability JSON mode", /doctorJson\.coordinator_reachability\.status/], ["doctor node readiness JSON mode", /doctorJson\.node_readiness_summary\.status[\s\S]*explicit_attach_required[\s\S]*missing_local_dependencies/], ["bundle inspect JSON mode", /\["bundle", "inspect", "--project", project, "--json"\]/], ["bundle inspect large input JSON mode", /large_input_policy[\s\S]*SourceSnapshot/], ["bundle inspect restart compatibility JSON mode", /restart_compatibility[\s\S]*source_edits_can_restart_from_clean_task_boundary/], ["auth expiry posture", /token_expiry_posture[\s\S]*expires_at/], ]) { expect(outputModeSmoke, name, pattern); } for (const [name, pattern] of [ ["fake coordinator quota rejection", /quota unavailable: resource limit exceeded for api_calls/], ["run uses JSON mode", /"run"[\s\S]*"--json"/], ["actual quota exit code", /assert\.strictEqual\(result\.code, 22/], ["actual quota resource-category assertion", /machine_error\.resource_category, "api_calls"/], ["actual quota abuse-heuristics assertion", /machine_error\.private_abuse_heuristics_exposed,[\s\S]*false/], ["exit-code application in JSON", /process_exit_code_applied[\s\S]*true/], ]) { expect(errorExitSmoke, name, pattern); } console.log("CLI-first contract smoke passed");