Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1455e33
feat: add pnpm materialization profiles
schickling-assistant Jun 29, 2026
1a74613
fix: refine pnpm materialization profile contract
schickling-assistant Jun 29, 2026
97ca2aa
docs: clarify pnpm split files profile
schickling-assistant Jun 29, 2026
f4b74f8
fix: repair notion-cli deps fod hash
schickling-assistant Jun 29, 2026
ea51039
feat: configure pnpm materialization store paths
schickling-assistant Jun 30, 2026
e6e07cf
fix: keep pnpm hardlink profile local-only
schickling-assistant Jun 30, 2026
bda697d
fix: gate local pnpm CAS overrides on Linux
schickling-assistant Jun 30, 2026
b845e9d
fix(nix): refresh genie and megarepo deps hashes
schickling-assistant Jun 30, 2026
e4df801
fix(nix): refresh notion-md deps hash
schickling-assistant Jun 30, 2026
093363b
fix: refresh materialization profile artifacts after rebase
schickling-assistant Jul 1, 2026
9173888
fix(nix): refresh materialization profile fod hashes
schickling-assistant Jul 1, 2026
ef06e57
fix(nix): refresh genie deps hash
schickling-assistant Jul 1, 2026
ab7f3c4
fix: refresh generated labels
schickling-assistant Jul 1, 2026
2f7128d
fix(nix): refresh rebased CLI dependency hashes
schickling-assistant Jul 1, 2026
513b29d
fix(nix): refresh ci-tools dependency hash
schickling-assistant Jul 1, 2026
3ec8996
fix(genie): keep packaged workflow imports pure
schickling-assistant Jul 1, 2026
02c742e
fix(ci-tools): refresh packaged deps hash
schickling-assistant Jul 1, 2026
2199201
fix(pnpm-cli): retain workspace source inputs
schickling-assistant Jul 1, 2026
58dc9b7
fix(nix): refresh oxc config deps hash
schickling-assistant Jul 1, 2026
a1db00a
fix(pnpm-cli): retain workspace source inputs
schickling-assistant Jul 1, 2026
9ebb4e3
fix(nix): refresh megarepo deps hash
schickling-assistant Jul 1, 2026
d646d4a
style(pnpm-cli): format source capture attrs
schickling-assistant Jul 1, 2026
5e0f780
style(pnpm-cli): format source capture attrs
schickling-assistant Jul 1, 2026
e8abdbc
docs: record workspace source input fix
schickling-assistant Jul 1, 2026
0782111
fix(nix): preserve downstream workspace source inputs
schickling-assistant Jul 1, 2026
f25309b
style(pnpm-cli): format source capture attrs
schickling-assistant Jul 1, 2026
0afb1c7
fix(nix): refresh notion pnpm dependency hashes
schickling-assistant Jul 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ All notable changes to this project will be documented in this file.

### Changed

- **@overeng/genie / @overeng/ci-tools**: Keep packaged Genie generation pure by
staging generated workflow imports through a dependency-free ci-tools
workflow-report contract, declaring ci-tools' runtime Effect closure
explicitly, and refreshing the managed Genie and ci-tools pnpm-deps hashes.

- **nix workspace tools / mk-pnpm-cli**: Preserve external workspace source
roots as sandbox inputs for full workspace materialization, so downstream
flake consumers can build CLIs whose install roots copy packages from an
effect-utils flake input; refresh the affected Notion CLI and oxlint
plugin dependency hashes after the source-input repair.

- **nix packages / @overeng/genie**: Refresh the `genie-unwrapped`
pnpm-deps fixed-output hash after the materialization profile rebase.

- **devenv deploy tasks / @overeng/ci-tools**: Centralize deploy-preview
workflow-report and GitHub output emission in `ci-tools`, including
provider-owned skip records, URL outputs, and task metadata, so generated CI
Expand Down Expand Up @@ -83,6 +97,11 @@ All notable changes to this project will be documented in this file.
typed OTEL spans through the production bounded git runner, so CI fixture
stalls can produce inspectable trace evidence.

- **devenv/pnpm**: Add an explicit `materializationProfile` API and profile
evidence contract for `ciJobLocal`, transitional Linux `splitFilesCas`,
macOS `darwinSplitCas`, opt-in `linuxSharedHardlink`, and `isolated` without
changing Linux `auto` to hardlink materialization yet.

- **@overeng/genie**: Document the intended package export type-proof
architecture: strict proofs should use an explicit compiler executable
boundary (`tsgo` by default, custom only by explicit override) instead of
Expand Down Expand Up @@ -223,6 +242,9 @@ All notable changes to this project will be documented in this file.
by keeping the short-lived PTY session alive long enough for peek/attach
assertions.

- **@overeng/genie, @overeng/megarepo**: Refresh stale pnpm dependency FOD
hashes for the CAS materialization profile branch.

- **@overeng/genie**: Emit Starlark `#` generated-file headers for Buck2
`BUCK`, `.bzl`, and `.bxl` outputs.

Expand Down
10 changes: 5 additions & 5 deletions genie/ci-workflow/reporting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
workflowReportManagedMarker,
workflowReportRecordLineMarker,
type WorkflowReportRecord,
} from '../../packages/@overeng/ci-tools/src/mod.ts'
} from '../../packages/@overeng/ci-tools/src/workflow-report-contract.ts'
import { runDevenvTasksBefore, shellSingleQuote } from './shared.ts'

type GitHubWorkflowStep = GitHubWorkflowArgs['jobs'][string]['steps'][number]
Expand Down Expand Up @@ -60,10 +60,10 @@ export type WorkflowReportCommentBodyStepOptions = {
export const workflowReportProducerStep = (
opts: WorkflowReportProducerStepOptions,
): GitHubWorkflowStep => {
const line = encodeWorkflowReportRecordLine(
opts.record,
opts.marker ?? workflowReportRecordLineMarker,
)
const line = encodeWorkflowReportRecordLine({
record: opts.record,
marker: opts.marker ?? workflowReportRecordLineMarker,
})
const outputPath = opts.outputPath

return {
Expand Down
2 changes: 1 addition & 1 deletion genie/deploy-preview/shared.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { workflowReportRecordLineMarker } from '../../packages/@overeng/ci-tools/src/mod.ts'
import { workflowReportRecordLineMarker } from '../../packages/@overeng/ci-tools/src/workflow-report-contract.ts'

export const deployTargetEnvSuffix = (name: string) =>
name
Expand Down
156 changes: 153 additions & 3 deletions nix/devenv-modules/tasks/shared/pnpm-task-helpers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -146,18 +146,137 @@ process.exit(
EOF
}

dependency_materialization_validate_same_device() {
local node_bin="$1"
local workspace_dir="$2"
local files_path="$3"

"$node_bin" - "$workspace_dir" "$files_path" <<'EOF'
const fs = require('node:fs')

const [workspaceDir, filesPath] = process.argv.slice(2)
const realWorkspace = fs.realpathSync(workspaceDir)
const realFiles = fs.realpathSync(filesPath)
const workspaceDev = fs.statSync(realWorkspace).dev
const filesDev = fs.statSync(realFiles).dev

if (workspaceDev !== filesDev) {
console.error('[pnpm] linuxSharedHardlink requires workspace and files pool on the same device')
console.error(`[pnpm] workspace: ${realWorkspace} (dev ${workspaceDev})`)
console.error(`[pnpm] files pool: ${realFiles} (dev ${filesDev})`)
console.error('[pnpm] Use materializationProfile = "isolated" for cross-device reproduction.')
process.exit(1)
}
EOF
}

prepare_dependency_materialization_store() {
local node_bin="$1"
local requested_profile="$2"
local host_is_darwin="$3"
local workspace_dir="$4"
local store_dir="$5"

case "$requested_profile" in
auto | ciJobLocal | splitFilesCas | darwinSplitCas | linuxSharedHardlink | isolated) ;;
*)
echo "[pnpm] Unsupported materializationProfile: $requested_profile" >&2
exit 1
;;
esac

if [ -z "${store_dir:-}" ]; then
echo "[pnpm] npm_config_store_dir is empty; cannot prepare dependency materialization store" >&2
exit 1
fi

local store_version_dir="$store_dir/v11"
local files_path="$store_version_dir/files"
local shared_files_path="${PNPM_SHARED_FILES_DIR:-$HOME/.local/share/pnpm/shared-files}/v11"
local effective_profile="$requested_profile"

if [ -n "${CI:-}" ] && [ "$requested_profile" = auto ]; then
effective_profile="ciJobLocal"
elif [ "$requested_profile" = auto ]; then
if [ "$host_is_darwin" = true ]; then
effective_profile="darwinSplitCas"
else
effective_profile="splitFilesCas"
fi
fi

mkdir -p "$store_version_dir"

case "$effective_profile" in
ciJobLocal | isolated)
if [ -L "$files_path" ]; then
rm "$files_path"
fi
mkdir -p "$files_path"
;;
splitFilesCas | darwinSplitCas | linuxSharedHardlink)
mkdir -p "$shared_files_path"
if [ -L "$files_path" ]; then
if [ "$(readlink "$files_path")" != "$shared_files_path" ]; then
echo "[pnpm] $files_path points at $(readlink "$files_path"), expected $shared_files_path" >&2
exit 1
fi
elif [ -e "$files_path" ]; then
if [ "$requested_profile" = auto ] && [ -d "$files_path" ] && [ -n "$(find "$files_path" -mindepth 1 -maxdepth 1 -print -quit)" ]; then
printf '%s\n' isolated
return 0
fi
if [ -d "$files_path" ] && [ -z "$(find "$files_path" -mindepth 1 -maxdepth 1 -print -quit)" ]; then
rmdir "$files_path"
else
echo "[pnpm] $files_path is a non-empty local files store; choose materializationProfile = \"isolated\" or run the coordinated migration" >&2
exit 1
fi
fi
if [ ! -L "$files_path" ]; then
ln -s "$shared_files_path" "$files_path"
fi
if [ "$effective_profile" = linuxSharedHardlink ]; then
dependency_materialization_validate_same_device "$node_bin" "$workspace_dir" "$files_path"
fi
;;
esac

printf '%s\n' "$effective_profile"
}

dependency_materialization_install_policy_flags() {
local profile="$1"

case "$profile" in
linuxSharedHardlink)
printf '%s\n' "--config.package-import-method=hardlink"
;;
ciJobLocal | splitFilesCas | darwinSplitCas | isolated)
printf '%s\n' "--config.package-import-method=clone-or-copy"
;;
*)
echo "[pnpm] Unsupported dependency materialization profile for install policy: $profile" >&2
exit 1
;;
esac
}

emit_dependency_materialization_profile() {
local node_bin="$1"
local contract_file="$2"
local store_trait="$3"
local output_file="${4:-}"
local workspace_dir="${5:-}"
local store_dir="${6:-}"
local package_import_method="${7:-}"

"$node_bin" - "$contract_file" "$store_trait" "$output_file" <<'EOF'
"$node_bin" - "$contract_file" "$store_trait" "$output_file" "$workspace_dir" "$store_dir" "$package_import_method" <<'EOF'
const crypto = require('node:crypto')
const fs = require('node:fs')
const path = require('node:path')

const [contractFile, storeTrait, outputFile] = process.argv.slice(2)
const [contractFile, storeTrait, outputFile, workspaceDir, storeDir, packageImportMethodArg] = process.argv.slice(2)
const contract = JSON.parse(fs.readFileSync(contractFile, 'utf8'))
const evidenceContractPath = path.isAbsolute(contractFile)
? path.relative(fs.realpathSync(process.cwd()), fs.realpathSync(contractFile))
Expand Down Expand Up @@ -197,6 +316,28 @@ if (trait === undefined) {
process.exit(1)
}

const storeLayoutVersion = contract.storeContract?.layoutVersion ?? 'v11'
const filesPath = storeDir ? path.join(storeDir, storeLayoutVersion, 'files') : undefined
const realPathOf = (candidate) => {
if (!candidate) return undefined
try {
return fs.realpathSync(candidate)
} catch {
return candidate
}
}
const filesRealPath = realPathOf(filesPath)
const workspaceRealPath = realPathOf(workspaceDir)
const sameDevice = (() => {
if (!workspaceRealPath || !filesRealPath) return undefined
try {
return fs.statSync(workspaceRealPath).dev === fs.statSync(filesRealPath).dev
} catch {
return undefined
}
})()
const packageImportMethod = packageImportMethodArg || trait.importMethod

const inputSections = Object.fromEntries(
profileContract.identityInputs.map((section) => {
if (!Object.prototype.hasOwnProperty.call(contract, section)) {
Expand Down Expand Up @@ -230,6 +371,11 @@ const profile = {
store: {
trait: storeTrait,
contract: inputSections.storeContract,
filesPath,
filesRealPath,
sameDeviceRequired: trait.sameDeviceRequired === true,
sameDevice,
packageImportMethod,
},
authorities: {
gc: trait.gcAuthority,
Expand Down Expand Up @@ -301,6 +447,7 @@ const singletonRegistry = {
{
id: rootId,
profileId: profile.profileId,
trait: profile.store?.trait,
project: projectDir,
store: storeDir,
filesPoolId: poolId,
Expand All @@ -310,6 +457,9 @@ const singletonRegistry = {
{
id: poolId,
filesPath,
filesRealPath: realFilesPath,
sameDeviceRequired: profile.store?.sameDeviceRequired === true,
sameDevice: profile.store?.sameDevice,
},
],
}
Expand Down Expand Up @@ -447,7 +597,7 @@ const profiles = Array.isArray(registry.profiles) ? registry.profiles : []
for (const profile of profiles
.filter((row) => row.filesPoolId === filesPoolId)
.sort((left, right) => left.id.localeCompare(right.id))) {
process.stdout.write(`${profile.project}\t${profile.store}\n`)
process.stdout.write(`${profile.project}\t${profile.store}\t${profile.trait ?? ''}\n`)
}
EOF
}
Expand Down
Loading
Loading