antcolony
All repositories: gitoria
3.1 KB
// registry.hl — project metadata, one JSON file per project (`<name>.json`), the model being the// antcolony repo's `projects/` folder on Byrodin (decided 2026-09-24, docs/scheduler-agent.md).// COLONY_PROJECTS_DIR points at the folder; default `projects/` beside scheduler.hl (a copy —// refresh it from Byrodin, README "Config").//// A project file: { name, dev: { host, folder }, concept, dependsOn: [..], code?, live?, deploy?, note?,// workers?, ui?, needs? }. Only what the rules need is checked: `name` = file name, `concept` a string (may be// empty = no concept yet), `dependsOn` a list of strings, `workers` a boolean when present// (`false` = the scheduler never starts a worker there, e.g. hybriel: AntColony only files issues).import { listDir } from 'hl:fs'import { env } from 'hl:proc'import { readJson, fromCwd, isList, isObject, isString, sortStrings } from './util.hl'static projectsDir = () => {let d = env('COLONY_PROJECTS_DIR')if (d == null || d == '') { return './projects' }return fromCwd(d)}// → { dir, projects: { name → meta }, names: [sorted], errors: [text] }static loadRegistry = () => {let dir = projectsDir()let out = { dir = dir projects = {} names = [] errors = [] }for (n of listDir(dir)) {let file = hlTypeName(n) == 'String' ? n : n.nameif (file.endsWith('.json')) {let r = readJson(dir + '/' + file)let name = file.slice(0, file.length - 5)if (r.error != null) {out.errors.push(r.error)} else if (!isObject(r.value)) {out.errors.push(file + ': not a JSON object')} else if (r.value.name != name) {out.errors.push(file + ": 'name' must be '" + name + "' (the file name)")} else {let m = r.valuelet deps = []if (m.dependsOn != null) {if (!isList(m.dependsOn)) { out.errors.push(file + ": 'dependsOn' must be a list") } else {for (d of m.dependsOn) { if (isString(d)) { deps.push(d) } else { out.errors.push(file + ": 'dependsOn' entries must be strings") } }}}m.deps = depsm.takesWorkers = trueif (m.workers != null) {if (hlTypeName(m.workers) != 'Boolean') { out.errors.push(file + ": 'workers' must be true or false") }else if (m.workers == false) { m.takesWorkers = false }}// antcolony#15: `"needs": ["chrome", "gpu"]` = capabilities the host's agent must announce before work starts herelet needs = []if (m.needs != null) {if (!isList(m.needs)) { out.errors.push(file + ": 'needs' must be a list") } else {for (x of m.needs) { if (isString(x) && x.trim() != '') { needs.push(x.trim().toLowerCase()) } else { out.errors.push(file + ": 'needs' entries must be non-empty strings") } }}}m.needList = needsm.hasConcept = isString(m.concept) && m.concept.trim() != ''// mission 029: `"ui": true` = an app with pages/styles → its briefs name the creator's layout conventionsm.hasUi = falseif (m.ui != null) {if (hlTypeName(m.ui) != 'Boolean') { out.errors.push(file + ": 'ui' must be true or false") }else if (m.ui == true) { m.hasUi = true }}out.projects[name] = mout.names.push(name)}}}sortStrings(out.names)return out}
Branches
- mainmain branch
Latest commits
- a6af7883tracker: worker box sees calendar.worldapi.org (login to copy)mre
- c613d26btemplates: bridges to external components (login.js for ident's selector) are allowed (creator 2026-09-27)mre
- 9062978ctracker: worker box sees /media/STORAGE/projects/old-tracker read-only (tracker#2 source data)mre
- 7f9660eeState of 2026-09-27, before the move to gitoriamre