Phase B of PLAN_LICENSE_STANDARDISATION_EUPL12_20260419. Follows Phase A (c85f310f,4ddc54a0) which flipped the LICENSE file + README; this commit propagates EUPL-1.2 through source-file headers. 21 files touched across 4 distinct Apache-reference variants: - V1 (14 files) — full Apache header block (JS /* ... */): 2 routes + 1 controller + 7 services + 2 models + 3 utils. Replaced with equivalent EUPL-1.2 block pointing at EC canonical URL. - V2 (2 files) — inline JSDoc license line (Copyright Tractatus Project): src/routes/calendar.routes.js + src/models/ScheduledTask.model.js. Replaced with EUPL-1.2 v. 1.2 equivalent. - V3 (4 files) — Python docstring 'License: Apache 2.0': all 4 al-integration Python files. Replaced with 'License: EUPL-1.2'. - V4 (1 file) — al-integration/README.md bare 'Apache 2.0' under '## License' heading. Replaced with 'EUPL-1.2'. Verification: - grep -r "Apache License|Apache 2.0|apache.org/licenses" src/ al-integration/ returns zero matches (modulo venv). - Unit tests: 524/524 pass (npm run test:unit). - Integration test failures (177) are DB-connection infrastructure, pre-existing, unrelated to this header-only change. Sole author basis: TheFlow, 930+ commits, unilateral relicensing (same as Phase A). Replacement infrastructure also committed: scripts/relicense-apache-to-eupl.js (auto-detecting variant replacement, idempotent, --dry-run mode). Reusable for Phase C (community-repo sweep) if pattern structure aligns. Out-of-scope Apache mentions still in the repo (next pass, NOT Phase B): - SESSION_HANDOFF_ENFORCEMENT_COMPLETE.md (root doc) - CLAUDE_Tractatus_Maintenance_Guide.md (root doc) - For Claude Web/tractatus-claude-web-complete/** (docs snapshot subdirectory) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
157 lines
6 KiB
JavaScript
157 lines
6 KiB
JavaScript
#!/usr/bin/env node
|
|
/*
|
|
* Copyright 2025 John G Stroh
|
|
*
|
|
* Licensed under the European Union Public Licence, Version 1.2 (EUPL-1.2);
|
|
* you may not use this file except in compliance with the Licence.
|
|
*
|
|
* You may obtain a copy of the Licence at:
|
|
* https://interoperable-europe.ec.europa.eu/collection/eupl/eupl-text-eupl-12
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the Licence is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the Licence for the specific language governing permissions and
|
|
* limitations under the Licence.
|
|
*/
|
|
|
|
// Relicense Apache 2.0 → EUPL-1.2 across Tractatus source files.
|
|
// Phase B of PLAN_LICENSE_STANDARDISATION_EUPL12_20260419.
|
|
//
|
|
// Usage:
|
|
// node scripts/relicense-apache-to-eupl.js # Apply changes
|
|
// node scripts/relicense-apache-to-eupl.js --dry-run # Show changes without writing
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const DRY_RUN = process.argv.includes('--dry-run');
|
|
const REPO_ROOT = path.resolve(__dirname, '..');
|
|
|
|
// --- Variant 1: Full Apache header block (JS /* ... */) ---
|
|
const V1_APACHE = `/*
|
|
* Copyright 2025 John G Stroh
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/`;
|
|
|
|
const V1_EUPL = `/*
|
|
* Copyright 2025 John G Stroh
|
|
*
|
|
* Licensed under the European Union Public Licence, Version 1.2 (EUPL-1.2);
|
|
* you may not use this file except in compliance with the Licence.
|
|
*
|
|
* You may obtain a copy of the Licence at:
|
|
* https://interoperable-europe.ec.europa.eu/collection/eupl/eupl-text-eupl-12
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the Licence is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the Licence for the specific language governing permissions and
|
|
* limitations under the Licence.
|
|
*/`;
|
|
|
|
// --- Variant 2: Inline JSDoc license lines (inside descriptive block) ---
|
|
const V2_APACHE = ` * Copyright 2025 Tractatus Project\n * Licensed under Apache License 2.0`;
|
|
const V2_EUPL = ` * Copyright 2025 Tractatus Project\n * Licensed under the European Union Public Licence, v. 1.2 (EUPL-1.2)`;
|
|
|
|
// --- Variant 3: Python docstring License line ---
|
|
const V3_APACHE = `License: Apache 2.0`;
|
|
const V3_EUPL = `License: EUPL-1.2`;
|
|
|
|
// --- Variant 4: al-integration/README.md — bare "Apache 2.0" under "## License" heading ---
|
|
const V4_APACHE = `## License\n\nApache 2.0`;
|
|
const V4_EUPL = `## License\n\nEUPL-1.2`;
|
|
|
|
const FILES = [
|
|
// Variant 1 expected — full Apache block (12 JS files)
|
|
'src/routes/audit.routes.js',
|
|
'src/controllers/audit.controller.js',
|
|
'src/services/AdaptiveCommunicationOrchestrator.service.js',
|
|
'src/services/InstructionPersistenceClassifier.service.js',
|
|
'src/services/MetacognitiveVerifier.service.js',
|
|
'src/services/ContextPressureMonitor.service.js',
|
|
'src/services/BoundaryEnforcer.service.js',
|
|
'src/services/CrossReferenceValidator.service.js',
|
|
'src/services/PluralisticDeliberationOrchestrator.service.js',
|
|
'src/utils/attack-surface-validator.util.js',
|
|
'src/utils/activity-classifier.util.js',
|
|
'src/utils/audit-sanitizer.util.js',
|
|
// Variant 2 expected — inline JSDoc license lines (4 JS files)
|
|
'src/routes/calendar.routes.js',
|
|
'src/models/ScheduledTask.model.js',
|
|
'src/models/SyncMetadata.model.js',
|
|
'src/models/MissedBreach.model.js',
|
|
// Variant 3 expected — Python docstring (4 files)
|
|
'al-integration/testing/stress_test.py',
|
|
'al-integration/testing/stress_test_vllm.py',
|
|
'al-integration/training/train_analyzer.py',
|
|
'al-integration/agents/feedback_analyzer.py',
|
|
// Variant 4 expected — al-integration README (1 file)
|
|
'al-integration/README.md',
|
|
];
|
|
|
|
function processFile(relPath) {
|
|
const fullPath = path.join(REPO_ROOT, relPath);
|
|
if (!fs.existsSync(fullPath)) {
|
|
return { status: 'NOT_FOUND', variants: [] };
|
|
}
|
|
let content = fs.readFileSync(fullPath, 'utf8');
|
|
const original = content;
|
|
const variants = [];
|
|
|
|
if (content.includes(V1_APACHE)) {
|
|
content = content.replace(V1_APACHE, V1_EUPL);
|
|
variants.push('V1');
|
|
}
|
|
if (content.includes(V2_APACHE)) {
|
|
content = content.replace(V2_APACHE, V2_EUPL);
|
|
variants.push('V2');
|
|
}
|
|
if (content.includes(V3_APACHE)) {
|
|
content = content.replace(V3_APACHE, V3_EUPL);
|
|
variants.push('V3');
|
|
}
|
|
if (content.includes(V4_APACHE)) {
|
|
content = content.replace(V4_APACHE, V4_EUPL);
|
|
variants.push('V4');
|
|
}
|
|
|
|
if (content === original) {
|
|
return { status: 'NO_MATCH', variants: [] };
|
|
}
|
|
|
|
if (!DRY_RUN) {
|
|
fs.writeFileSync(fullPath, content, 'utf8');
|
|
}
|
|
return { status: 'CHANGED', variants };
|
|
}
|
|
|
|
const results = FILES.map((f) => ({ path: f, ...processFile(f) }));
|
|
|
|
console.log(`${DRY_RUN ? '[DRY RUN] ' : ''}Relicense Apache 2.0 → EUPL-1.2 — ${FILES.length} files in scope\n`);
|
|
|
|
const changed = results.filter((r) => r.status === 'CHANGED');
|
|
const noMatch = results.filter((r) => r.status === 'NO_MATCH');
|
|
const notFound = results.filter((r) => r.status === 'NOT_FOUND');
|
|
|
|
changed.forEach((r) => console.log(` CHANGED [${r.variants.join(',')}] ${r.path}`));
|
|
noMatch.forEach((r) => console.log(` NO_MATCH (check patterns) ${r.path}`));
|
|
notFound.forEach((r) => console.log(` NOT_FOUND ${r.path}`));
|
|
|
|
console.log(`\nSummary: ${changed.length} changed / ${noMatch.length} no-match / ${notFound.length} not-found (total ${FILES.length}).`);
|
|
if (DRY_RUN) {
|
|
console.log('\nDRY-RUN: no files written. Re-run without --dry-run to apply.');
|
|
}
|
|
|
|
process.exit(noMatch.length > 0 || notFound.length > 0 ? 1 : 0);
|