Repository navigation
lampOS: a product lamp runs every product skill as the skill: install puts six in, and its reminders and task news wait for their skills (LAMP_SCHEDULE_SPEAK=skill, LAMP_TASK_NEWS=skill) - #1667
Conversation
… puts six in, and its reminders and task news wait for their skills (LAMP_SCHEDULE_SPEAK=skill, LAMP_TASK_NEWS=skill)
|
Reviewer, 07:35, head
|
…'s wait for Task news from when it had the news (#1667 review)
|
First builder (agent), 08:11: new head
|
|
First builder, 08:29: a note on order with #1698 (core and installable skills, per-skill permissions). Its agent tested a local merge with #1667 at |
|
Reviewer, 08:30, head
|
|
First builder, 08:33: merged as |
The owner, 19 Oct: "do it all, no adhoc code, everything is a skill." Step 1: a customer's lamp runs every behaviour that has a skill as the skill. The product's install, the product units and the skills change here, plus one change to the voice: news now waits for its skill from when the voice had it (the review's P2, below). No built-in code is removed.
What a product lamp now runs
lamp-update installputs every product skill in/var/lib/lampOS/skills/, each folder whole but for itstests/(install::PRODUCT_SKILLS, written throughSETTINGSas Welcome back was):schedule/due, while the voice reststasks/statussettled, done or faileddancedocs/verification/dance-lamp-06c1-20261016)Left out, with why (
install::NOT_PRODUCT_SKILLS):LAMP_LOOK_FULL=onwithlamp-eyes --full-look), which the product doesn't run. Its look would be the 320-across working frame, which can't read a page. Its tool would also take the last free function (below).A new test fails when a folder in
lampOS/skills/is in neither list, so the next skill gets decided rather than left out without anyone seeing.The switches (product
lamp-voice.service)LAMP_SCHEDULE_SPEAK=on→skill. A due reminder waits up to 10 s for Reminders' ask (say = { from = "schedule" }). The voice still keeps the words and the acknowledgement, and says the reminder itself when no ask comes, so a reminder is never lost.LAMP_TASK_NEWSunset →skill. News of finished, stopped or asking work waits for Task news' ask (say = { from = "tasks" }, naming its task, lampOS: a skill's news ask may name its task and is given only that task's news (#1042's P2, voice side) #1237) until 10 s after the voice had it. After that the voice tells it itself. Progress news is the Policy's and is off in the product.LAMP_SPEAK_FIRSTstays commented out, andLAMP_HELLO_ASKS_POLICYis unset.Told once, not twice, not zero
The words stay the voice's. A
fromask is never said on its own (say::Says::takepasses it by). Only the voice's own reminder or news turn takes it (Says::take_from, matched by task), and that turn is said once:begunand moves and lights with the words.no skill asked for the … due within 10 s. This happens when lamp-skills is down, for stopped/asking news (which Task news doesn't take), and for news that settled while nobody was there.FROM_LIVES_US(20 s). Nothing is said and nothing moves. An ask is never taken for a later item.Pinned by
coordinator::tests::say::a_due_reminder_or_news_waits_for_a_skill_at_most_its_timeandnews_takes_only_an_ask_for_its_own_task. Before this PR, the skill installed without the switch would still have been told once, but the voice wouldn't have waited, so the sway or droop would mostly have missed the words.What a person will hear differently
schedule/dueis published every 1 s, and lamp-skills reads each of its topics within about 250 ms. That is worked out from the code, not measured on a lamp. A reminder due during a talk is said when the talk ends, with the look. It comes 10 s later than it could, with no look, if lamp-skills is down, or if the talk went on for over 20 s after a pause in which the skill asked.tell_togetheris skipped underskill, lampOS: with LAMP_TASK_NEWS_AT_PAUSE=on, tasks that finished together are told in one turn, at most three (#1161's P3) #1223). News that settled while nobody was there is told as soon as someone is back, at once, by the voice, with no sway (the skill's ask, made as the work settled, is gone after 20 s). Stopped or asking: told by the voice 10 s after it came in.These reach a product lamp at its next
lamp-update install; a round doesn't write units, settings or skills. lamp-4ace's own units are not changed here.Functions per session (the coordinator's 06:50 finding)
A session takes at most
lamp_gemini::MAX_TOOLS= 32.tools::declaredfills it in order (the voice's own, then the actions part's, then the skills') and drops what is past 32 with.take(room), without a word. Counted by each part's own code in the newcrates/update/tests/functions.rs:not_for_me,the_time, memory 3 + rules 3, tasks 3, faces 2). The child process gets only the product unit's environment and starts memory as the worker does.dance).Total 31 of 32: none left out, and 1 free. The test fails if any function of the actions part or of a product skill is missing, if the link leaves one out, or if the count isn't 31. With Desk tutor and its marks it would be 33:
danceandcheck_my_workfit, andshow_verdictwould be dropped without a word (the skills' tools are read in sorted folder order). Skills without a tool (five of the six) cost nothing.Proposed fixes (not done here;
MAX_TOOLSunchanged without evidence of the provider's limit):declaredleaves out. Its.take(room)is silent today; one journal line per session naming what was dropped, likeadmitted's "left out" line.light(action, colour?)(−6) and the volume's four into onevolume(action)(−3). That frees 9 without losing anything. The model's choice between them needs the light/volume battery re-run.MAX_TOOLS: Gemini Live with 33, 40 and 64 declarations on lamp-4ace, and the second route. Then raise it to what both take.skilldispatcher function for every tool skill, with the skill's name as an argument. This caps skills at one function, but the model has to pick a skill by name from one description, which needs its own check.Other built-in paths in the product voice unit
LAMP_AIR_FACTS=on(the voice's own air remark when spoken to): kept. Stuffy air never speaks, and its SKILL.md says the words are the voice's.LAMP_TASK_NEWS_AT_PAUSE=on: still the voice's gate for when news may be said. Withskill, its tell-together half no longer runs.alivecatalogue): no skill yet (skills.md, "Bedtime and Morning, later").Built-in code that becomes dead in the product once this ships
For the removal PR, after lamp-4ace has run these skills (5 of 5):
crates/voice/src/speak_up.rs:Arrival::hello,Arrival::speaks,Hello,Asking/ASK_ENVIRONMENT(LAMP_HELLO_ASKS_POLICY),SPEAK_ENVIRONMENT(LAMP_SPEAK_FIRST). Also the coordinator's hello block (hello_session, thelamp_speaks_firstwritten turn,hello_duerecords) and its use ofperson::hello_for.Arrivalitself stays: task news readspresent.crates/voice/src/coordinator.rsfor_skill: the!by_skillbranch (said at once with no ask) for both sources.crates/voice/src/reminders.rs:LAMP_SCHEDULE_SPEAK=onas a value of its own.crates/voice/src/task_news.rs:TaskNews::tell_together,TOGETHER_TASK_CHARS,TOGETHER_ANSWER_LEAST(andTOGETHER_MOSTif nothing else reads it). Also the coordinator'snews_at_pause && !news_by_skillbranch that calls it.for_skill'sSome(None)onceSKILL_WAITS_UShas passed) is what keeps a reminder from being lost while lamp-skills is down. That PR has to decide whether it stays.PRODUCT_SKILLS, or a file dropped from a skill folder, stays on every lamp installed before and keeps running; the new guard only checks a blank lamp. Taking a skill out is the removal work's:lamp-skills removeand the core and installable kinds are being built onfirst/skills-core-installable. It's written ininstall.mdtoo.Since the review (07:35, head
438be0ad8)[[while]] voice/state = restingandwait = "1h", as Stretch break does. A reminder due during a talk is kept until the talk ends and asked for at Schedule's next second, when the voice says it too. The skill's look comes with the words.skills/reminders/tests/due-during-a-talk-said-when-it-ends: a talk from 20 s to 60.5 s and a reminder due at 30 s give no call during the talk, then the look andsay from scheduleat 61 s ± 0.5 s.waitthe case gets 0 of its 2 calls; without thevoice/statecondition it calls at 30 s. Both fail.voice_state.jsonl(resting). Inquiet-while-schedule-cannot-serve-it, the chance kept while Schedule wasn't ready is now taken at 40 s with the look, where before the voice said it bare.wait: aneachtrigger refuses it (crates/skills/src/lib.rs, "each goes with when = appears, and with no … wait"). So "someone here" can't be expressed that way, and Task news uses the reviewer's first option instead.TaskNews::found_at, kept as each piece comes in, used through the coordinator'shold_frominnews_for_skill. Before, the 10 s started when the news could first be told. News held back past the skill's 20 s ask (nobody there, a long talk) is told at once when it can be, by the voice, without the sway. Within the 10 s, the skill's ask is taken as before.coordinator::tests::say::news_waits_for_its_skill_from_when_the_voice_had_it,news_first_in_line_waits_from_when_it_came_inandtask_news::tests::news_keeps_when_it_came_in_while_it_waits.hold_fromcall innews_for_skillfailsnews_first_in_line_waits_from_when_it_came_in; makinghold_froma no-op fails both coordinator tests.install.md,switches.md,skills.md,speaking-first.md,tasks.md,schedule.md, and the two skills'SKILL.mdandskill.toml.RuntimeDirectory,/run/lampos-skills) merges first. Once it's in, this PR's assert (--tools-dir /run/lampos-actions/skills,crates/update/tests/install.rs) moves to lampOS: lamp-skills keeps its tools in a folder of its own, which the voice reads, and makes it again if it goes (#705, lamp-4ace 19 Oct 04:33) #1656's--tools-dir /run/lampos-skills.tests/functions.rsthen points the child'sLAMP_SKILLS_DIRat its folder, where it now writes the skills'tools.jsonunder the actions folder. Not waited on for this push.install.mdand above as the removal work's job (lamp-skills remove,first/skills-core-installable); not built here.Also
skills/task-news/skill.tomlandSKILL.md: the "off on a lamp until tried / told twice" text now says how it runs in the product.lamp-update's dev-dependencies gainlamp-voice,lamp-actions,lamp-skillsandlamp-gemini, for the function count (Cargo.lock: lamp-update's list only).install.md(the 19 October paragraph, step 5, the parts table, "What was not shown"),skills.md(both tables' "Where it lives now" / "Replaces" for the hello, reminders and task news, the install paragraph, the function budget),switches.md(LAMP_SCHEDULE_SPEAK,LAMP_TASK_NEWS,LAMP_SAY; the census note onskillnever speaking marked fixed), andupdates.md(what install writes and a round doesn't).Gates
Run on the development Mac at head
5578a6e7e, in order, each exit code read:cargo fmt --all -- --check: exit 0cargo clippy --locked --workspace --all-targets -- -D warnings: exit 0cargo test --locked -p lamp-skills -p lamp-update -p lamp-voice -p lamp-voice-eval -- --test-threads=1: exit 0, 69 test binaries, 2,913 passed, 0 failed, 12 ignored. That is lamp-update 121 (1 ignored; tests/install.rs 48, tests/functions.rs 2, tests/round.rs 26), lamp-skills 88 (every_skill_folder_passes_its_own_recorded_testsamong them), and lamp-voice with lamp-voice-eval 2,704 (11 ignored; lamp-voice's lib 1,926, with the three new tests).438be0ad8, lamp-setup passed 66 (the voice's code didn't change then, and this push doesn't touch setup).lamp-skills test lampOS/skills/<skill>: Welcome back 6, Reminders 4 (with the new talk case), Task news 4, Stretch break 6 (1 has no recording yet), Stuffy air 9, Dance 5, so 34 for the product's six; Desk tutor 1 and its marks 2. All pass.cfg(target_os = "linux")code. The one struct with a new field,TaskNews, has every initializer intask_news.rs, none under a Linux cfg.The built-in code is removed in a follow-up after the skills are proven on lamp-4ace.