mirror of
https://github.com/esengine/DeepSeek-Reasonix.git
synced 2026-11-07 10:45:59 -10:00
ci: stop requiring Windows tests for features that were removed
The pull-request-only Windows steps listed tests by name and failed when one was missing. The sub-agent, isolation, background-job and carried-proof rewrites deleted a number of them, so every pull request failed its Windows check. Drop the steps whose whole list is gone, prune the removed names from the rest, and remove the concurrency inventory runner whose two inventories named nothing that exists.
This commit is contained in:
1 parent
611094ba17
commit
2e2a484781
7 files changed
+17
-562
No files matched your search
@@ -1,24 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"package": "reasonix/internal/runtime/delegation",
|
|
||||||
"tests": [
|
|
||||||
"TestAncestorCopyAdmissionCoversUnpublishedRun",
|
|
||||||
"TestAncestorCopyAdmissionCoversUnpublishedRun/continue_then_continue",
|
|
||||||
"TestAncestorCopyAdmissionCoversUnpublishedRun/continue_then_legacy",
|
|
||||||
"TestAncestorCopyAdmissionCoversUnpublishedRun/legacy_then_continue",
|
|
||||||
"TestAncestorCopyAdmissionCoversUnpublishedRun/legacy_then_legacy",
|
|
||||||
"TestAncestorCopyAdmissionAllowsDifferentParents",
|
|
||||||
"TestAncestorCopyAdmissionReleasesAbandonedPreparation",
|
|
||||||
"TestAncestorCopyAdmissionReleasesAfterInvalidCopy",
|
|
||||||
"TestAncestorCopyAdmissionAllowsDifferentSources",
|
|
||||||
"TestAncestorCopyAdmissionUsesNearestSourceIdentity",
|
|
||||||
"TestAncestorCopyAdmissionReleasesAfterBusyCurrentReference",
|
|
||||||
"TestTaskAncestorCopyAdmissionBeforeRunningMetadata",
|
|
||||||
"TestTaskAncestorCopyAdmissionBeforeRunningMetadata/continue_from",
|
|
||||||
"TestTaskAncestorCopyAdmissionBeforeRunningMetadata/fork_from",
|
|
||||||
"TestTaskAncestorCopyAdmissionReleasesUnstartedBackground",
|
|
||||||
"TestTaskAncestorCopyAdmissionReleasesUnstartedBackground/continue_from",
|
|
||||||
"TestTaskAncestorCopyAdmissionReleasesUnstartedBackground/fork_from"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"package": "reasonix/internal/runtime/agent",
|
|
||||||
"tests": [
|
|
||||||
"TestCarriedProofInvalidatesPermissionChange",
|
|
||||||
"TestCarriedProofFileStateCompatibility",
|
|
||||||
"TestCarriedProofFileStateCompatibility/legacy_file",
|
|
||||||
"TestCarriedProofFileStateCompatibility/legacy_absent",
|
|
||||||
"TestCarriedProofFileStateCompatibility/future",
|
|
||||||
"TestCarriedProofFileStateCompatibility/current_file",
|
|
||||||
"TestCarriedProofFileStateCompatibility/current_absent",
|
|
||||||
"TestCarriedProofRejectsDirectoryState",
|
|
||||||
"TestCarriedProofStandsOnlyForUnchangedContent",
|
|
||||||
"TestCarriedProofSeesADeletion"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"package": "reasonix/internal/assembly/boot",
|
|
||||||
"tests": [
|
|
||||||
"TestEffectCarriedProofTracksFileState",
|
|
||||||
"TestEffectCarriedProofTracksFileState/unchanged",
|
|
||||||
"TestEffectCarriedProofTracksFileState/content",
|
|
||||||
"TestEffectCarriedProofTracksFileState/mode"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
+17
-155
@@ -170,23 +170,6 @@ jobs:
|
|||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: Get-CimInstance Win32_Processor | Select-Object -ExpandProperty Name
|
run: Get-CimInstance Win32_Processor | Select-Object -ExpandProperty Name
|
||||||
|
|
||||||
- name: test (Windows concurrency contracts)
|
|
||||||
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
||||||
timeout-minutes: 5
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
node --test scripts/windows-concurrency-tests.test.mjs
|
|
||||||
node scripts/windows-concurrency-tests.mjs "$RUNNER_TEMP/concurrency-windows.jsonl"
|
|
||||||
|
|
||||||
- name: upload Windows concurrency inventory
|
|
||||||
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
||||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
||||||
with:
|
|
||||||
name: concurrency-windows-${{ github.run_attempt }}
|
|
||||||
path: ${{ runner.temp }}/concurrency-windows.jsonl
|
|
||||||
if-no-files-found: error
|
|
||||||
retention-days: 7
|
|
||||||
|
|
||||||
- name: test
|
- name: test
|
||||||
if: env.RUN_STEPS == 'true' && runner.os != 'Windows'
|
if: env.RUN_STEPS == 'true' && runner.os != 'Windows'
|
||||||
env:
|
env:
|
||||||
@@ -196,35 +179,6 @@ jobs:
|
|||||||
REASONIX_RELEASE_CACHE_GUARD: "1"
|
REASONIX_RELEASE_CACHE_GUARD: "1"
|
||||||
run: go test ./...
|
run: go test ./...
|
||||||
|
|
||||||
- name: test (Windows subagent status admission)
|
|
||||||
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
||||||
timeout-minutes: 5
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -o pipefail
|
|
||||||
go test -count=1 -timeout=3m -json -run '^TestSubagent(PersistedStatusAdmission|UnknownStatusStillReadableForDiagnosis)$' ./internal/runtime/delegation | tee "$RUNNER_TEMP/subagent-status-admission.jsonl"
|
|
||||||
jq -se '
|
|
||||||
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
||||||
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
||||||
["future-paused", "missing", "empty", "COMPLETED", "completed", "cancelled", "failed", "interrupted", "running"] as $states |
|
|
||||||
["continue", "copy", "ancestor", "legacy_ancestor", "current_copy"] as $routes |
|
|
||||||
(["TestSubagentPersistedStatusAdmission", "TestSubagentUnknownStatusStillReadableForDiagnosis"] +
|
|
||||||
[$states[] | "TestSubagentPersistedStatusAdmission/" + .] +
|
|
||||||
[$states[] as $state | $routes[] | "TestSubagentPersistedStatusAdmission/" + $state + "/" + .]) as $required |
|
|
||||||
all(.[]; .Action != "skip" and .Action != "fail") and
|
|
||||||
(["reasonix/internal/runtime/delegation"] - $packages | length) == 0 and
|
|
||||||
($required - $tests | length) == 0
|
|
||||||
' "$RUNNER_TEMP/subagent-status-admission.jsonl"
|
|
||||||
|
|
||||||
- name: upload Windows subagent status admission inventory
|
|
||||||
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
||||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
||||||
with:
|
|
||||||
name: subagent-status-admission-windows-${{ github.run_attempt }}
|
|
||||||
path: ${{ runner.temp }}/subagent-status-admission.jsonl
|
|
||||||
if-no-files-found: ignore
|
|
||||||
retention-days: 7
|
|
||||||
|
|
||||||
- name: test (Windows composition links)
|
- name: test (Windows composition links)
|
||||||
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
@@ -307,34 +261,17 @@ jobs:
|
|||||||
[.[] | select(.Test == null and .Action == "pass") | .Package] as $passed |
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $passed |
|
||||||
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
||||||
(["reasonix/internal/runtime/isolation", "reasonix/internal/platform/worktree", "reasonix/internal/state/mutation"] - $passed | length) == 0 and
|
(["reasonix/internal/runtime/isolation", "reasonix/internal/platform/worktree", "reasonix/internal/state/mutation"] - $passed | length) == 0 and
|
||||||
(["TestResultOperationUsesCrossProcessOwnership",
|
(["TestHeldPathsCoverOnlyTheSameFileAcrossCaseSpellings",
|
||||||
"TestActualResultOperationHoldsOwnershipThroughWriteAndCleanup/restore",
|
|
||||||
"TestActualResultOperationHoldsOwnershipThroughWriteAndCleanup/remove",
|
|
||||||
"TestApplyPathsWithUntrustedModesPreservesTheIndex/content",
|
|
||||||
"TestApplyPathsWithUntrustedModesPreservesTheIndex/source_index_mode",
|
|
||||||
"TestApplyPathsWithUntrustedModesPreservesTheIndex/candidate_mode",
|
|
||||||
"TestApplyPathsWithUntrustedModesPreservesTheIndex/candidate_type",
|
|
||||||
"TestApplyPathsEmulatedLinksUseSnapshotFilters",
|
|
||||||
"TestHeldPathsCoverOnlyTheSameFileAcrossCaseSpellings",
|
|
||||||
"TestLegacyWaitDoesNotConsumeExecutionCapacity"] - $tests | length) == 0
|
"TestLegacyWaitDoesNotConsumeExecutionCapacity"] - $tests | length) == 0
|
||||||
' "$RUNNER_TEMP/isolation-owners.jsonl"
|
' "$RUNNER_TEMP/isolation-owners.jsonl"
|
||||||
jq -se '
|
jq -se '
|
||||||
. as $events |
|
. as $events |
|
||||||
{"reasonix/internal/platform/worktree": [
|
{"reasonix/internal/platform/worktree": [
|
||||||
"TestApplyPathsRejectsRedirectedAncestors",
|
|
||||||
"TestApplyPathsRejectsRedirectedAncestors/outside_delete",
|
|
||||||
"TestApplyPathsRejectsRedirectedAncestors/inside_delete",
|
|
||||||
"TestApplyPathsRejectsRedirectedAncestors/dangling_delete",
|
|
||||||
"TestApplyPathsRejectsRedirectedAncestors/outside_write",
|
|
||||||
"TestApplyPathsRejectsRedirectedAncestors/inside_write",
|
|
||||||
"TestApplyPathsRejectsRedirectedAncestors/regular_parent",
|
|
||||||
"TestApplyPathsRejectsRedirectedAncestors/unchanged",
|
|
||||||
"TestApplyPathsRejectsRedirectedAncestors/missing_creation",
|
|
||||||
"TestWriteChangesRejectsRedirectedDeletion",
|
"TestWriteChangesRejectsRedirectedDeletion",
|
||||||
"TestWriteChangesUnlinksLeafDirectoryLink",
|
"TestWriteChangesUnlinksLeafDirectoryLink"
|
||||||
"TestWholeWorkspaceApplyPreservesFileToDirectoryTransition"],
|
],
|
||||||
"reasonix/internal/runtime/isolation": [
|
"reasonix/internal/runtime/isolation": [
|
||||||
"TestApplyToolRetainsResultAfterAncestorReplacement"]} |
|
]} |
|
||||||
to_entries | all(.[]; . as $package |
|
to_entries | all(.[]; . as $package |
|
||||||
([ $events[] | select(.Package == $package.key and .Test == null and
|
([ $events[] | select(.Package == $package.key and .Test == null and
|
||||||
(.Action == "pass" or .Action == "fail" or .Action == "skip")) ] |
|
(.Action == "pass" or .Action == "fail" or .Action == "skip")) ] |
|
||||||
@@ -354,60 +291,15 @@ jobs:
|
|||||||
if-no-files-found: ignore
|
if-no-files-found: ignore
|
||||||
retention-days: 7
|
retention-days: 7
|
||||||
|
|
||||||
- name: test (Windows background resource owners)
|
|
||||||
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
||||||
timeout-minutes: 25
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -o pipefail
|
|
||||||
go test -count=1 -p 2 -timeout=18m -json ./internal/tools/jobs/... ./internal/runtime/delegation/... | tee "$RUNNER_TEMP/background-resources.jsonl" |
|
|
||||||
jq -rj --unbuffered 'select(.Action == "output" and .Test == null) | .Output'
|
|
||||||
jq -se '
|
|
||||||
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
||||||
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
||||||
(["reasonix/internal/tools/jobs", "reasonix/internal/runtime/delegation"] - $packages | length) == 0 and
|
|
||||||
(["TestJobFinalizationCoversInvokedAndUninvoked/success",
|
|
||||||
"TestJobFinalizationCoversInvokedAndUninvoked/error",
|
|
||||||
"TestJobFinalizationCoversInvokedAndUninvoked/panic",
|
|
||||||
"TestJobFinalizationCoversInvokedAndUninvoked/closed",
|
|
||||||
"TestJobFinalizationCoversInvokedAndUninvoked/invalid_session",
|
|
||||||
"TestJobFinalizationCoversInvokedAndUninvoked/invalid_kind",
|
|
||||||
"TestJobFinalizationFailuresAttemptAllCallbacksAndKeepCauses/invoked",
|
|
||||||
"TestJobFinalizationFailuresAttemptAllCallbacksAndKeepCauses/uninvoked",
|
|
||||||
"TestJobFinalizationPrecedesCompletionPublication",
|
|
||||||
"TestJobFinalizationCloseBetweenPublicationAndLaunch",
|
|
||||||
"TestJobFinalizationWaitsForClosureAfterLogicalCancellation",
|
|
||||||
"TestBackgroundNoLaunchFinalizesOwnedResources/task/closed_manager",
|
|
||||||
"TestBackgroundNoLaunchFinalizesOwnedResources/task/invalid_session",
|
|
||||||
"TestBackgroundNoLaunchFinalizesOwnedResources/fleet/closed_manager",
|
|
||||||
"TestBackgroundNoLaunchFinalizesOwnedResources/fleet/invalid_session"] - $tests | length) == 0
|
|
||||||
' "$RUNNER_TEMP/background-resources.jsonl"
|
|
||||||
|
|
||||||
- name: upload Windows background resource inventory
|
|
||||||
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
||||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
||||||
with:
|
|
||||||
name: background-resources-windows-${{ github.run_attempt }}
|
|
||||||
path: ${{ runner.temp }}/background-resources.jsonl
|
|
||||||
if-no-files-found: ignore
|
|
||||||
retention-days: 7
|
|
||||||
|
|
||||||
- name: test (Windows delegated Goal usage scope)
|
- name: test (Windows delegated Goal usage scope)
|
||||||
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
go test -count=1 -timeout=3m -json -run '^Test(UsageScope.*|DelegatedUsageKeepsGoalOwner|EffectDelegatedUsageKeepsGoalOwner)$' ./internal/contract/event ./internal/session/control ./internal/assembly/boot | tee "$RUNNER_TEMP/goal-usage-scope.jsonl"
|
go test -count=1 -timeout=3m -json -run '^Test(UsageScope.*)$' ./internal/contract/event ./internal/session/control ./internal/assembly/boot | tee "$RUNNER_TEMP/goal-usage-scope.jsonl"
|
||||||
jq -se '
|
jq -se '
|
||||||
["TestUsageScopePreservesCapturedOwnerAndWire", "TestUsageScopeKeepsEarlierEventOwner",
|
["TestUsageScopeKeepsEarlierEventOwner",
|
||||||
"TestUsageScopeWithoutCapability", "TestDelegatedUsageKeepsGoalOwner",
|
"TestUsageScopeWithoutCapability" ] as $required |
|
||||||
"TestDelegatedUsageKeepsGoalOwner/chat_to_goal", "TestDelegatedUsageKeepsGoalOwner/replaced_goal",
|
|
||||||
"TestDelegatedUsageKeepsGoalOwner/cleared_goal", "TestDelegatedUsageKeepsGoalOwner/resumed_goal",
|
|
||||||
"TestDelegatedUsageKeepsGoalOwner/same_goal_next_turn", "TestDelegatedUsageKeepsGoalOwner/between_turns",
|
|
||||||
"TestDelegatedUsageKeepsGoalOwner/nested_after_replacement", "TestEffectDelegatedUsageKeepsGoalOwner",
|
|
||||||
"TestEffectDelegatedUsageKeepsGoalOwner/chat_to_goal", "TestEffectDelegatedUsageKeepsGoalOwner/replaced_goal",
|
|
||||||
"TestEffectDelegatedUsageKeepsGoalOwner/nested_chat_to_goal", "TestEffectDelegatedUsageKeepsGoalOwner/same_goal",
|
|
||||||
"TestEffectDelegatedUsageKeepsGoalOwner/completed_before_goal"] as $required |
|
|
||||||
[.[] | select(.Test != null and .Action == "pass") | .Test] as $passed |
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $passed |
|
||||||
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
||||||
all(.[]; .Action != "fail" and .Action != "skip") and
|
all(.[]; .Action != "fail" and .Action != "skip") and
|
||||||
@@ -511,10 +403,7 @@ jobs:
|
|||||||
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
||||||
all(.[]; .Action != "skip" and .Action != "fail") and
|
all(.[]; .Action != "skip" and .Action != "fail") and
|
||||||
(["reasonix/internal/runtime/agent", "reasonix/internal/runtime/coordinator", "reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
(["reasonix/internal/runtime/agent", "reasonix/internal/runtime/coordinator", "reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
||||||
(["TestPreparedRootBudgetLifetime", "TestPreparedRootBudgetLifetime/continuation",
|
(["TestCoordinatorRootBudgetRoutes",
|
||||||
"TestPreparedRootBudgetLifetime/new_scope", "TestPreparedRootBudgetLifetime/new_task",
|
|
||||||
"TestPreparedRootBudgetLifetime/reset", "TestPreparedRootBudgetLifetime/new_session",
|
|
||||||
"TestPreparedRootBudgetProjectionAndPreservedTurn", "TestCoordinatorRootBudgetRoutes",
|
|
||||||
"TestCoordinatorRootBudgetRoutes/raw", "TestCoordinatorRootBudgetRoutes/tool_planner",
|
"TestCoordinatorRootBudgetRoutes/raw", "TestCoordinatorRootBudgetRoutes/tool_planner",
|
||||||
"TestCoordinatorRootBudgetRoutes/failure_fallback", "TestCoordinatorRootBudgetRoutes/plan_only_continuation",
|
"TestCoordinatorRootBudgetRoutes/failure_fallback", "TestCoordinatorRootBudgetRoutes/plan_only_continuation",
|
||||||
"TestCoordinatorRootBudgetRoutes/approval_declined_continuation", "TestCoordinatorRootBudgetRoutes/approval_allowed",
|
"TestCoordinatorRootBudgetRoutes/approval_declined_continuation", "TestCoordinatorRootBudgetRoutes/approval_allowed",
|
||||||
@@ -578,10 +467,8 @@ jobs:
|
|||||||
"TestRootWallBudgetReachesDelegatedAgents/context", "TestRootWallBudgetReachesDelegatedAgents/unconfigured",
|
"TestRootWallBudgetReachesDelegatedAgents/context", "TestRootWallBudgetReachesDelegatedAgents/unconfigured",
|
||||||
"TestRootWallBudgetReachesDelegatedAgents/explicit_zero", "TestRootWallBudgetContinuationAndReset",
|
"TestRootWallBudgetReachesDelegatedAgents/explicit_zero", "TestRootWallBudgetContinuationAndReset",
|
||||||
"TestRootWallBudgetContinuationAndReset/continuation", "TestRootWallBudgetContinuationAndReset/new_task",
|
"TestRootWallBudgetContinuationAndReset/continuation", "TestRootWallBudgetContinuationAndReset/new_task",
|
||||||
"TestRootWallBudgetContinuationAndReset/reset", "TestRootWallBudgetContinuationAndReset/override",
|
"TestRootWallBudgetContinuationAndReset/reset", "TestRootWallBudgetContinuationAndReset/override"
|
||||||
"TestRootWallBudgetProjectionKeepsJobDeadline", "TestEffectRootWallBudgetReachesManagedJobs",
|
] - $tests | length) == 0
|
||||||
"TestEffectRootWallBudgetReachesManagedJobs/task", "TestEffectRootWallBudgetReachesManagedJobs/capability",
|
|
||||||
"TestEffectRootWallBudgetReachesManagedJobs/fleet"] - $tests | length) == 0
|
|
||||||
' "$RUNNER_TEMP/root-wall-budget.jsonl"
|
' "$RUNNER_TEMP/root-wall-budget.jsonl"
|
||||||
|
|
||||||
- name: upload Windows root wall budget inventory
|
- name: upload Windows root wall budget inventory
|
||||||
@@ -611,10 +498,7 @@ jobs:
|
|||||||
"TestRootTokenBudgetSurvivesNestedAndConcurrentChildren/nested", "TestRootTokenBudgetSurvivesNestedAndConcurrentChildren/siblings",
|
"TestRootTokenBudgetSurvivesNestedAndConcurrentChildren/nested", "TestRootTokenBudgetSurvivesNestedAndConcurrentChildren/siblings",
|
||||||
"TestRootTokenBudgetSurvivesNestedAndConcurrentChildren/child_override", "TestRootTokenBudgetContinuationAndReset",
|
"TestRootTokenBudgetSurvivesNestedAndConcurrentChildren/child_override", "TestRootTokenBudgetContinuationAndReset",
|
||||||
"TestRootTokenBudgetContinuationAndReset/continuation", "TestRootTokenBudgetContinuationAndReset/new_task",
|
"TestRootTokenBudgetContinuationAndReset/continuation", "TestRootTokenBudgetContinuationAndReset/new_task",
|
||||||
"TestRootTokenBudgetContinuationAndReset/reset", "TestRootTokenScopeAtomicAccountingAndJobCancellation",
|
"TestRootTokenBudgetContinuationAndReset/reset" ] - $tests | length) == 0
|
||||||
"TestEffectRootTokenBudgetReachesDelegatedJobs", "TestEffectRootTokenBudgetReachesDelegatedJobs/foreground",
|
|
||||||
"TestEffectRootTokenBudgetReachesDelegatedJobs/foreground_capability", "TestEffectRootTokenBudgetReachesDelegatedJobs/background",
|
|
||||||
"TestEffectRootTokenBudgetReachesDelegatedJobs/background_capability", "TestEffectRootTokenBudgetReachesDelegatedJobs/background_fleet"] - $tests | length) == 0
|
|
||||||
' "$RUNNER_TEMP/root-token-budget.jsonl"
|
' "$RUNNER_TEMP/root-token-budget.jsonl"
|
||||||
jq -se '
|
jq -se '
|
||||||
. as $events |
|
. as $events |
|
||||||
@@ -628,8 +512,6 @@ jobs:
|
|||||||
"TestBudgetCountsKnownReportedTokens/negative_split",
|
"TestBudgetCountsKnownReportedTokens/negative_split",
|
||||||
"TestBudgetCountsKnownReportedTokens/zero",
|
"TestBudgetCountsKnownReportedTokens/zero",
|
||||||
"TestBudgetCountsKnownReportedTokens/negative",
|
"TestBudgetCountsKnownReportedTokens/negative",
|
||||||
"TestReportedTokensEnforceLocalCapOnInheritedRoot",
|
|
||||||
"TestReportedTokensFollowOriginalAuxiliaryRoot",
|
|
||||||
"TestReportedTokenCountersSaturate"],
|
"TestReportedTokenCountersSaturate"],
|
||||||
"reasonix/internal/assembly/boot": [
|
"reasonix/internal/assembly/boot": [
|
||||||
"TestEffectReportedTotalTokenBudget",
|
"TestEffectReportedTotalTokenBudget",
|
||||||
@@ -697,7 +579,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
go test -count=1 -timeout=3m -json -run '^Test(HostStorageEnvironment|HostObjectStorage|HostExplicitStorageControls|DetachedStorageEnvironment|WorktreePreparationOwnsItsIndex|EffectIsolatedTaskOwnsGitStorage)$' ./internal/platform/gitcmd ./internal/platform/worktree ./internal/assembly/boot | tee "$RUNNER_TEMP/git-storage-environment.jsonl"
|
go test -count=1 -timeout=3m -json -run '^Test(HostStorageEnvironment|HostObjectStorage|HostExplicitStorageControls|DetachedStorageEnvironment)$' ./internal/platform/gitcmd ./internal/platform/worktree ./internal/assembly/boot | tee "$RUNNER_TEMP/git-storage-environment.jsonl"
|
||||||
jq -se '
|
jq -se '
|
||||||
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
||||||
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
||||||
@@ -707,10 +589,6 @@ jobs:
|
|||||||
"TestDetachedStorageEnvironment",
|
"TestDetachedStorageEnvironment",
|
||||||
"TestDetachedStorageEnvironment/explicit_env",
|
"TestDetachedStorageEnvironment/explicit_env",
|
||||||
"TestDetachedStorageEnvironment/inherited_env",
|
"TestDetachedStorageEnvironment/inherited_env",
|
||||||
"TestEffectIsolatedTaskOwnsGitStorage",
|
|
||||||
"TestEffectIsolatedTaskOwnsGitStorage/ambient_existing",
|
|
||||||
"TestEffectIsolatedTaskOwnsGitStorage/ambient_missing",
|
|
||||||
"TestEffectIsolatedTaskOwnsGitStorage/control",
|
|
||||||
"TestHostExplicitStorageControls",
|
"TestHostExplicitStorageControls",
|
||||||
"TestHostExplicitStorageControls/explicit_object_directory",
|
"TestHostExplicitStorageControls/explicit_object_directory",
|
||||||
"TestHostExplicitStorageControls/private_index",
|
"TestHostExplicitStorageControls/private_index",
|
||||||
@@ -721,15 +599,8 @@ jobs:
|
|||||||
"TestHostStorageEnvironment",
|
"TestHostStorageEnvironment",
|
||||||
"TestHostStorageEnvironment/GIT_ALTERNATE_OBJECT_DIRECTORIES",
|
"TestHostStorageEnvironment/GIT_ALTERNATE_OBJECT_DIRECTORIES",
|
||||||
"TestHostStorageEnvironment/GIT_INDEX_FILE",
|
"TestHostStorageEnvironment/GIT_INDEX_FILE",
|
||||||
"TestHostStorageEnvironment/GIT_OBJECT_DIRECTORY",
|
"TestHostStorageEnvironment/GIT_OBJECT_DIRECTORY"
|
||||||
"TestWorktreePreparationOwnsItsIndex",
|
] - $tests | length) == 0
|
||||||
"TestWorktreePreparationOwnsItsIndex/candidate_ambient_existing",
|
|
||||||
"TestWorktreePreparationOwnsItsIndex/candidate_ambient_missing",
|
|
||||||
"TestWorktreePreparationOwnsItsIndex/candidate_control",
|
|
||||||
"TestWorktreePreparationOwnsItsIndex/delivery_ambient_existing",
|
|
||||||
"TestWorktreePreparationOwnsItsIndex/delivery_ambient_missing",
|
|
||||||
"TestWorktreePreparationOwnsItsIndex/delivery_control"
|
|
||||||
] - $tests | length) == 0
|
|
||||||
' "$RUNNER_TEMP/git-storage-environment.jsonl"
|
' "$RUNNER_TEMP/git-storage-environment.jsonl"
|
||||||
|
|
||||||
- name: upload Windows Git storage environment inventory
|
- name: upload Windows Git storage environment inventory
|
||||||
@@ -816,11 +687,7 @@ jobs:
|
|||||||
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
||||||
all(.[]; .Action != "skip" and .Action != "fail") and
|
all(.[]; .Action != "skip" and .Action != "fail") and
|
||||||
(["reasonix/internal/session/control", "reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
(["reasonix/internal/session/control", "reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
||||||
(["TestProfileRootBudgetLifetime", "TestProfileRootBudgetLifetime/new_task",
|
(["TestProfileBudgetPreparationUsesTurnAdmission", "TestEffectExplicitSkillRootBudget",
|
||||||
"TestProfileRootBudgetLifetime/same_scope", "TestProfileRootBudgetLifetime/new_scope",
|
|
||||||
"TestProfileRootBudgetLifetime/reset", "TestProfileRootBudgetLifetime/new_session",
|
|
||||||
"TestProfileRootBudgetLifetime/inherited", "TestProfileRootBudgetLifetime/context_zero",
|
|
||||||
"TestProfileBudgetPreparationUsesTurnAdmission", "TestEffectExplicitSkillRootBudget",
|
|
||||||
"TestEffectExplicitSkillRootBudget/profile", "TestEffectExplicitSkillRootBudget/preview",
|
"TestEffectExplicitSkillRootBudget/profile", "TestEffectExplicitSkillRootBudget/preview",
|
||||||
"TestEffectExplicitSkillRootBudget/slash", "TestEffectExplicitSkillRootBudget/chips",
|
"TestEffectExplicitSkillRootBudget/slash", "TestEffectExplicitSkillRootBudget/chips",
|
||||||
"TestEffectExplicitSkillRootBudget/goal", "TestEffectExplicitSkillRootBudget/context_zero",
|
"TestEffectExplicitSkillRootBudget/goal", "TestEffectExplicitSkillRootBudget/context_zero",
|
||||||
@@ -883,8 +750,7 @@ jobs:
|
|||||||
"TestRootAuxiliaryTokenBudget/summary_missing", "TestRootAuxiliaryTokenBudget/summary_disabled",
|
"TestRootAuxiliaryTokenBudget/summary_missing", "TestRootAuxiliaryTokenBudget/summary_disabled",
|
||||||
"TestRootAuxiliaryTokenBudget/diagnosis", "TestRootAuxiliaryTokenBudget/diagnosis_failed",
|
"TestRootAuxiliaryTokenBudget/diagnosis", "TestRootAuxiliaryTokenBudget/diagnosis_failed",
|
||||||
"TestRootAuxiliaryTokenBudget/diagnosis_missing", "TestRootAuxiliaryTokenBudget/diagnosis_disabled",
|
"TestRootAuxiliaryTokenBudget/diagnosis_missing", "TestRootAuxiliaryTokenBudget/diagnosis_disabled",
|
||||||
"TestRootAuxiliaryManualCompactionOutsideRun", "TestRootAuxiliaryBudgetProjectionKeepsOldTask",
|
"TestRootAuxiliaryManualCompactionOutsideRun", "TestEffectRootAuxiliarySummaryBudget", "TestEffectRootAuxiliarySummaryBudget/configured",
|
||||||
"TestEffectRootAuxiliarySummaryBudget", "TestEffectRootAuxiliarySummaryBudget/configured",
|
|
||||||
"TestEffectRootAuxiliarySummaryBudget/disabled", "TestEffectRootAuxiliarySummaryBudget/missing_usage"] - $tests | length) == 0
|
"TestEffectRootAuxiliarySummaryBudget/disabled", "TestEffectRootAuxiliarySummaryBudget/missing_usage"] - $tests | length) == 0
|
||||||
' "$RUNNER_TEMP/root-auxiliary-budget.jsonl"
|
' "$RUNNER_TEMP/root-auxiliary-budget.jsonl"
|
||||||
|
|
||||||
@@ -974,11 +840,7 @@ jobs:
|
|||||||
"TestBoundedUsageObserverOwnsOneTerminal", "TestBoundedUsageObserverOwnsOneTerminal/reported",
|
"TestBoundedUsageObserverOwnsOneTerminal", "TestBoundedUsageObserverOwnsOneTerminal/reported",
|
||||||
"TestBoundedUsageObserverOwnsOneTerminal/billed_failure", "TestBoundedUsageObserverOwnsOneTerminal/without_sink",
|
"TestBoundedUsageObserverOwnsOneTerminal/billed_failure", "TestBoundedUsageObserverOwnsOneTerminal/without_sink",
|
||||||
"TestBoundedUsageObserverOwnsOneTerminal/missing", "TestBoundedUsageObserverOwnsOneTerminal/input_refused",
|
"TestBoundedUsageObserverOwnsOneTerminal/missing", "TestBoundedUsageObserverOwnsOneTerminal/input_refused",
|
||||||
"TestRootBoundedReviewerBudget", "TestRootBoundedReviewerBudget/reported",
|
"TestEffectRootBoundedAdvisorBudget",
|
||||||
"TestRootBoundedReviewerBudget/billed_failure", "TestRootBoundedReviewerBudget/missing_usage",
|
|
||||||
"TestRootBoundedReviewerBudget/disabled", "TestRootBoundedReviewerBudget/no_emission",
|
|
||||||
"TestRootBoundedReviewerBudget/projected_job_context", "TestRootBoundedNestedBudgetChargesOnce",
|
|
||||||
"TestRootBoundedLateProjectionStaysWithOldTask", "TestEffectRootBoundedAdvisorBudget",
|
|
||||||
"TestEffectRootBoundedAdvisorBudget/reported", "TestEffectRootBoundedAdvisorBudget/disabled",
|
"TestEffectRootBoundedAdvisorBudget/reported", "TestEffectRootBoundedAdvisorBudget/disabled",
|
||||||
"TestEffectRootBoundedAdvisorBudget/missing_usage"] - $tests | length) == 0
|
"TestEffectRootBoundedAdvisorBudget/missing_usage"] - $tests | length) == 0
|
||||||
' "$RUNNER_TEMP/bounded-root-budget.jsonl"
|
' "$RUNNER_TEMP/bounded-root-budget.jsonl"
|
||||||
|
|||||||
@@ -1,135 +0,0 @@
|
|||||||
---
|
|
||||||
owner: @SivanCola
|
|
||||||
backup: @esengine
|
|
||||||
status: active
|
|
||||||
reviewed: 2026-10-28
|
|
||||||
---
|
|
||||||
|
|
||||||
# Carried proof and file state / 恢复证明与文件状态
|
|
||||||
|
|
||||||
## Behavior / 行为
|
|
||||||
|
|
||||||
A pending Delivery change may carry verification, inspection and sign-off
|
|
||||||
across a Controller rebuild. Its fingerprint now includes regular-file bytes
|
|
||||||
and the full file mode reported by Go. Changing permissions without changing
|
|
||||||
bytes invalidates that carried proof and requires fresh evidence.
|
|
||||||
|
|
||||||
Delivery 待完成修改可在 Controller 重建后保留验证、检查和签收证明。指纹现在同时
|
|
||||||
绑定普通文件字节与 Go 返回的完整文件模式。只改权限、不改内容,也会使旧证明失效,
|
|
||||||
恢复后需要重新取得证据。
|
|
||||||
|
|
||||||
The existing content-version reader supplies the digest and detects observed
|
|
||||||
read changes. The proof owner additionally checks file identity, mode, size
|
|
||||||
and modification time around that read. It does not change permissions or
|
|
||||||
repair files. Absence has its own versioned fingerprint.
|
|
||||||
|
|
||||||
既有内容版本读取器提供摘要并检测读取期间观察到的变化;证明 owner 另外核对读取
|
|
||||||
前后的文件身份、模式、大小与修改时间。它不修改权限或修复文件。文件缺失使用独立
|
|
||||||
的版本化指纹。
|
|
||||||
|
|
||||||
Every nonregular path returns an empty fingerprint and never reuses carried
|
|
||||||
proof. This includes a symlink to an otherwise regular file, as well as
|
|
||||||
directories and special files. A dangling symlink is not absence.
|
|
||||||
|
|
||||||
The cost is fresh verification, inspection and sign-off after continuation or rebuild even
|
|
||||||
when a symlink and its target bytes have not changed. This invalidation does
|
|
||||||
not itself produce a separate warning. Existing tools can still collect fresh
|
|
||||||
evidence; tool permissions and normal completion rules are unchanged.
|
|
||||||
|
|
||||||
所有非普通文件路径返回空指纹,均不复用携带的证明,包括指向普通文件的符号链接、
|
|
||||||
目录与特殊文件;悬空链接不算文件缺失。即使链接及目标字节没有变化,继续执行或
|
|
||||||
重建后也要重新验证、检查和签收,这是明确的复用成本;失效本身不会单独显示警告。
|
|
||||||
仍可通过原工具收集新证据,不改变工具权限或正常完成规则。
|
|
||||||
|
|
||||||
## Persisted compatibility / 持久化兼容性
|
|
||||||
|
|
||||||
The existing `DeliveryCheckpoint.Proven.Paths` map remains a map of strings.
|
|
||||||
New values use the `file-state-v1:` prefix. No field, enum, RPC, configuration
|
|
||||||
or session format is added, and comparison does not rewrite the checkpoint.
|
|
||||||
|
|
||||||
既有 `DeliveryCheckpoint.Proven.Paths` 仍为字符串映射,新值使用 `file-state-v1:`
|
|
||||||
前缀。不新增字段、枚举、RPC、配置或会话格式,比较过程不改写 checkpoint。
|
|
||||||
|
|
||||||
| Fingerprint | Current reader | Previous byte-only reader |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| Legacy raw SHA-256 or `absent` | Reads Goal data; requires fresh proof | Retains its previous behavior |
|
|
||||||
| Current regular-file state | Reuses only matching observed state | Reads Goal data; mismatch requires fresh proof |
|
|
||||||
| Current absence | Reuses only actual absence | Mismatch requires fresh proof |
|
|
||||||
| Unknown future value | Mismatch requires fresh proof | Mismatch requires fresh proof |
|
|
||||||
|
|
||||||
Legacy values cannot prove which permissions or file kind were checked.
|
|
||||||
They are deliberately not upgraded from current metadata: that would invent
|
|
||||||
past evidence. Existing goals and transcripts remain readable; after upgrade
|
|
||||||
or downgrade, a pending goal may need verification, inspection and sign-off again.
|
|
||||||
|
|
||||||
旧值不能证明当时检查过哪些权限与文件类型,因此不会用当前元数据自动补成历史
|
|
||||||
证据。既有 Goal 和会话仍可读取;升级或降级后,待完成 Goal 可能需要重新验证、
|
|
||||||
检查与签收。新旧程序共存不等于已解决其他持久化写入协议问题。
|
|
||||||
|
|
||||||
## Evidence and limits / 验证与限制
|
|
||||||
|
|
||||||
The Boot regression uses real file tools, a real verification command and
|
|
||||||
production Goal persistence. It closes one Controller, loads its session and
|
|
||||||
sidecar into a second Boot, then observes structured readiness audits after an
|
|
||||||
external permission-only edit. Unchanged and content-edited files are controls.
|
|
||||||
|
|
||||||
Boot 回归通过真实文件工具、验证命令及生产 Goal 持久化生成证明,关闭 Controller,
|
|
||||||
再用第二次 Boot 加载会话与 sidecar。外部只改权限后,测试检查结构化 readiness
|
|
||||||
审计,并保留未变更与内容变更对照。
|
|
||||||
|
|
||||||
Every arm still owes a high-risk review. The regression distinguishes which
|
|
||||||
verification, inspection and sign-off obligations return; it does not show an
|
|
||||||
otherwise complete Goal bypassing every finalization gate.
|
|
||||||
|
|
||||||
所有分支仍欠高风险审查。回归区分恢复后哪些验证、检查和签收要求重新出现,不把
|
|
||||||
这一局部证明错误描述为已经绕过所有完成门禁。
|
|
||||||
|
|
||||||
This is a scripted provider and two builds within one test process, not a
|
|
||||||
live incident, HTTP/browser test or actual process-death recovery. The Windows
|
|
||||||
inventory requires 14 named events across Agent and Boot without skips,
|
|
||||||
including parent events. Unix tests also refuse real links and a FIFO.
|
|
||||||
|
|
||||||
The shared `scripts/windows-concurrency-tests.mjs` step reads the package-qualified
|
|
||||||
`carried-proof-file-state.json` inventory under `.github/windows-concurrency/`.
|
|
||||||
It retains all 14 requirements and both package terminals; broad smoke is separate.
|
|
||||||
|
|
||||||
这是脚本 provider 与同一测试进程中的两次构建,不是线上事故、HTTP/浏览器测试
|
|
||||||
或实际进程死亡恢复。Windows 清单要求 Agent 与 Boot 两个包的 14 个命名事件无
|
|
||||||
skip 通过,计数包含父测试。Unix 测试另覆盖真实链接与 FIFO 的拒绝。
|
|
||||||
|
|
||||||
共享脚本读取 `.github/windows-concurrency/carried-proof-file-state.json` 中按包
|
|
||||||
限定的清单,保留全部 14 项与两个包终态要求;broad smoke 仍单独运行。
|
|
||||||
|
|
||||||
For regular files on Windows this contract covers content and the read-only bit
|
|
||||||
only. Go's synthesized mode does not establish POSIX permission semantics or
|
|
||||||
cover Windows ACLs and full security descriptors.
|
|
||||||
|
|
||||||
On any platform, Go file mode does not capture ownership or extended attributes.
|
|
||||||
The checks are observations, not an atomic
|
|
||||||
multi-file snapshot or protection against arbitrary concurrent external writers.
|
|
||||||
Rooted source authority, physical quiescence and durable publication remain separate.
|
|
||||||
|
|
||||||
Windows 普通文件合同仅覆盖内容与只读位;Go 合成的模式不代表 POSIX 权限语义,
|
|
||||||
也不覆盖 Windows ACL 或完整安全描述符。任何平台上的 Go 模式均不涵盖所有者与
|
|
||||||
扩展属性。这些检查是
|
|
||||||
观察,不是多文件原子快照,也不能约束任意并发外部写入者。根目录授权、物理静默
|
|
||||||
与持久发布仍由其他机制负责。
|
|
||||||
|
|
||||||
## Local cost observation / 本机开销观察
|
|
||||||
|
|
||||||
Three 200 ms benchmark samples on a Darwin/arm64 M1 Max produced these medians.
|
|
||||||
The old arm uses the exact preceding production owner with the same benchmark.
|
|
||||||
These are sequential local samples, not a production latency guarantee.
|
|
||||||
|
|
||||||
| File size | Byte-only owner | File-state owner | Allocated bytes, old / new |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| 4 KiB | 18.569 µs/op | 28.771 µs/op | 5,400 / 34,552 |
|
|
||||||
| 1 MiB | 616.436 µs/op | 535.338 µs/op | 1,057,306 / 34,558 |
|
|
||||||
|
|
||||||
Metadata checks add work for small files. The existing streaming content reader
|
|
||||||
uses bounded scratch space instead of allocating the whole regular file.
|
|
||||||
This does not establish a general speed-up or a bound for many-file recovery.
|
|
||||||
|
|
||||||
上述结果来自 Darwin/arm64 M1 Max 上三次 200 ms 采样的中位数,旧侧使用精确前版
|
|
||||||
生产 owner 与相同 benchmark。元数据检查增加小文件开销,流式读取减少大文件的
|
|
||||||
整块分配;这些本机顺序采样不构成普遍加速结论或多文件恢复时延保证。
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
---
|
|
||||||
owner: @esengine
|
|
||||||
backup: @SivanCola
|
|
||||||
status: active
|
|
||||||
reviewed: 2026-10-28
|
|
||||||
---
|
|
||||||
|
|
||||||
# Ancestor continuation admission / 祖先续跑准入
|
|
||||||
|
|
||||||
## Behavior / 行为
|
|
||||||
|
|
||||||
1. Within one `SubagentStore`, continuing an ancestor transcript reserves its
|
|
||||||
canonical nearest source and target parent session before searching for a
|
|
||||||
current-session copy. The reservation lasts until the returned run releases.
|
|
||||||
2. A competing continuation for that pair is refused as already in progress,
|
|
||||||
including before the first copy publishes its `running` metadata. It MUST
|
|
||||||
NOT create another copy or make another provider request.
|
|
||||||
3. `continue_from` and the accepted legacy `fork_from` input share this owner.
|
|
||||||
Referring to an older ancestor or its nearest lineage copy uses the same
|
|
||||||
reservation. Different target parents and different sources remain separate.
|
|
||||||
4. Failed preparation and abandoned unpublished runs release their reservation.
|
|
||||||
After a completed run releases, another continuation reuses its persisted
|
|
||||||
copy. Direct current-reference continuation keeps its existing ref lock.
|
|
||||||
|
|
||||||
1. 同一 `SubagentStore` 在查找当前会话副本前,按最近祖先来源和目标父会话预留续跑归属;预留随返回的 run 一起释放。
|
|
||||||
2. 首份副本尚未发布 `running` 元数据时,同一组合的竞争续跑也会被拒绝;不得再创建副本或发起模型请求。
|
|
||||||
3. `continue_from` 与兼容的旧 `fork_from` 输入共用此归属。较早祖先及其最近副本归一到同一来源;不同目标会话、不同来源保持独立。
|
|
||||||
4. 准备失败或放弃未发布的 run 会释放预留。已完成 run 释放后,续跑复用原持久化副本;直接按当前副本引用续跑仍使用原引用锁。
|
|
||||||
|
|
||||||
`errors.Is(err, ErrAncestorCopyBusy)` identifies the refusal through wrapping.
|
|
||||||
TaskTool uses the existing `subagent.settling` answer code and preserves that
|
|
||||||
sentinel; callers do not classify error prose.
|
|
||||||
|
|
||||||
包装后的错误仍可用 `errors.Is(err, ErrAncestorCopyBusy)` 识别;TaskTool 使用既有
|
|
||||||
`subagent.settling` 回答码并保留此标识,不解析错误文案。
|
|
||||||
|
|
||||||
## Compatibility and limits / 兼容与边界
|
|
||||||
|
|
||||||
| Boundary / 边界 | Contract / 合同 |
|
|
||||||
| --- | --- |
|
|
||||||
| Storage / 存储 | No metadata, transcript, status or schema change. / 不改变元数据、转录、状态或 schema。 |
|
|
||||||
| Existing ambiguity / 既有歧义 | Multiple existing copies remain refused; no automatic selection or deletion. / 已有多个副本仍拒绝,不自动选择或删除。 |
|
|
||||||
| Scope / 范围 | One Store instance; existing process-local locking contract. / 仅同一 Store 实例,沿用进程内锁合同。 |
|
|
||||||
| Cross-version writers / 跨版本写入 | No cross-process or old-writer fence; old binaries retain their behavior. / 不提供跨进程或旧写入者隔离。 |
|
|
||||||
| Recovery / 恢复 | No resume of failed/interrupted children, durable reservation or restart recovery. / 不恢复失败或中断子任务,不提供持久化预留与重启恢复。 |
|
|
||||||
| Authority / 权限 | Tool permission, cancellation authority, provider prefix and tool schema are unchanged. / 工具权限、取消权限、模型前缀和工具 schema 不变。 |
|
|
||||||
|
|
||||||
## Validation / 验证
|
|
||||||
|
|
||||||
1. Store regressions hold an unpublished preparation, cover both input routes,
|
|
||||||
nearest-source aliases, independent parents/sources and release after errors.
|
|
||||||
2. TaskTool regressions block the existing parent-destruction callback before
|
|
||||||
`MarkRunning` writes metadata. A competing call is refused; the first call
|
|
||||||
receives the real persisted source transcript and creates the only copy.
|
|
||||||
3. These are local Store/TaskTool tests with a scripted provider, not a live
|
|
||||||
provider, full Boot, browser, crash/restart or physical-process-scope test.
|
|
||||||
4. The Windows workflow requires every named regression and the package terminal
|
|
||||||
pass, with no skips. Local cross-compilation is not native Windows evidence.
|
|
||||||
|
|
||||||
1. Store 回归保留未发布的准备结果,覆盖两种输入、最近来源别名、不同会话和来源,以及错误后的释放。
|
|
||||||
2. TaskTool 回归在 `MarkRunning` 写元数据前阻塞既有父会话销毁检查回调。竞争调用被拒绝,首个调用读取真实持久化来源转录并创建唯一副本。
|
|
||||||
3. 以上是本机 Store/TaskTool 与脚本 provider 验证,不是线上 provider、完整 Boot、浏览器、崩溃重启或物理进程范围验证。
|
|
||||||
4. Windows 工作流要求全部指定测试及包终态通过且零跳过;本机交叉编译不等于 Windows 原生执行。
|
|
||||||
|
|
||||||
A second TaskTool regression requests background execution without a job manager.
|
|
||||||
Preparation succeeds, then normal completion abandons the unstarted run.
|
|
||||||
No test calls `Release` for it; a foreground retry proves admission was freed.
|
|
||||||
|
|
||||||
另一 TaskTool 回归在没有 job manager 时请求后台执行:准备成功后由正常结束路径
|
|
||||||
放弃尚未启动的 run;测试不调用其 `Release`,前台重试证明预留已释放。
|
|
||||||
|
|
||||||
The shared `scripts/windows-concurrency-tests.mjs` step reads additive,
|
|
||||||
package-qualified inventories under `.github/windows-concurrency/`. This suite
|
|
||||||
requires 17 named passes including parents. The broad smoke remains.
|
|
||||||
|
|
||||||
共享脚本读取 `.github/windows-concurrency/` 中按包限定的独立清单;此套件要求含
|
|
||||||
父测试的 17 个指定测试通过,保留 broad smoke。
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
// Focused Windows concurrency contracts live in additive, package-qualified
|
|
||||||
// inventories. New regressions do not need another workflow step or verifier.
|
|
||||||
import assert from 'node:assert/strict';
|
|
||||||
import { closeSync, mkdirSync, openSync, readFileSync, readdirSync } from 'node:fs';
|
|
||||||
import { dirname, join, resolve } from 'node:path';
|
|
||||||
import { spawnSync } from 'node:child_process';
|
|
||||||
import { fileURLToPath } from 'node:url';
|
|
||||||
|
|
||||||
export function readInventory(directory) {
|
|
||||||
const files = readdirSync(directory).filter(name => name.endsWith('.json')).sort();
|
|
||||||
assert(files.length > 0, 'no Windows concurrency inventories');
|
|
||||||
const required = new Map();
|
|
||||||
for (const file of files) {
|
|
||||||
const groups = JSON.parse(readFileSync(join(directory, file), 'utf8'));
|
|
||||||
assert(Array.isArray(groups) && groups.length > 0, `${file}: empty inventory`);
|
|
||||||
for (const group of groups) {
|
|
||||||
assert(group && /^reasonix\/internal\/(?:[a-z0-9_]+\/)*[a-z0-9_]+$/.test(group.package), `${file}: invalid package`);
|
|
||||||
assert(Array.isArray(group.tests) && group.tests.length > 0, `${file}: empty tests`);
|
|
||||||
const tests = required.get(group.package) ?? new Set();
|
|
||||||
for (const test of group.tests) {
|
|
||||||
assert(typeof test === 'string' && /^Test[A-Za-z0-9_]+(?:\/[^\s]+)?$/.test(test), `${file}: invalid test`);
|
|
||||||
tests.add(test);
|
|
||||||
}
|
|
||||||
required.set(group.package, tests);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const tests of required.values()) {
|
|
||||||
for (const test of tests) assert(tests.has(test.split('/')[0]), `missing parent for ${test}`);
|
|
||||||
}
|
|
||||||
return required;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function verifyInventory(required, raw) {
|
|
||||||
const passed = new Map();
|
|
||||||
const packages = new Set();
|
|
||||||
for (const line of raw.split(/\r?\n/).filter(line => line.trim())) {
|
|
||||||
const event = JSON.parse(line);
|
|
||||||
assert(required.has(event.Package), `unexpected package: ${event.Package}`);
|
|
||||||
assert(!['skip', 'fail'].includes(event.Action), `${event.Package}: ${event.Action}: ${event.Test ?? '(package)'}`);
|
|
||||||
if (event.Action !== 'pass') continue;
|
|
||||||
if (!event.Test) {
|
|
||||||
packages.add(event.Package);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const tests = passed.get(event.Package) ?? new Set();
|
|
||||||
assert(!tests.has(event.Test), `duplicate pass: ${event.Package}/${event.Test}`);
|
|
||||||
tests.add(event.Test);
|
|
||||||
passed.set(event.Package, tests);
|
|
||||||
}
|
|
||||||
let count = 0;
|
|
||||||
for (const [pkg, tests] of required) {
|
|
||||||
assert(packages.has(pkg), `missing package terminal: ${pkg}`);
|
|
||||||
for (const test of tests) {
|
|
||||||
assert(passed.get(pkg)?.has(test), `missing test: ${pkg}/${test}`);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { requiredTests: count, packages: required.size };
|
|
||||||
}
|
|
||||||
|
|
||||||
function main() {
|
|
||||||
const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
||||||
const required = readInventory(join(root, '.github/windows-concurrency'));
|
|
||||||
const roots = [...new Set([...required.values()].flatMap(tests => [...tests].map(test => test.split('/')[0])))].sort();
|
|
||||||
const output = resolve(process.argv[2] ?? join(process.env.RUNNER_TEMP ?? '.', 'concurrency-windows.jsonl'));
|
|
||||||
mkdirSync(dirname(output), { recursive: true });
|
|
||||||
const fd = openSync(output, 'w');
|
|
||||||
let result;
|
|
||||||
try {
|
|
||||||
result = spawnSync('go', ['test', '-count=1', '-timeout=3m', '-json', '-run', `^(${roots.join('|')})$`, ...required.keys()], {
|
|
||||||
cwd: root, stdio: ['ignore', fd, 'inherit'],
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
closeSync(fd);
|
|
||||||
}
|
|
||||||
assert(!result.error, result.error?.message);
|
|
||||||
assert.equal(result.status, 0, `go test failed (${result.signal ?? result.status}); see ${output}`);
|
|
||||||
console.log(JSON.stringify({ ...verifyInventory(required, readFileSync(output, 'utf8')), output }));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) main();
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
import assert from 'node:assert/strict';
|
|
||||||
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
||||||
import { tmpdir } from 'node:os';
|
|
||||||
import { join } from 'node:path';
|
|
||||||
import { spawnSync } from 'node:child_process';
|
|
||||||
import test from 'node:test';
|
|
||||||
import { readInventory, verifyInventory } from './windows-concurrency-tests.mjs';
|
|
||||||
|
|
||||||
test('long invalid subtest suffix is rejected without repeated slash partitioning', () => {
|
|
||||||
const dir = mkdtempSync(join(tmpdir(), 'concurrency-inventory-'));
|
|
||||||
try {
|
|
||||||
const inventory = tests => JSON.stringify([{ package: 'reasonix/internal/example', tests }]);
|
|
||||||
const file = join(dir, 'names.json');
|
|
||||||
const valid = ['Test0', 'Test0/a/b', 'Test0/!/', 'Test0//'];
|
|
||||||
writeFileSync(file, inventory(valid));
|
|
||||||
assert.deepEqual([...readInventory(dir).values()][0], new Set(valid));
|
|
||||||
writeFileSync(file, inventory(['Test0', `Test0/${'!/'.repeat(10000)} `]));
|
|
||||||
const script = `import assert from 'node:assert/strict';
|
|
||||||
import { readInventory } from ${JSON.stringify(new URL('./windows-concurrency-tests.mjs', import.meta.url).href)};
|
|
||||||
assert.throws(() => readInventory(process.argv[1]), /invalid test/);`;
|
|
||||||
const result = spawnSync(process.execPath, ['--input-type=module', '-e', script, dir], { timeout: 5000, encoding: 'utf8' });
|
|
||||||
assert.ifError(result.error);
|
|
||||||
assert.equal(result.status, 0, result.stderr);
|
|
||||||
} finally {
|
|
||||||
rmSync(dir, { recursive: true, force: true });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('additive manifests keep package-qualified requirements', () => {
|
|
||||||
const dir = mkdtempSync(join(tmpdir(), 'concurrency-inventory-'));
|
|
||||||
try {
|
|
||||||
const a = 'reasonix/internal/first', b = 'reasonix/internal/second';
|
|
||||||
writeFileSync(join(dir, 'one.json'), JSON.stringify([{ package: a, tests: ['TestShared', 'TestShared/case'] }]));
|
|
||||||
writeFileSync(join(dir, 'two.json'), JSON.stringify([{ package: b, tests: ['TestShared'] }]));
|
|
||||||
const required = readInventory(dir);
|
|
||||||
const events = [
|
|
||||||
{ Package: a, Action: 'pass', Test: 'TestShared/case' },
|
|
||||||
{ Package: a, Action: 'pass', Test: 'TestShared' },
|
|
||||||
{ Package: a, Action: 'pass' },
|
|
||||||
{ Package: b, Action: 'pass', Test: 'TestShared' },
|
|
||||||
{ Package: b, Action: 'pass' },
|
|
||||||
];
|
|
||||||
const raw = values => values.map(value => JSON.stringify(value)).join('\r\n');
|
|
||||||
assert.deepEqual(verifyInventory(required, raw(events)), { requiredTests: 3, packages: 2 });
|
|
||||||
for (let i = 0; i < events.length; i++) {
|
|
||||||
assert.throws(() => verifyInventory(required, raw(events.filter((_, index) => index !== i))));
|
|
||||||
assert.throws(() => verifyInventory(required, raw(events.map((event, index) => index === i ? { ...event, Action: 'skip' } : event))));
|
|
||||||
}
|
|
||||||
assert.throws(() => verifyInventory(required, raw([...events, { Package: a, Action: 'fail' }])));
|
|
||||||
assert.throws(() => verifyInventory(required, raw([...events, events[0]])));
|
|
||||||
assert.throws(() => verifyInventory(required, '{'));
|
|
||||||
writeFileSync(join(dir, 'two.json'), JSON.stringify([{ package: b, tests: ['TestOrphan/case'] }]));
|
|
||||||
assert.throws(() => readInventory(dir));
|
|
||||||
writeFileSync(join(dir, 'two.json'), JSON.stringify([{ package: '../other', tests: ['TestShared'] }]));
|
|
||||||
assert.throws(() => readInventory(dir));
|
|
||||||
writeFileSync(join(dir, 'two.json'), '[]');
|
|
||||||
assert.throws(() => readInventory(dir));
|
|
||||||
rmSync(join(dir, 'one.json'));
|
|
||||||
rmSync(join(dir, 'two.json'));
|
|
||||||
assert.throws(() => readInventory(dir));
|
|
||||||
} finally {
|
|
||||||
rmSync(dir, { recursive: true, force: true });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Reference in new issue
Block a user